Понадобился мне тут сабж... в boost'е ничего подобного, к моему глубочайшему удивлению, не обнаружилось; гуглевание по словам "C++ singleton thread safe" выдало лишь массу ссылок на "общие слова", по прочтении которых наваялось вот такое:
class MyOneAndOnly: public Singleton<MyOneAndOnly> { ... };
MyOneAndOnly::GetObject().some_method();
Теперь собственно проблемы/вопросы:
Обращение к методам MyOneAndOnly потенциально возможно из конструкторов/деструкторов глобальных объектов (почему pObject и создается в куче). С первыи проблем, как я понимаю не возникнет, так как при первом же общении произойдет вызов new _Class_t. А вот деструкторами все хуже, потому как никаких гарантий, что уже не был разрушен Locker, у меня нет. Это можно как-то преодолеть?
Очевидно, что когда-то нужно вызвать delete pObject — но как это сделать "безопасно" (то есть, с гарантией, что все глобальные объекты уже разрушены)? Копать в сторону atexit()?
[]
SDB>MyOneAndOnly::GetObject().some_method(); SDB>[/ccode] SDB>Теперь собственно проблемы/вопросы:
SDB> SDB>Обращение к методам MyOneAndOnly потенциально возможно из конструкторов/деструкторов глобальных объектов (почему pObject и создается в куче). С первыи проблем, как я понимаю не возникнет, так как при первом же общении произойдет вызов new _Class_t. А вот деструкторами все хуже, потому как никаких гарантий, что уже не был разрушен Locker, у меня нет. Это можно как-то преодолеть?
SDB>Очевидно, что когда-то нужно вызвать delete pObject — но как это сделать "безопасно" (то есть, с гарантией, что все глобальные объекты уже разрушены)? Копать в сторону atexit()?
SDB>Я правильно понимаю, что реализовать singleton для класса, который не имеет конструктора по умолчанию, невозможно? SDB>
SDB>P.S. SDB>В ожидании ответов пошел читать Паттерн Singleton (Одиночка). Примеры использования
1) Зачем писать свой Locker, когда есть ATL::CComAutoCriticalSection, ATL::CComCritSecLock? Или нет возможности их юзать?
2) Зачем у Locker'а private конструктор? Класс же и так private? Из-за этого тебе пришлось тянуть friend. Сделай конструктор/десруктор public
3) Есть идея создавать CS в куче и вообще не удалять ни твой объект, ни CS. При грохе процесса все почистится. Но это зависит от "сложности" деструктора MyOneAndOnly
4) Может все-таки Loki + напильник?
Здравствуйте, Константин Л., Вы писали:
КЛ>Почему Loki не воспринимаешь?
Сложно сказать... для меня это больше "академический эксперимент" по проверке и демонстрации возможностей C++ и каких-то концепций, чем "боевой" продукт.
КЛ>1) Зачем писать свой Locker, когда есть ATL::CComAutoCriticalSection, ATL::CComCritSecLock? Или нет возможности их юзать?
Нет, нужна максимальная независимость от любых библиотек (исключая STL).
КЛ>2) Зачем у Locker'а private конструктор? Класс же и так private? Из-за этого тебе пришлось тянуть friend. Сделай конструктор/десруктор public
Согласен.
КЛ>3) Есть идея создавать CS в куче и вообще не удалять ни твой объект, ни CS. При грохе процесса все почистится.
За такой подход у нас на работе рихтуют напильником... сначала руки, потом — голову. И очень правильно ИМХО делают.
КЛ>Но это зависит от "сложности" деструктора MyOneAndOnly
Вот именно.
КЛ>4) Может все-таки Loki + напильник?
Нет уж, увольте. Я тут нагугли-таки пару полезных ссылочек по теме со вполне читабельным кодом:
Здравствуйте, SchweinDeBurg, Вы писали:
SDB>Здравствуйте, Константин Л., Вы писали:
КЛ>>Почему Loki не воспринимаешь?
SDB>Сложно сказать... для меня это больше "академический эксперимент" по проверке и демонстрации возможностей C++ и каких-то концепций, чем "боевой" продукт.
КЛ>>1) Зачем писать свой Locker, когда есть ATL::CComAutoCriticalSection, ATL::CComCritSecLock? Или нет возможности их юзать?
SDB>Нет, нужна максимальная независимость от любых библиотек (исключая STL).
КЛ>>2) Зачем у Locker'а private конструктор? Класс же и так private? Из-за этого тебе пришлось тянуть friend. Сделай конструктор/десруктор public
SDB>Согласен.
КЛ>>3) Есть идея создавать CS в куче и вообще не удалять ни твой объект, ни CS. При грохе процесса все почистится.
SDB>За такой подход у нас на работе рихтуют напильником... сначала руки, потом — голову. И очень правильно ИМХО делают.
ИМХО тоже, просто предложил как один из "возможных" вариантов
КЛ>>Но это зависит от "сложности" деструктора MyOneAndOnly
SDB>Вот именно.
КЛ>>4) Может все-таки Loki + напильник?
SDB>Нет уж, увольте. Я тут нагугли-таки пару полезных ссылочек по теме со вполне читабельным кодом:
SDB>Singleton.h
Есть сомнения по поводу необходимости наследования от SingletonBase. Этот класс является аналогом boost::noncopyable и ничего не дает кроме невозможности копирования.
Здравствуйте, SchweinDeBurg, Вы писали:
SDB>Понадобился мне тут сабж... в boost'е ничего подобного, к моему глубочайшему удивлению, не обнаружилось;
в boost'е есть синглтон — но в виде детали реализации библиотеки pool — boost\pool\detail\singleton.hpp
идея потокобезопасности проста и эффективна — используется синглтон Майерса + instance() первый раз вызывается в конструкторе глобальной переменной, это происходит до входа в main и, следовательно, потокобезопасно.
код примерно такой
template<class T> class singleton : public T
{
private:
...
struct creator
{
creator()
{
singleton<T>::instance();
}
}
static creator s_singleton_creator;
public:
static T& instance()
{
static T inst;
return inst;
}
};
template<class T> typename singleton<T>::creator singleton<T>::s_singleton_creator;
Здравствуйте, Константин Л., Вы писали:
КЛ>ИМХО тоже, просто предложил как один из "возможных" вариантов
Для меня он не возможен, даже в кавычках.
КЛ>Есть сомнения по поводу необходимости наследования от SingletonBase. Этот класс является аналогом boost::noncopyable и ничего не дает кроме невозможности копирования.
Угу.
КЛ>Так что необходимость наследования от него считаю лишней
Ну, это уже частности... при наличии рашпиля.
[ posted via RSDN@Home 1.1.4 stable SR1 r568, accompanied by silence ]
Здравствуйте, Ivan, Вы писали:
I>в boost'е есть синглтон — но в виде детали реализации библиотеки pool — boost\pool\detail\singleton.hpp I>идея потокобезопасности проста и эффективна — используется синглтон Майерса + instance() первый раз вызывается в конструкторе глобальной переменной, это происходит до входа в main и, следовательно, потокобезопасно.
Засмотрел. Все бы хорошо, но:
1.
// The following helper classes are placeholders for a generic "singleton"
// class. The classes below support usage of singletons, including use in
// program startup/shutdown code, AS LONG AS there is only one thread
// running before main() begins, and only one thread running after main()
// exits.
Будучи параноиком, выделенным смущен.
2.
// Furthermore, since the instance() function contains the object, instead
// of the singleton_default class containing a static instance of the
// object, that object is guaranteed to be constructed (at the latest) in
// the first call to instance(). This permits calls to instance() from
// static code, even if that code is called before the file-scope objects
// in this file have been initialized.
Увы, но разрушение такого синглетона после всех глобальных объектов, которые им пользовались, не гарантируется.
Здравствуйте, SchweinDeBurg, Вы писали:
SDB>Доброго времени суток всем нам!
SDB>Понадобился мне тут сабж... в boost'е ничего подобного, к моему глубочайшему удивлению, не обнаружилось; гуглевание по словам "C++ singleton thread safe" выдало лишь массу ссылок на "общие слова", по прочтении которых наваялось вот такое:
Так на RSDN же и была интересная тема thread safe singlton — возможно ли такое в принципе
Здравствуйте, SchweinDeBurg, Вы писали:
SDB>Доброго времени суток всем нам!
SDB>Понадобился мне тут сабж... в boost'е ничего подобного, к моему глубочайшему удивлению, не обнаружилось; гуглевание по словам "C++ singleton thread safe" выдало лишь массу ссылок на "общие слова", по прочтении которых наваялось вот такое:
Ну, вот так всегда: спросишь что-нибудь на RSDN — пошлют в Гугль, а если первым делом скажешь, что в Гугле уже был — "а чего ты на RSDN не посмотрел?.."
Спасибо, Вит, занес ссылку в избранное, почитаю на досуге.
[ posted via RSDN@Home 1.1.4 stable SR1 r568, accompanied by silence ]
Здравствуйте, SchweinDeBurg, Вы писали:
SDB>Здравствуйте, DigitalGuru, Вы писали:
DG>>Конечно! У Александреску именно так и написано
SDB>"Great minds think alike..." Но код из Context Singletons — context-specific shared objects in C++ читается значительно приятнее.
Full disclosure: phoenix is based partly on MC++D's code. In particular, i've stolen Andrei's trick of matching atexit(), manual dtor invokation and the placement new operator .
Еще позабавило имя переменной "myers" .
А что касается реализации Singlton'а, то, мне лично, приятнее вот это:
class my_singleton_t {
...
};
extern my_singleton_t my_singleton;
Re[3]: Потоко-бесопасный синглетон
От:
Аноним
Дата:
24.05.06 10:36
Оценка:
Здравствуйте, SchweinDeBurg, Вы писали:
SDB>Здравствуйте, Ivan, Вы писали:
[snip]
SDB>1. SDB>
SDB>// The following helper classes are placeholders for a generic "singleton"
SDB>// class. The classes below support usage of singletons, including use in
SDB>// program startup/shutdown code, AS LONG AS there is only one thread
SDB>// running before main() begins, and only one thread running after main()
SDB>// exits.
SDB>Будучи параноиком, выделенным смущен.
А у вас часто создаются нити до входа в main? Правда, очень интересно где это может понадобиться.
[snip]
SDB>Увы, но разрушение такого синглетона после всех глобальных объектов, которые им пользовались, не гарантируется.
Здравствуйте, <Аноним>, Вы писали:
SDB>>Будучи параноиком, выделенным смущен. А>А у вас часто создаются нити до входа в main? Правда, очень интересно где это может понадобиться.
См. выделенное. Мне крайне не хочется копаться в исходниках CRT очередного компилятора, чтобы убедиться, что до входа в main() мы имеем ровно один поток.
А>здесь
Здравствуйте, SchweinDeBurg, Вы писали:
SDB>Засмотрел. Все бы хорошо, но:
SDB>1. SDB>
SDB>// AS LONG AS there is only one thread
SDB>// running before main() begins, and only one thread running after main()
SDB>// exits.
если речь идет о Dll модуле, то вызов DllMain происходит внутри спецальной секции LoaderLock и создание других потоков в этот момент будет приостановлено до завершения работы DllMain. В exe модуле технически завести несколько потоков можно — в конструктторах глобальных переменных, но я с таким не встречался.
если представить, что кто-то создает потоки в конструкторах глобальных переменных, то в это время еще не завершилась инициализация CRT в главном потоке — это может создать проблемы при инициализации CRT в порожденных потоках. и второй момент — при обращении из этих потоков к глобальным переменным — можно получить доступ к переменным, которые еще не успели сконструироваться в главном потоке.
SDB>Увы, но разрушение такого синглетона после всех глобальных объектов, которые им пользовались, не гарантируется.
да, здесь похоже по стандарту UB при обращении после его разрушения, на практике для Visual C++ — он 'возродится'
Здравствуйте, SchweinDeBurg, Вы писали:
SDB>Ну, вот так всегда: спросишь что-нибудь на RSDN — пошлют в Гугль, а если первым делом скажешь, что в Гугле уже был — "а чего ты на RSDN не посмотрел?.."
Хочешь я тебе тулзу дам, которая ищет одновременно и там, и там, объединяя результаты вместе? Только я её пока в гугль-группах и на codeproject искать не научил, но это в планах есть...
SDB>Спасибо, Вит, занес ссылку в избранное, почитаю на досуге.
Смущает пара моментов, вроде в ветке не упоминались: SDB>
SDB> static Locker m_objectLocker; // 1) инициализируется в runtime - обращение
// к GetObject из других единиц трансляции
// может обломиться
SDB>template <class _Class_t>
SDB>_Class_t& Singleton<_Class_t>::GetObject(void)
SDB>{
SDB> m_objectLocker.Enter();
SDB> static _Class_t* pObject;
SDB> if (pObject == NULL)
SDB> {
SDB> pObject = new _Class_t();// 2) маловероятно, но может бросить исключение,
SDB> }
SDB> m_objectLocker.Leave(); // ...и сюда мы не попадаем
SDB> return (*pObject);
SDB>}
SDB>
SDB>Теперь собственно проблемы/вопросы:
SDB>[list=1] SDB>Обращение к методам MyOneAndOnly потенциально возможно из конструкторов/деструкторов глобальных объектов (почему pObject и создается в куче). С первыи проблем, как я понимаю не возникнет,
См. 1), могут возникнуть.