Re[2]: Как создать объект раньше остальных?
От: Анатолий Широков СССР  
Дата: 28.08.07 17:30
Оценка: 6 (1) +1
Здравствуйте, Андрей Коростелев, Вы писали:

АК>Здравствуйте, slavo, Вы писали:


S>>День добрый, как гарантированно создать экземпляр класс CClass раньше, чем создастся экземпляр любого другого класса?


АК>Идиома Schwarz Counter позволяет обеспечить гарантированный порядок инициализации объектов со static storage duration.


Только там откровенный ляп:

class StreamInitializer {
  public:
    StreamInitializer ();
    ~StreamInitializer ();
} initializer; //Note object here in the header.


Объект initializer должен быть статическим, в противном случае линкер надает по рукам за множественное определение одного и того же объекта в разных единицах трансляции. Исправляем:

static class StreamInitializer {
  public:
    StreamInitializer ();
    ~StreamInitializer ();
} initializer; //Note object here in the header.
Re[6]: Как создать объект раньше остальных?
От: slavo  
Дата: 29.08.07 06:12
Оценка:
Здравствуйте, alzt, Вы писали:

A>Здравствуйте, slavo, Вы писали:


S>>singleton проблему решает, просто не хотелось постоянно дергать GetInstance. Но видно, никуда не деться. Сделал singleton.


A>А каким образом он решает проблему? Можно пример кода?


Наверное изначально я неправильно вопрос поставил. Нужно либо обеспечить создание объекта раньше какого-либо другого, либо обеспечить его существование при первом обращении к определенному набору функций. Singleton это решает, хотя и не совсем так, как хотелось. То, что я написал тоже не совсем похоже на singleton.

bool CCore::DoCreate()
{
    static CCriticalSection CS;
    static bool fCreated = InitializeStaticCriticalSection(&CS);

    CS.Lock();

    if(!fCreated)
    {
        fCreated = true; // To prevent subsequent attempts to create.

        if(!Create())
        {
            CS.Unlock();
            return false;
        }
    }

    CS.Unlock();

    return true;
}
Re: Как создать объект раньше остальных?
От: rg45 СССР  
Дата: 29.08.07 06:18
Оценка:
Здравствуйте, slavo, Вы писали:

S>День добрый, как гарантированно создать экземпляр класс CClass раньше, чем создастся экземпляр любого другого класса?


Есть способ — полностью отказаться от использования статических переменных, в т.ч. синглтонов, и управлять временем жизни объектов явно.
... << RSDN@Home 1.1.4 stable SR1 rev. 568>>
--
Не можешь достичь желаемого — пожелай достигнутого.
Re[2]: Как создать объект раньше остальных?
От: rg45 СССР  
Дата: 29.08.07 06:31
Оценка: 4 (1)
Здравствуйте, rg45, Вы писали:

R>Здравствуйте, slavo, Вы писали:


S>>День добрый, как гарантированно создать экземпляр класс CClass раньше, чем создастся экземпляр любого другого класса?


R>Есть способ — полностью отказаться от использования статических переменных, в т.ч. синглтонов, и управлять временем жизни объектов явно.


Самый простой рецепт — собери все статические переменные и сделай их членами (НЕстатическими) одного класса. Часто такой класс называют Application или что-то в этом роде. Инициализироваться эти переменные будут строго в той последовательности, в которой они объявлены в классе. Экземпляр самого Application создается в основной функции приложения — в куче с помошью оператора new, или же прямо на стеке.
... << RSDN@Home 1.1.4 stable SR1 rev. 568>>
--
Не можешь достичь желаемого — пожелай достигнутого.
Re: Как создать объект раньше остальных?
От: Erop Россия  
Дата: 29.08.07 06:41
Оценка:
Здравствуйте, slavo, Вы писали:

S>День добрый, как гарантированно создать экземпляр класс CClass раньше, чем создастся экземпляр любого другого класса?


1) Лучше бы так не делать вообще, так как трудно отлаживать и поддерживать. Если ты хочешь пользоваться своимм объектом из каких-то функций, которые могут быть вызваны слишком рано, то я бы советовал просто проверять в этих функциях, что объект уже инициализирован.

2) Если совсем никак не избежать (что сомнительно), то озвучь компилятор. У всех популярных компиляторов есть всякие непереносимые способы (например через специальные #pargma) указать, что этот объект надо создавать до остальных...
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
Re[3]: Как создать объект раньше остальных?
От: slavo  
Дата: 29.08.07 06:48
Оценка:
Здравствуйте, rg45, Вы писали:

R>Здравствуйте, rg45, Вы писали:


R>>Здравствуйте, slavo, Вы писали:


S>>>День добрый, как гарантированно создать экземпляр класс CClass раньше, чем создастся экземпляр любого другого класса?


R>>Есть способ — полностью отказаться от использования статических переменных, в т.ч. синглтонов, и управлять временем жизни объектов явно.


R>Самый простой рецепт — собери все статические переменные и сделай их членами (НЕстатическими) одного класса. Часто такой класс называют Application или что-то в этом роде. Инициализироваться эти переменные будут строго в той последовательности, в которой они объявлены в классе. Экземпляр самого Application создается в основной функции приложения — в куче с помошью оператора new, или же прямо на стеке.


Проблема в том, что я не могу трогать архитектуру. Надо работать с тем, что есть.
Re[2]: Как создать объект раньше остальных?
От: slavo  
Дата: 29.08.07 06:52
Оценка:
Здравствуйте, Erop, Вы писали:

E>Здравствуйте, slavo, Вы писали:


S>>День добрый, как гарантированно создать экземпляр класс CClass раньше, чем создастся экземпляр любого другого класса?


E>1) Лучше бы так не делать вообще, так как трудно отлаживать и поддерживать. Если ты хочешь пользоваться своимм объектом из каких-то функций, которые могут быть вызваны слишком рано, то я бы советовал просто проверять в этих функциях, что объект уже инициализирован.


Вот так я и сделал.

E>2) Если совсем никак не избежать (что сомнительно), то озвучь компилятор. У всех популярных компиляторов есть всякие непереносимые способы (например через специальные #pargma) указать, что этот объект надо создавать до остальных...


Это нельзя. Проект должен компиляться как минимум на MSVS6.0 и с помощью последней версии g++.
Re[4]: Как создать объект раньше остальных?
От: rg45 СССР  
Дата: 29.08.07 07:18
Оценка: 4 (1) -1
Здравствуйте, slavo, Вы писали:

S>Здравствуйте, rg45, Вы писали:


R>>Здравствуйте, rg45, Вы писали:


R>>>Здравствуйте, slavo, Вы писали:


S>>>>День добрый, как гарантированно создать экземпляр класс CClass раньше, чем создастся экземпляр любого другого класса?


R>>>Есть способ — полностью отказаться от использования статических переменных, в т.ч. синглтонов, и управлять временем жизни объектов явно.


R>>Самый простой рецепт — собери все статические переменные и сделай их членами (НЕстатическими) одного класса. Часто такой класс называют Application или что-то в этом роде. Инициализироваться эти переменные будут строго в той последовательности, в которой они объявлены в классе. Экземпляр самого Application создается в основной функции приложения — в куче с помошью оператора new, или же прямо на стеке.


S>Проблема в том, что я не могу трогать архитектуру. Надо работать с тем, что есть.


Плохо дело. Тогда могу предложить такой прием, может пригодится. Допустим есть две статические переменные, определенные в разных единицах трансляции. Пусть вторая переменная является зависимой от первой — т.е. при инициализации второй переменной используется первая. Например:
//Module1.cpp
static std::string folder = "..\\DATA";

//Module2.cpp
static std::string path = folder + "\\log.txt";


Порядок инициализации статических переменных, определенных в разных единицах трансляции неопределен. Нам же необходимо, чтобы переменная folder проинициализировалась раньше переменной path. Сделать это можно, если определения статических переменных спрятать внутри функций:
//Module1.cpp
std::string& folder()
{
    static std::string value = "..\\DATA";
    return value;
} 

//Module2.cpp
std::string& path()
{
    static value = folder() + "\\log.txt";
    return value;
}


В данном примере статические переменные не были константами, поэтому функции возвращают ссылки на статические переменные, доступные таким образом для модификации. Это иллюстрирует адекватность замены статических переменных функциями, плюс детерминированный порядок инициализации.
... << RSDN@Home 1.1.4 stable SR1 rev. 568>>
--
Не можешь достичь желаемого — пожелай достигнутого.
Re[3]: Как создать объект раньше остальных?
От: Андрей Коростелев Голландия http://www.korostelev.net/
Дата: 29.08.07 07:21
Оценка:
Здравствуйте, Анатолий Широков, Вы писали:

АШ>Здравствуйте, Андрей Коростелев, Вы писали:


АК>>Идиома Schwarz Counter позволяет обеспечить гарантированный порядок инициализации объектов со static storage duration.


АШ>Только там откровенный ляп:

АШ>
static StreamInitializer {
...


Я поправил.
-- Андрей
Re[7]: Пара вопросов про синглетон
От: Erop Россия  
Дата: 29.08.07 09:11
Оценка:
Здравствуйте, slavo, Вы писали:

S>Наверное изначально я неправильно вопрос поставил. Нужно либо обеспечить создание объекта раньше какого-либо другого, либо обеспечить его существование при первом обращении к определенному набору функций. Singleton это решает, хотя и не совсем так, как хотелось. То, что я написал тоже не совсем похоже на singleton.


1) А какая система у тебя? Я так понимаю, что бычно инициализация статических переменных происходит ещё до многопоточности. Поэтому ты скорее всего можешь выбросить из своего синглетона синхронизацию. Для этого достаточно где-то написать
const bool isCoreCreated = CCore::DoCreate();


2) Я так понимаю, что у тебя очень много статических объектов (иначе откуда возьмутся столь ранние вызовы твоих функций). Тогда наверное у тебя постепенно возниктнет много таких синглетонов. Соответсвенно порядок их инициализации, а возможно и её результат, станет трудноуправляемым и малопредсказуемым. Оно тебе надо?
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
Re[5]: Как создать объект раньше остальных?
От: Erop Россия  
Дата: 29.08.07 09:15
Оценка:
Здравствуйте, rg45, Вы писали:

R>>>>Есть способ — полностью отказаться от использования статических переменных, в т.ч. синглтонов, и управлять временем жизни объектов явно.


R>
R>//Module1.cpp
R>std::string& folder()
R>{
R>    static std::string value = "..\\DATA";
R>    return value;
R>} 

R>//Module2.cpp
R>std::string& path()
R>{
R>    static value = folder() + "\\log.txt";
R>    return value;
R>}
R>


R>...плюс детерминированный порядок инициализации.

Нифига он не детерминированный
Кроме того есть ещё и порядок разрушения...
Почему бы действительно ен управлять этим делом явно? Ведь в компиляторах обычно есть для этого средства!!!
Один фиг хорошее решение -- вообще избавится от зависимостей такого рода, не доступно... От чего бы не попросить компилятор о том, что тебе требуется прямо, а не через хаки какие-то?
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
Re[3]: Как создать объект раньше остальных?
От: Erop Россия  
Дата: 29.08.07 09:18
Оценка:
Здравствуйте, slavo, Вы писали:

E>>1) Лучше бы так не делать вообще, так как трудно отлаживать и поддерживать. Если ты хочешь пользоваться своимм объектом из каких-то функций, которые могут быть вызваны слишком рано, то я бы советовал просто проверять в этих функциях, что объект уже инициализирован.


S>Вот так я и сделал.

Насколько я понял, ты сделал не так.

E>>2) Если совсем никак не избежать (что сомнительно), то озвучь компилятор. У всех популярных компиляторов есть всякие непереносимые способы (например через специальные #pargma) указать, что этот объект надо создавать до остальных...


S>Это нельзя. Проект должен компиляться как минимум на MSVS6.0 и с помощью последней версии g++.

Ну и там и там таки есредства есть.
в одном нужно указать правильную секцию кода, а в другом приоритет создания.
Немного пошаманить с условной компиляцией и всё получится.
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
Re[4]: #pragma init_seg
От: Erop Россия  
Дата: 29.08.07 09:22
Оценка:
Здравствуйте, Erop, Вы писали:

E>Немного пошаманить с условной компиляцией и всё получится.

В VC 6 это кажется называлось #pragma init_seg, или непосредственно надо было писать через #pragma comment( linker )
Про gcc сейчас не помню. Вспомню -- напишу, хотя может ещё кто помнит. Там можно было задавать приоритет создания объекта.
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
Re[8]: Пара вопросов про синглетон
От: slavo  
Дата: 29.08.07 09:57
Оценка:
Здравствуйте, Erop, Вы писали:

E>Здравствуйте, slavo, Вы писали:


S>>Наверное изначально я неправильно вопрос поставил. Нужно либо обеспечить создание объекта раньше какого-либо другого, либо обеспечить его существование при первом обращении к определенному набору функций. Singleton это решает, хотя и не совсем так, как хотелось. То, что я написал тоже не совсем похоже на singleton.


E>1) А какая система у тебя? Я так понимаю, что бычно инициализация статических переменных происходит ещё до многопоточности. Поэтому ты скорее всего можешь выбросить из своего синглетона синхронизацию. Для этого достаточно где-то написать
const bool isCoreCreated = CCore::DoCreate();


Почему до многопоточности? Если у меня где-то есть объект А, который запускает поток, то разве это означает, что все статические объекты уже созданы? Нет. Я это проверил. Поэтому синхронизацию выбросить не получится.

E>2) Я так понимаю, что у тебя очень много статических объектов (иначе откуда возьмутся столь ранние вызовы твоих функций). Тогда наверное у тебя постепенно возниктнет много таких синглетонов. Соответсвенно порядок их инициализации, а возможно и её результат, станет трудноуправляемым и малопредсказуемым. Оно тебе надо?


Статических объектов тут много, но порядок их создания уже отлажен и проблем не возникает, поэтому они не будут переделываться на синглетоны. Если понадобится еще один такой объект (который мне нужен) и они оба захотят создаваться раньше друг друга, то тут и настанет конец мира .
Re[5]: #pragma init_seg
От: slavo  
Дата: 29.08.07 10:02
Оценка:
Здравствуйте, Erop, Вы писали:

E>Здравствуйте, Erop, Вы писали:


E>>Немного пошаманить с условной компиляцией и всё получится.

E>В VC 6 это кажется называлось #pragma init_seg, или непосредственно надо было писать через #pragma comment( linker )
E>Про gcc сейчас не помню. Вспомню -- напишу, хотя может ещё кто помнит. Там можно было задавать приоритет создания объекта.

Информация полезная, но не хотелось бы привязывать проект (и без того мутный) к таким тонкостям .
Re: Как создать объект раньше остальных?
От: MasterZiv СССР  
Дата: 29.08.07 10:06
Оценка:
slavo пишет:
> День добрый, как гарантированно создать экземпляр класс CClass раньше,
> чем создастся экземпляр любого другого класса?
> Как создать объект раньше остальных? <message/2636970.aspx> Оценить

В общем-то, если кратко — никак.
Posted via RSDN NNTP Server 2.1 beta
Re[6]: Как создать объект раньше остальных?
От: remark Россия http://www.1024cores.net/
Дата: 29.08.07 10:23
Оценка:
Здравствуйте, Кодт, Вы писали:

K>>>>>заюзать singleton.

S>>>>а если не юзать singleton?
А>>>А аргументы против этого метода имеются?

S>>Возможно будет медленнее работать из-за потерь на вход в критическую секцию и проверку флага создания.


К>А это уже измышления вокруг конкретной реализации конкретной разновидности синглетона.


Смотрите, пожалуйста, здесь:
[Trick] Упгрейд для синглтона
Автор: remark
Дата: 29.08.07



1024cores &mdash; all about multithreading, multicore, concurrency, parallelism, lock-free algorithms
Re[7]: Как создать объект раньше остальных?
От: Кодт Россия  
Дата: 29.08.07 10:49
Оценка:
Здравствуйте, slavo, Вы писали:

Можно записать проще:
S>
S>bool CCore::DoCreate()
S>{
    static long fCreated = 0;
    if( !fCreated ) // первая проверка - дешёвая (и плевать на гонки)
        if( !atomic_test_and_set(&fCreate,0,1) ) // вторая - строгая
            Create();
S>}
S>

Тем более, что в исходном коде у тебя
— гонки при инициализации критической секции
— нет кода деинициализации этой секции

Функцию atomic_test_and_set — выбери соответствующую из WinAPI, pthreads или кроссплатформенных библиотек.
(В WinAPI это InterlockedTestExchange)

А вот интересный вопрос: это предполагалось использовать в таком контексте?
class CCore
{
public:
    CCore()
    {
        DoCreate();
    }
};

CCore& core()
{
    static CCore obj;
    return obj;
}

Если да — то выкинь идею к чёрту.
Получится, что в условиях гонок объект конструируется дважды: один раз по полному пути, другой раз по сокращённому (члены конструируются, а тело — нет).
... << RSDN@Home 1.2.0 alpha rev. 655>>
Перекуём баги на фичи!
Re[4]: Как создать объект раньше остальных?
От: Jonathan  
Дата: 29.08.07 11:56
Оценка:
Здравствуйте.
Я не понимаю одну вещь
Как эта идиома позволяет обеспечить гарантированный порядок инициализации объектов со static storage duration в таком случае:

У меня есть class A:

// ----------- A.h ---------------
class A
{
public:
A(){};
~A();
}

// ---------- A.cpp --------------
#include "stream.h"

A::~A()
{
// work with stream
}

и функция main:

#include "A.h"

A a;

int main()
{
return 0;
}

Почему я могу быть уверен, что объект 'a' будет создан до Stream и разрушен после?

Спс.
"If everything seems under control, you're just not going fast enough"
Re[6]: Как создать объект раньше остальных?
От: rg45 СССР  
Дата: 29.08.07 12:46
Оценка:
Здравствуйте, Erop, Вы писали:

E>Здравствуйте, rg45, Вы писали:


R>>...плюс детерминированный порядок инициализации.

E>Нифига он не детерминированный
Время жизни статической переменной, объявленной внутри функции начинается при первом вызове функции — это по стандарту. Поэтому порядок инициализации, все-таки, детерминированный.

E>Кроме того есть ещё и порядок разрушения...

Если к этим переменным нет обращения в период разрушения статики (а мне думается, что в данном случае так и есть, пусть автор вопроса поправит, если я ошибаюсь), то неопределенность порядка разрушения не имеет никакого значения.

E>Почему бы действительно ен управлять этим делом явно? Ведь в компиляторах обычно есть для этого средства!!!

E>Один фиг хорошее решение -- вообще избавится от зависимостей такого рода, не доступно... От чего бы не попросить компилятор о том, что тебе требуется прямо, а не через хаки какие-то?

Ну это у автора вопроса надо спрашивать, согласен ли он на зависимость от фич отдельных компиляторов.
... << RSDN@Home 1.1.4 stable SR1 rev. 568>>
--
Не можешь достичь желаемого — пожелай достигнутого.
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.