Пользователь
-
Автор темы
- #1
Код:
#include <atomic>
#include <iostream>
#include <future>
#include <mutex>
#include <thread>
template<typename T>
class Singleton
{
protected:
Singleton() {}
~Singleton() {}
Singleton(const Singleton&) = delete;
Singleton& operator=(const Singleton&) = delete;
Singleton(Singleton&&) = delete;
Singleton& operator=(Singleton&&) = delete;
private:
static std::atomic<T> instance;
static std::mutex Mutex;
public:
static T& Get()
{
T inst = instance.load(std::memory_order_acquire);
if ( !inst )
{
std::lock_guard<std::mutex> Lock(Mutex);
inst = instance.load(std::memory_order_relaxed);
if( !inst )
{
inst = new Singleton();
instance.store(inst,std::memory_order_release);
}
}
return inst;
}
};
Описание работы синглтона:
Чтение синглтона - операция получения, запись, операции деблокирования(14 и 20 строка). Поскольку обе операции происходят на одном и том же атоме, мне не нужна последовательная согласованность. Стандарт C++ гарантирует, что операция получения синхронизируется с операцией освобождения на том же атоме. В этом случае эти условия сохраняются, поэтому я могу ослабить модель памяти C++ в строках 14 и 20. Достаточно получить семантику получения-освобождения.
Семантика получения-выпуска имеет такую же производительность, как и последовательная согласованность. Это неудивительно, потому что на x86 обе модели памяти очень похожи.