Я создал все синглтоны в своей программе с учетом этого документа: http://erdani.com/publications/DDJ_Jul_Aug_2004_revised.pdf (если кому-то интересно, почему синглтон, все они являются фабриками, и некоторые из них хранят некоторые глобальные настройки, касающиеся того, как они должны создавать экземпляры).
Каждый из них выглядит примерно так:
декларация:
class SingletonAndFactory {
static SingletonAndFactory* volatile instance;
public:
static SingletonAndFactory& getInstance();
private:
SingletonAndFactory();
SingletonAndFactory(
const SingletonAndFactory& ingletonFactory
);
~SingletonAndFactory();
};
определение:
boost::mutex singletonAndFactoryMutex;
////////////////////////////////////////////////////////////////////////////////
// class SingletonAndFactory {
SingletonAndFactory* volatile singletonAndFactory::instance = 0;
// public:
SingletonAndFactory& SingletonAndFactory::getInstance() {
// Singleton implemented according to:
// "C++ and the Perils of Double-Checked Locking".
if (!instance) {
boost::mutex::scoped_lock lock(SingletonAndFactoryMutex);
if (!instance) {
SingletonAndFactory* volatile tmp = (SingletonAndFactory*) malloc(sizeof(SingletonAndFactory));
new (tmp) SingletonAndFactory; // placement new
instance = tmp;
}
}
return *instance;
}
// private:
SingletonAndFactory::SingletonAndFactory() {}
// };
Оставив в стороне вопрос какой дизайн синглтона лучше (поскольку это приведет к бессмысленной флеймовой войне), мой вопрос: принесет ли мне пользу замена обычного указателя на std::unique_ptr? В частности, вызовет ли он деструктор синглтона при выходе из программы? Если да, то как бы я этого добился? Когда я попытался добавить что-то вроде friend class std::unique_ptr<SingletonAndFactory>;
, это не сработало, поскольку компилятор продолжает жаловаться, что деструктор является закрытым.
Я знаю, что это не имеет значения в моем текущем проекте, поскольку ни на одной из фабрик нет чего-то, что требовало бы какой-либо очистки, но для дальнейшего использования я хотел бы знать, как реализовать такое поведение.
Thing& getThing() { static Thing thing; return thing; }
Забудьте о блокировках, забудьте об одиночках. - person R. Martinho Fernandes   schedule 09.10.2013malloc
+ место размещения новое? О, давай... - person R. Martinho Fernandes   schedule 09.10.2013volatile
. C++11 не присваиваетvolatile
семантики, связанной с потоком. - person R. Martinho Fernandes   schedule 09.10.2013volatile
был скопирован из примера в связанном документе, описывающего, какvolatile
недостаточно для обеспечения безопасности потоков. Вам нужен C++11, чтобы обеспечить необходимые гарантии атомарности; и как только у вас есть С++ 11, вы можете также использовать локальную статику. - person Mike Seymour   schedule 09.10.2013instance = new Thing;
, и ваша чепуха включают в себя одно присваиваниеinstance
и, следовательно, так же безопасны (или, в данном случае, небезопасны), как и друг друга. - person Mike Seymour   schedule 09.10.2013-std=C++11 -Wall -Wextra -pedantic
и, например. изменил BOOST_FOREACH на C++11 для. Тело getInstance было написано, когда я буквально начинал свое приключение с C++, имея в основном опыт работы с Java SE. Потребовалось несколько недель кодирования и чтения, чтобы понять некоторые вещи. Поэтому недавно я переписываю некоторые части своего кода, чтобы сделать их лучше. Я также разберусь с malloc. - person Mateusz Kubuszok   schedule 09.10.2013