thread safe singlton - возможно ли такое в принципе
От: Andrew S Россия http://alchemy-lab.com
Дата: 06.02.04 13:07
Оценка:
Всем доброго времени суток.
Итак, как было выяснено здесь
Автор: Andrew S
Дата: 06.02.04
, синглтон Майерса не является потокобезопасным.


struct MeyersSingleton
{
    static MeyersSingleton &Instance()
    {
        static MeyersSingleton obj;
        return obj;
    }
================
    mov    al, BYTE PTR ?$S223@?1??Instance@?$CMeyersSingleton@VCNetworkSession@@@@SAAAVCNetworkSession@@XZ@4EA
    mov    BYTE PTR __$EHRec$[esp+80], 4
    test    al, 1
    jne    SHORT $L90959
    or    al, 1
    push    10                    ; 0000000aH
    mov    ecx, OFFSET FLAT:?obj@?1??Instance@?$CMeyersSingleton@VCNetworkSession@@@@SAAAVCNetworkSession@@XZ@4U2@A
    mov    BYTE PTR ?$S223@?1??Instance@?$CMeyersSingleton@VCNetworkSession@@@@SAAAVCNetworkSession@@XZ@4EA, al
    push    OFFSET FLAT:?obj@?1??Instance@?$CMeyersSingleton@VCNetworkSession@@@@SAAAVCNetworkSession@@XZ@$AU1@A ; obj
    call    _atexit
    add    esp, 4
$L90959:

================
private:
    MeyersSingleton(){};
    MeyersSingleton(const MeyersSingleton &);
    MeyersSingleton & operator = (const MeyersSingleton &);
    ~MeyersSingleton(){};
};



Первое, что я подумал — сделать синглтон на хипе, создание защитить критическими секциями. Однако, критические секции (ну или мутексы, какая разница...) перед использованием надо инициализировать. Но, поскольку для синхронизации нам надо уже иметь проинициализированной критическую секкцию, опять приходим к идиоме синглтона майерса (уже для инициализации критической секции) со всем вытекающими проблемами потоконебезопасности.
Какие варианты подскажет уважаемая общественность?
http://www.rusyaz.ru/pr — стараемся писАть по-русски
Re: thread safe singlton - возможно ли такое в принципе
От: ArtDenis Россия  
Дата: 06.02.04 13:20
Оценка:
Здравствуйте, Andrew S, Вы писали:

AS>Итак, как было выяснено здесь
Автор: Andrew S
Дата: 06.02.04
, синглтон Майерса не является потокобезопасным.


У Александреску есть хороший потокобезопасный синглтон.
... << RSDN@Home 1.1.2 stable >>
http://ufa-darts.ru/ — дартс-лига Уфы
Re: thread safe singlton - возможно ли такое в принципе
От: Вадим Никулин Россия Здесь
Дата: 06.02.04 13:42
Оценка:
Здравствуйте, Andrew S, Вы писали:

AS>Всем доброго времени суток.

AS>Итак, как было выяснено здесь
Автор: Andrew S
Дата: 06.02.04
, синглтон Майерса не является потокобезопасным.



AS>
AS>struct MeyersSingleton
AS>{
AS>    static MeyersSingleton &Instance()
AS>    {
           Lock lock;                        // А что мешает блокировку вставить?
           {
AS>           static MeyersSingleton obj;
AS>           return obj;
           }
AS>    }
AS>

AS>Какие варианты подскажет уважаемая общественность?
Не совсем понятно, почему студия должна генерить потоко-независимый код. Если бы она это делала, то какая была бы эффективность этого кода? Об этом должен заботиться разработчик.
Re[2]: thread safe singlton - возможно ли такое в принципе
От: Вадим Никулин Россия Здесь
Дата: 06.02.04 13:49
Оценка:
Здравствуйте, Вадим Никулин, Вы писали:

ВН>Здравствуйте, Andrew S, Вы писали:


AS>>Всем доброго времени суток.

AS>>Итак, как было выяснено здесь
Автор: Andrew S
Дата: 06.02.04
, синглтон Майерса не является потокобезопасным.



AS>>
AS>>struct MeyersSingleton
AS>>{
AS>>    static MeyersSingleton &Instance()
AS>>    {
ВН>           Lock lock;                        // А что мешает блокировку вставить?
ВН>           {
AS>>           static MeyersSingleton obj;
AS>>           return obj;
ВН>           }
AS>>    }
AS>>

AS>>Какие варианты подскажет уважаемая общественность?
ВН>Не совсем понятно, почему студия должна генерить потоко-независимый код. Если бы она это делала, то какая была бы эффективность этого кода? Об этом должен заботиться разработчик.

Да, забыл сказать, мьютекс можно создать без проблем, т. к. если два потока одновременно попытаются создать мьютексы с одинаковым именем, один из них получит отказ, и должен будет проверить, а не создан ли мьютекс пока он его создавал. Если да, то его просто нужно открыть.
Re: thread safe singlton - возможно ли такое в принципе
От: WolfHound  
Дата: 06.02.04 13:50
Оценка: 18 (3)
Здравствуйте, Andrew S, Вы писали:

Толком не тестировал но по идеи так
LONG atom_set(volatile LONG* ptr, LONG value)
{
    return InterlockedExchange(ptr, value);
}
LONG atom_get(volatile LONG* ptr)
{
    return InterlockedExchangeAdd(ptr, 0);
}
struct auto_lock
{
    auto_lock(LONG* ptr)
        :ptr_(ptr)
    {
        while(atom_set(ptr_, 1))
            Sleep(1);
    }
    ~auto_lock()
    {
        atom_set(ptr_, 0);
    }
    LONG* ptr_;
};
template<class T>
struct MTSingleton
{
    static T &Instance()
    {
        static T* obj_ptr=0;//Статическая инициализация(потокобезопасно)
        static LONG flag=0;//Аналогично
        T* ptr=(T*)atom_get((LONG*)&obj_ptr);
        if(!ptr)
        {
            auto_lock lock(&flag);
            ptr=(T*)atom_get((LONG*)&obj_ptr);
            if(!ptr)
            {
                static T obj;//Создастся пи первом поподании сюда
                ptr=&obj;
                atom_set((LONG*)&obj_ptr, (LONG)ptr);
            }
        }
        return *ptr;
    }
};
struct test_singleton
    :MTSingleton<test_singleton>
{
    test_singleton()
    {
    }
};
... << RSDN@Home 1.1.3 beta 1 >>
Пусть это будет просто:
просто, как только можно,
но не проще.
(C) А. Эйнштейн
Re[2]: thread safe singlton - возможно ли такое в принципе
От: Andrew S Россия http://alchemy-lab.com
Дата: 06.02.04 13:54
Оценка:
AS>>Итак, как было выяснено здесь
Автор: Andrew S
Дата: 06.02.04
, синглтон Майерса не является потокобезопасным.


AD>У Александреску есть хороший потокобезопасный синглтон.


Нет у него _работающего_ потокобезопасного синглетона, к сожалению. То, что есть — основывается на том, что критическая секция инициализируется в конструкторе синглетона. А тот, в свою очередь, статически создается в cpp файле. Тогда уже можно и целевой объект статически создавать в cpp файле, напарываясь при этом на неопределенность инициализации статических объектов в разных модулях. За что боролись, на то и напоролись.
http://www.rusyaz.ru/pr — стараемся писАть по-русски
Re[3]: thread safe singlton - возможно ли такое в принципе
От: Andrew S Россия http://alchemy-lab.com
Дата: 06.02.04 13:57
Оценка:
ВН>>Не совсем понятно, почему студия должна генерить потоко-независимый код. Если бы она это делала, то какая была бы эффективность этого кода? Об этом должен заботиться разработчик.

Ну, этот код вызывается один раз при первом вызове функции — эффективность не сильно пострадала бы. А вот нервы разработчика — точно были бы целее.

ВН>Да, забыл сказать, мьютекс можно создать без проблем, т. к. если два потока одновременно попытаются создать мьютексы с одинаковым именем, один из них получит отказ, и должен будет проверить, а не создан ли мьютекс пока он его создавал. Если да, то его просто нужно открыть.


Верно, но это только для именованых мьютексов. Представляете, какая производительность такого кода будет?
http://www.rusyaz.ru/pr — стараемся писАть по-русски
Re[2]: thread safe singlton - возможно ли такое в принципе
От: Andrew S Россия http://alchemy-lab.com
Дата: 06.02.04 14:05
Оценка:

WH>    auto_lock(LONG* ptr)
WH>        :ptr_(ptr)
WH>    {
WH>        while(atom_set(ptr_, 1))
WH>            Sleep(1);
WH>    }


Честно говоря, я так и думал, что будут советовать нечто в этом роде
Я сам рассматривал возможность синхронизации через семейство Interlockedxxx функций, но, согласитесь, выглядит это по меньшей мере страшненько (на самом деле я бы такой код в проекте не допустил, уж лучше инициализировать синглетон статически в файле реализации и потерять безопасность на этапе конструирования статических объектов — т.е. гарантировать, что на этом этапе вызова Instance не будет. Это проще и безопаснее, чем написать такое решение...). Но за попытку спасибо!
http://www.rusyaz.ru/pr — стараемся писАть по-русски
Re[3]: thread safe singlton - возможно ли такое в принципе
От: WolfHound  
Дата: 06.02.04 14:15
Оценка:
Здравствуйте, Andrew S, Вы писали:

AS>Я сам рассматривал возможность синхронизации через семейство Interlockedxxx функций, но, согласитесь, выглядит это по меньшей мере страшненько (на самом деле я бы такой код в проекте не допустил, уж лучше инициализировать синглетон статически в файле реализации и потерять безопасность на этапе конструирования статических объектов — т.е. гарантировать, что на этом этапе вызова Instance не будет. Это проще и безопаснее, чем написать такое решение...). Но за попытку спасибо!

Чем лучше? Я эту идею из boost позаимствовал...
... << RSDN@Home 1.1.3 beta 1 >>
Пусть это будет просто:
просто, как только можно,
но не проще.
(C) А. Эйнштейн
Re: thread safe singlton - возможно ли такое в принципе
От: Павел Кузнецов  
Дата: 06.02.04 14:23
Оценка:
Здравствуйте, Andrew, Вы писали:

AS> Первое, что я подумал — сделать синглтон на хипе, создание

AS> защитить критическими секциями.

Не обязательно создавать объект singleton в динамической памяти. Достаточно
предварить определение статического объекта захватом мьютекса или критической
секции.

AS> Однако, критические секции (ну или мутексы, какая разница...) перед

AS> использованием надо инициализировать.

Один из вариантов — инициализировать критическую секцию/мьютекс заведомо до
использования singleton.

Если структура программы настолько аморфна, что ничего о времени использования
тех или иных объектов сказать нельзя, возможно, стоит задуматься об архитектуре.
Posted via RSDN NNTP Server 1.7 "Bedlam"
Легче одурачить людей, чем убедить их в том, что они одурачены. — Марк Твен
Re[4]: thread safe singlton - возможно ли такое в принципе
От: unrealalex Россия  
Дата: 06.02.04 14:25
Оценка:
WH>Я эту идею из boost позаимствовал...
если мне память не изменяет, то из lightweight_mutex... только я бы Sleep(0) оставил — так квант отдаеться, а в твоем случае задержка, хоть и маленькая.
Невозможное мы сделаем сегодня — чудо займет немного больше времени. /Аноним/
Re[2]: thread safe singlton - возможно ли такое в принципе
От: Andrew S Россия http://alchemy-lab.com
Дата: 06.02.04 14:27
Оценка:
ПК>Один из вариантов — инициализировать критическую секцию/мьютекс заведомо до
ПК>использования singleton.

Верно. Например, в файле реализации синглетона, как это сделано у Александреску.
Но тогда возможна ситуация вызова Instance с еще непроинициализированной критической секцией. В общем, за что боролись... Печально, Павел, неужели нет красивого выхода из этой ситауции?

ПК>Если структура программы настолько аморфна, что ничего о времени использования

ПК>тех или иных объектов сказать нельзя, возможно, стоит задуматься об архитектуре.
Нет, меня вполне устраивает объявление объекта синглтона в файле реализации и я могу гарантировать, что Instance будет вызываться только после инициализации статических объектов. Но меня интересует не конкретный проект, а именно принцип.
http://www.rusyaz.ru/pr — стараемся писАть по-русски
Re[4]: thread safe singlton - возможно ли такое в принципе
От: Andrew S Россия http://alchemy-lab.com
Дата: 06.02.04 14:30
Оценка:
AS>>Я сам рассматривал возможность синхронизации через семейство Interlockedxxx функций, но, согласитесь, выглядит это по меньшей мере страшненько (на самом деле я бы такой код в проекте не допустил, уж лучше инициализировать синглетон статически в файле реализации и потерять безопасность на этапе конструирования статических объектов — т.е. гарантировать, что на этом этапе вызова Instance не будет. Это проще и безопаснее, чем написать такое решение...). Но за попытку спасибо!
WH>Чем лучше? Я эту идею из boost позаимствовал...
Ну, мы люди темные, бустом не пользуемся Но такой вариант я придумал сразу и отверг его, содрогнувшись в душе.
Как говорил Туполев — некрасивый самолет не полетит.
http://www.rusyaz.ru/pr — стараемся писАть по-русски
Re[5]: thread safe singlton - возможно ли такое в принципе
От: Andrew S Россия http://alchemy-lab.com
Дата: 06.02.04 14:31
Оценка:
WH>>Я эту идею из boost позаимствовал...
U>если мне память не изменяет, то из lightweight_mutex... только я бы Sleep(0) оставил — так квант отдаеться, а в твоем случае задержка, хоть и маленькая.

Нет, это ошибка в MSDN. Квант то отдается, а вот загрузка процесса — становится максимальной.
http://www.rusyaz.ru/pr — стараемся писАть по-русски
Re: thread safe singlton - возможно ли такое в принципе
От: Vamp Россия  
Дата: 06.02.04 14:38
Оценка:
Наверное, я чего-то не понимаю. А почему нельзя просто

AS>
AS>struct MeyersSingleton
AS>{
AS>    static MeyersSingleton &Instance()
AS>    {
AS>        HANDLE h;
           CreateMutex(NULL, true, "mutext");
           static MeyersSingleton obj;
           ReleaseMutex(h);
AS>        return obj;
AS>    }
...
AS>

Виндоус-компилятора нет, проверить не могу — но любопытно.
Да здравствует мыло душистое и веревка пушистая.
Re[3]: thread safe singlton - возможно ли такое в принципе
От: Павел Кузнецов  
Дата: 06.02.04 14:39
Оценка:
Здравствуйте, Andrew, Вы писали:

AS> Нет, меня вполне устраивает объявление объекта синглтона в

AS> файле реализации и я могу гарантировать, что Instance
AS> будет вызываться только после инициализации статических объектов.
AS> Но меня интересует не конкретный проект, а именно принцип.

Боюсь, что более-менее общим принципом будет как раз архитектура, позволяющая
отделить инициализацию вспомогательных ресурсов (в данном случае критическая
секция) от инициализации и использования основных объектов (синглтон)... Думаю,
что "локального" платформенно-независимого решения, прозрачного для использующей
программы, нет.
Posted via RSDN NNTP Server 1.7 "Bedlam"
Легче одурачить людей, чем убедить их в том, что они одурачены. — Марк Твен
Re[2]: thread safe singlton - возможно ли такое в принципе
От: Andrew S Россия http://alchemy-lab.com
Дата: 06.02.04 14:48
Оценка:
AS>>
AS>>struct MeyersSingleton
AS>>{
AS>>    static MeyersSingleton &Instance()
AS>>    {
AS>>        HANDLE h;
V>           CreateMutex(NULL, true, "mutext");
V>           static MeyersSingleton obj;
V>           ReleaseMutex(h);
AS>>        return obj;
AS>>    }
V>...
AS>>

V>Виндоус-компилятора нет, проверить не могу — но любопытно.

Мысль правильная, реализация — нет.
1. Хэндл не присваивается и не закрывается
2. Медленно.
http://www.rusyaz.ru/pr — стараемся писАть по-русски
Re[3]: thread safe singlton - возможно ли такое в принципе
От: Vamp Россия  
Дата: 06.02.04 14:56
Оценка:
AS>Мысль правильная, реализация — нет.
AS>1. Хэндл не присваивается и не закрывается
Ну, это понятно. Замнем для ясности.
AS>2. Медленно.
А если вот так?

static MeyersSingleton &Instance()
    {
        bool instantiated=false;
        if (!instaniated) {  
           HANDLE h;
           h=CreateMutex(NULL, true, "mutext");
           static MeyersSingleton obj;
           instantiated=true;
           ReleaseMutex(h);
           CloseHandle(h);
        } 
        return obj;
    }
Да здравствует мыло душистое и веревка пушистая.
Re[4]: thread safe singlton - возможно ли такое в принципе
От: Andrew S Россия http://alchemy-lab.com
Дата: 06.02.04 15:21
Оценка: +1
AS>>2. Медленно.
V>А если вот так?

V>
V>static MeyersSingleton &Instance()
V>    {
V>        bool instantiated=false;
V>        if (!instaniated) {  
V>           HANDLE h;
V>           h=CreateMutex(NULL, true, "mutext");
V>           static MeyersSingleton obj;
V>           instantiated=true;
V>           ReleaseMutex(h);
V>           CloseHandle(h);
V>        } 
V>        return obj;
V>    }
V>


И так медленно И неправильно.
1. static volatile bool
2. объвлять его членом класса.
3. Не скомпилируется — obj out of scope.
4. Создание объекта для надежности в отдельную статическую функцию (дабы не искушать оптимизатор).
5. Двойная проверка некорректно работает на некоторых SMP системах. Вообще ее не рекомендуют использовать — то там баг отловится, то там...

В общем, работающее решение предложил WolfHound, но мне оно по ряду причин не нравится и рекомендовать его к использованию я не могу. Но оно рабочее и даже в некотором смысле кошерное.
http://www.rusyaz.ru/pr — стараемся писАть по-русски
Re[2]: thread safe singlton - возможно ли такое в принципе
От: Andrew S Россия http://alchemy-lab.com
Дата: 06.02.04 16:08
Оценка:
Кстати, вот этот код абсолютно бесполезен:

WH>
WH>LONG atom_get(volatile LONG* ptr)
WH>{
WH>    return InterlockedExchangeAdd(ptr, 0);
WH>}
WH>


Просто читая volatile переменную типа int или long на win32 мы гарантированно получаем валидное значение (старое или новое — вопрос другой, но валидное). Т.о. приведенный код ровным счетом ничего не делает. Так утверждают и господин Рихтер, да и многие другие, и я склонен с ними соглашаться.
http://www.rusyaz.ru/pr — стараемся писАть по-русски
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.