threadsicheres singleton



  • OKOKOKOK Ihr habt mich überzeugt. War eine Sch...idee



  • ok war einige zeit nicht da und kann leider jetzt erst wieder antworten.

    kann man nich statt dem in dem link geschickten code auch das schreiben?
    (habe mal das template und den instance_helper gelöscht)

    #include <boost/thread/once.hpp>
    struct singleton : private boost::noncopyable{
    public:
     static singleton  instance(){
       boost::call_once(call_me_once,once_);
       static singleton  s;
       return s;
     }   
    
    private:
     static boost::once_flag once_;
     static void call_me_once(){
       instance();
     }
    
     singleton();
     ~singleton(); 
    };
    boost::once_flag singleton::once_ = BOOST_ONCE_INIT;
    


  • Das wird vermutlich in einem Stack-Overflow enden. Also der instance_helper macht schon Sinn, bzw. genauer: er ist nötig.

    Und natürlich kannst du das Singleton nicht "by value" zurückgeben, da es ja noncopyable ist. Ausserdem wäre es - selbst wenn es kopierbar wäre - dann kein Singleton mehr. Den Return-Typ von "instance" solltest du also auch wieder zu "singleton&" zurück-ändern.

    ps: das Entfernen des Templates ist natürlich OK. Auch wenn dadurch der Typ des Singletons (mMn unnötigerweise) festgelegt wird, und die schöne Wiederverwendbarkeit dadurch flöten geht.



  • Shade Of Mine schrieb:

    Deshalb verwende ich hier eine atomic Zuweisung. In echtem Code wuerde ich instance zu einem atomic<Foo*> machen. Wobei atomic eine Klasse ist, die mir eben atomic Operations bietet.

    Verhindert die Verwendung von atomic auch das Caching von Werten in den Registern sowie das Umordnen von Anweisungen?

    Gibt es eine plattform-unabhängige Variante (z.B. boost) für InterlockedExchange?



  • Atomic schrieb:

    Shade Of Mine schrieb:

    Deshalb verwende ich hier eine atomic Zuweisung. In echtem Code wuerde ich instance zu einem atomic<Foo*> machen. Wobei atomic eine Klasse ist, die mir eben atomic Operations bietet.

    Verhindert die Verwendung von atomic auch das Caching von Werten in den Registern sowie das Umordnen von Anweisungen?

    Grundsätzlich sind das zwei getrennte Konzepte, Atomics und Barriers/Fences.

    Allerdings gibt es auf vielen Plattformen Befehle die beides kombinieren. Macht auch Sinn, CAS (compare-and-swap aka. InterlockedCompareExchange) braucht man oft mit Acquire Semantik bzw. als Full-Barrier.

    Gibt es eine plattform-unabhängige Variante (z.B. boost) für InterlockedExchange?

    Wäre mir nichts bekannt. In C++0x könnte was kommen.



  • Wenn man jetzt atomic verwendet.
    Ist eine Variante wie unten dann Threadsafe.

    atomic<Foo*> Foo::instance = 0;
    
    Foo& Foo::getInstance(){
        if(!instance){
            boost::mutex::scoped_lock l(mutex); 
            if(!instance){
                Foo* temp = new Foo();
                instance = temp;
            }
        }
        return *Foo::instance;
    }
    

    Ich hab irgendwo mal gelesen, dass atomic
    auch das reordering von Anweisungen verhindert. Wie sieht es mit Caching aus?
    Ist das evtl. noch kritisch?


Anmelden zum Antworten