Safe singleton in C+ 03 - Разминка для мозга

Статус: Offline
Реєстрація: 05.02.2007
Повідом.: 36996
Safe singleton in C+ 03 - Разминка для мозга

Итак постановка задачи:
Я хочу написать полностью потокобезопасный контекстонезависимый синглтон.
Очевидно что нижеприведенный классический код:
Код:
class MySingleton
{
public:
	MySingleton& Instance()
	{
		static MySingleton instance;
		return instance;	
	}
};
В общем случае не являеться безопасным (хотя вроде как в С++ 11 он уже сам потокобезопасен).

Далее можно использовать указатели с мьютексами, но опять таки где гарантия что все не упадет при инициализации мьютекса?
Но в теории мьютекс можно сделать статиком и тогда он будет инициализирован при запуске программы, и вопрос синхронизации отпадет сам собой.
Но при таком подходе очевидно. что обращение к синглтону из других глобальных объектов может привести к крашу, если инициализация данных из файла с синглтоном не успеет выполниться до вызова синглтона при инициализации других данных.

Выходит тупик - либо у нас потокобезопасный синглтон который нельзя вызывать из global scope либо он непотокобезопасен, но безпроблемно вызываем из global scope?
ъУ кого то есть идеии как на С++ 03 реализовать полностью безопасный синглтон?
 
Останнє редагування:
в гугле забанили? тысячи тем от новичков по всему стековерфлов, примеры на мсдн, даже в педивикии есть =\
 
Тему еще раз прочти, потом статьи в гугле, если найдешь ответ - дай ссылку миня значит таки забанили :)
 
У кого то есть идеии как на С++ 03 реализовать полностью безопасный синглтон?

хм, ну как-нибудь так:
Код:
class MySingleton
{
public:
	MySingleton& Instance()
	{
		boost::mutex::scoped_lock lock(s_syncRoot);
		static MySingleton instance;
		return instance;	
	}

private:
	static boost::mutex s_syncRoot;

	MySingleton() {}
	~MySingleton() {}
	MySingleton(MySingleton const &);
	MySingleton &operator=(MySingleton const &);
};
 
Останнє редагування:
хм, ну как-нибудь так:
Код:
class MySingleton
{
public:
	MySingleton& Instance()
	{
		boost::mutex::scoped_lock lock(s_syncRoot);
		static MySingleton instance;
		return instance;	
	}

private:
	static boost::mutex s_syncRoot;

	MySingleton() {}
	~MySingleton() {}
	MySingleton(MySingleton const &);
	MySingleton &operator=(MySingleton const &);
};

Если Instance будет вызван при инициализации еденицы компиляции до инициализации еденицы компиляции MySingleton, это приведет к крашу, так как объект s_syncRoot еще не будет создан.
 
Если Instance будет вызван при инициализации еденицы компиляции до инициализации еденицы компиляции MySingleton, это приведет к крашу, так как объект s_syncRoot еще не будет создан.

ну да, если обращаться к MySingleton::Instance до вызова main (например во время инициализации глобальных переменных), то есть опасность что обращение произойдет до инициализации s_syncRoot.

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

Есть идея использовать для синхронизации именованый мьютекс windows. Думаю это решит проблему.
 
class Singleton
{
static Singleton* _instance;
static auto_ptr<Singleton> __instanceAuto;

protected:

Singleton() {}
Singleton(Singleton const&);
void operator = (Singleton const&);

public:

static Singleton* Instance()
{
return _instance;
}

virtual ~Singleton() {}
};

Singleton* Singleton::_instance(new Singleton);
auto_ptr<Singleton> Singleton::__instanceAuto(Singleton::_instance);
 
class Singleton
{
static Singleton* _instance;
static auto_ptr<Singleton> __instanceAuto;

protected:

Singleton() {}
Singleton(Singleton const&);
void operator = (Singleton const&);

public:

static Singleton* Instance()
{
return _instance;
}

virtual ~Singleton() {}
};

Singleton* Singleton::_instance(new Singleton);
auto_ptr<Singleton> Singleton::__instanceAuto(Singleton::_instance);

жесть... мои глаза наливаются кровью..
 
То есть задача лишь в том чтоб безопасно получить инстанс синглетона из любого потока? Обеспечивать синхронизацию конкретно методов синглетона не нужно?

Если так - то volatile и двойной чек спасет от вредной компиляторной оптимизации.
Но правда в многопроцессорной системе возможен пиздец все равно.

Если можно забить на эффективность - то остается лок делать каждый раз. И функция Instance() конечно static должна быть. Иначе хуевый синглетон как бы.
 
Останнє редагування:
Как я понял, да. Тогда действительно можно использовать либо системные мутехи, либо атомарные операции, что правда может быть не очень хорошо по перфомансу в зависимости от интенсивности обращений к синглтону. Либо использовать double-check locking и его производные алгоритмы - сам не проверял. Но опять же, вариант с системными вызовами получается будет платформозависим, а значит не универсален.
 
Как я понял, да. Тогда действительно можно использовать либо системные мутехи, либо атомарные операции, что может быть не очень хорошо по перфомансу в зависимости от интенсивности обращений к синглтону. Либо использовать double-check locking и его производные алгоритмы - сам не проверял. Но опять же, вариант с системными вызовами будет платформозависим.

DCL в С++ без volatile работает херово :) В дебаге будет все ок, а в релизе заебешься искать чего там компилер наоптимизировал.
Мутех конечно хорошо, но дорого.
 
DCL в С++ без volatile работает херово :) В дебаге будет все ок, а в релизе заебешься искать чего там компилер наоптимизировал.
Мутех конечно хорошо, но дорого.

Нет, ну естественно с волатил :)



Мутех конечно хорошо, но дорого.

Ну да, я так и написал :-D
 
Останнє редагування:
Re: Safe singleton in C+ 03 - Разминка для мозга

То есть задача лишь в том чтоб безопасно получить инстанс синглетона из любого потока? Обеспечивать синхронизацию конкретно методов синглетона не нужно?

Если так - то volatile и двойной чек спасет от вредной компиляторной оптимизации.
Но правда в многопроцессорной системе возможен пиздец все равно.

Если можно забить на эффективность - то остается лок делать каждый раз. И функция Instance() конечно static должна быть. Иначе хуевый синглетон как бы.

Проблема не в том чтобы синглтон создать, а в том что статический объект для лока безопасно инициализировать проблематично, точнее даже невозможно, без использования объектов синхронизации ос.

Изначально ТС'а интересовала возможность написать синглтон так чтобы к нему можно было безопасно обращаться из любого места, например во время инициализации статиков (еще до выполнения main). Т.е. речь идет о том, что обращение к синглтону может произойти в момент, когда объект синхронизации (объявленный статиком) еще не инициализирован. Таким образом статик переменную для синхронизации использовать нельзя.
 
Останнє редагування:
Проблема не в том чтобы синглтон создать, а в том что статический объект для лока безопасно инициализировать проблематично, точнее даже невозможно, без использования объектов синхронизации ос.

Стой. Еще раз: чем дабл чек локинг не подходит?
 
Стой. Еще раз: чем дабл чек локинг не подходит?

С волатил - подходит. Если один процессор :)

Проблема не в том чтобы синглтон создать, а в том что статический объект для лока безопасно инициализировать проблематично, точнее даже невозможно, без использования объектов синхронизации ос.

Можно подумать бустовый мутех не работает через виндовый мутех :іржач:
 
С волатил - подходит. Если один процессор :)

Можно подумать бустовый мутех не работает через виндовый мутех :іржач:

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

При использовании именованного мьютекса, можно обойтись без статика, создавать мьютекс по имени прямо внутри метода Instance(). Таким образом мы не используем статик, а синхронизацию выполняет система.
 
На это александреску когда-то рекомендовал писать какую-то магическую хуиту, позволяющую на многопроессорных системах сохранять порядок, но лично я до надобности этого еще не дошел )))
 
Назад
Зверху Знизу