Потоко-бесопасный синглетон
От: SchweinDeBurg Россия http://zarezky.spb.ru/
Дата: 24.05.06 07:25
Оценка:
Доброго времени суток всем нам!

Понадобился мне тут сабж... в boost'е ничего подобного, к моему глубочайшему удивлению, не обнаружилось; гуглевание по словам "C++ singleton thread safe" выдало лишь массу ссылок на "общие слова", по прочтении которых наваялось вот такое:

// interface

template <class _Class_t>
class Singleton
{
// construction/destruction
protected:
    Singleton(void);
    ~Singleton(void);

// copying/assignment - disabled and thus not implemented
private:
    Singleton(const Singleton&);
    Singleton& operator=(const Singleton&);

// object creator/accessor
public:
    static _Class_t& GetObject(void);

// attributes
private:
    class Locker: public CRITICAL_SECTION
    {
        friend class Singleton<_Class_t>;
        Locker(void);
        ~Locker(void);
        void Enter(void);
        void Leave(void);
    };
    static Locker m_objectLocker;
};

// Singleton<> implementation

template <class _Class_t>
inline Singleton<_Class_t>::Singleton(void)
{
}

template <class _Class_t>
inline Singleton<_Class_t>::~Singleton(void)
{
}

template <class _Class_t>
_Class_t& Singleton<_Class_t>::GetObject(void)
{
    m_objectLocker.Enter();
    static _Class_t* pObject;
    if (pObject == NULL)
    {
        pObject = new _Class_t();
    }
    m_objectLocker.Leave();
    return (*pObject);
}

template <class _Class_t>
typename Singleton<_Class_t>::Locker Singleton<_Class_t>::m_objectLocker;

// Singleton<>::Locker implementation

template <class _Class_t>
inline Singleton<_Class_t>::Locker::Locker(void)
{
    ::InitializeCriticalSection(this);
}

template <class _Class_t>
inline Singleton<_Class_t>::Locker::~Locker(void)
{
    ::DeleteCriticalSection(this);
}

template <class _Class_t>
inline void Singleton<_Class_t>::Locker::Enter(void)
{
    ::EnterCriticalSection(this);
}

template <class _Class_t>
inline void Singleton<_Class_t>::Locker::Leave(void)
{
    ::LeaveCriticalSection(this);
}

Метод использования очевиден:

class MyOneAndOnly: public Singleton<MyOneAndOnly> { ... };

MyOneAndOnly::GetObject().some_method();

Теперь собственно проблемы/вопросы:

  1. Обращение к методам MyOneAndOnly потенциально возможно из конструкторов/деструкторов глобальных объектов (почему pObject и создается в куче). С первыи проблем, как я понимаю не возникнет, так как при первом же общении произойдет вызов new _Class_t. А вот деструкторами все хуже, потому как никаких гарантий, что уже не был разрушен Locker, у меня нет. Это можно как-то преодолеть?

  2. Очевидно, что когда-то нужно вызвать delete pObject — но как это сделать "безопасно" (то есть, с гарантией, что все глобальные объекты уже разрушены)? Копать в сторону atexit()?

  3. Я правильно понимаю, что реализовать singleton для класса, который не имеет конструктора по умолчанию, невозможно?

P.S.
В ожидании ответов пошел читать Паттерн Singleton (Одиночка). Примеры использования
Автор(ы): Дмитрий Федоров
Дата: 14.11.2002
[ posted via RSDN@Home 1.1.4 stable SR1 r568, accompanied by silence ]
- Искренне ваш, Поросенок Пафнутий ~ ICQ#116846877
In Windows, there’s always a catch… © Paul DiLascia
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.