Singleton static und lazy creation
-
dot schrieb:
type& singleton() { static std::unique_ptr<type> instance(new type()); return *instance; }[...]
Ich würd das Ding übrigens nicht unbedingt singleton nennen, denn am Ende verwechselt es noch einer mit dem Singleton Pattern.Das ist das Singleton-Pattern.
Bzw. so knapp dran, dass ich keinen nennenswerten Unterschied sehe.
Das einzige was hier nicht dem Singleton-Pattern entspricht (bzw. vielleicht - wir sehen zu wenig Code um das sicher sagen zu können) ist, dass die Klasse sich nicht selbst "schützt" und zum Singleton macht.Was Vor-/Nachteile angeht ist das IMO aber nicht wirklich wichtig.
-
hustbaer schrieb:
dot schrieb:
type& singleton() { static std::unique_ptr<type> instance(new type()); return *instance; }[...]
Ich würd das Ding übrigens nicht unbedingt singleton nennen, denn am Ende verwechselt es noch einer mit dem Singleton Pattern.Das ist das Singleton-Pattern.
Bzw. so knapp dran, dass ich keinen nennenswerten Unterschied sehe.
Das einzige was hier nicht dem Singleton-Pattern entspricht (bzw. vielleicht - wir sehen zu wenig Code um das sicher sagen zu können) ist, dass die Klasse sich nicht selbst "schützt" und zum Singleton macht.Die Tatsache dass der Typ gegen Mehfachinstanzierung geschützt wird, ist doch die eine Eigenschaft die ein Singleton ausmacht!? Alles andere (globaler Zugriff auf die Instanz) ist nur Konsequenz einer konkreten Inkarnation des Pattern, nicht aber der Zweck des Singleton Pattern. Das da oben ist in etwa so orthogonal zum Singleton Pattern wie eine globale Variable...
EDIT: Natürlich gehe ich davon aus dass der Typ nicht geschützt ist. Du hast recht dass man das, basierend auf dem Codeschnipsel, nicht gesichert sagen kann, es ist aber imo ziemlich sicher anzunehmen

-
hustbaer schrieb:
Was die Speicher-Allokation für das Objekt selbst angeht, so ist diese in dem von dir gezeigten Code statisch: der "this" Pointer des
std::stringist im nach (fast-) C zurückübersetzten Code&test_void_::foo, also statisch. Das Speicher-Besorgen selbst ist als nicht "lazy".Natürlich landet das in .data/.rdata, anders wäre das ja auch unmöglich umzusetzen.
-
@Ethon/Hustbaer:
Im von Ethon geposteten assembler listing sind ja schon Mutexe für die Konstruktion drin.Macht das speziell nur der gcc oder gilt das z.B. auch bei VC++ (im multithreaded Modell)?
-
Naja, nur GCC will ich jetzt nicht sagen, gibt ja viele Compiler.
MSVC bis inklusive 2010 macht es allerdings nicht.
-
dot schrieb:
Die Tatsache dass der Typ gegen Mehfachinstanzierung geschützt wird, ist doch die eine Eigenschaft die ein Singleton ausmacht!?
Sehe ich jetzt nicht so.
Wenn ich einen Typ T habe, den man ganz normal instanzieren kann. Und aber eine T Instanz mit spezieller Bedeutung haben kann, die es nur 1x geben kann... es aber trotzdem Sinn macht andere Ts normal zu erzeugen...
Dann werde ich den Konstruktor von T nicht private machen, und eine "get the ony special T instance" Funktion machen.
Was für praktisch relevante Unterschiede gibt es da dann zu einem Singleton?
Für mich ist das einfach das selbe.Der Knackpunkt beim Singleton Pattern ist für mich einfach, dass man ein Objekt (nicht eine Klasse) zum Singleton erklärt. Mit all den Vor- und Nachteilen die sich daraus ergeben.
Für mich besteht auch kein wesentlicher Unterschied zwischen z.B. privaten static Members und Singletons.
-
Was ist überhaupt der Sinn des Singlwton-Patterns? Wieso keine freien Funktionen?
-
hustbaer schrieb:
Naja, nur GCC will ich jetzt nicht sagen, gibt ja viele Compiler.
MSVC bis inklusive 2010 macht es allerdings nicht.Was bedeutet das denn für den Konstruktoraufruf in dem Fall? Ist der dann nicht mehr thread-safe?
-
Ethon schrieb:
Was ist überhaupt der Sinn des Singlwton-Patterns? Wieso keine freien Funktionen?
Die Vorteile des Singleton-Pattern:
- Man kann sich wie ein OOPer fühlen, während man globale Variablen und Funktionen mit Seiteneffekten benutzt.
- Es lässt sich praktisch in jedem Programm anwenden.
- Es muss gut sein, steht schließlich "Pattern" dran.
-
ogni42 schrieb:
hustbaer schrieb:
Naja, nur GCC will ich jetzt nicht sagen, gibt ja viele Compiler.
MSVC bis inklusive 2010 macht es allerdings nicht.Was bedeutet das denn für den Konstruktoraufruf in dem Fall? Ist der dann nicht mehr thread-safe?
Genau, die Initialisierung von function-statics ist mit MSVC nicht threadsafe.
D.h. wenn man nen Fall hat, wo man nicht garantieren kann, dass die Funktion vollständig ausgeführt wurde, bevor man Threads startet die die selbe Funktion aufrufen, dann kann das in UB enden.
Ich hoffe dass MS da beim 2012er Studio mal nachbessert.
-
Was nebenbei bedeutet, dass nurfs Version auch nicht threadsafe ist (selbst wenn man davon ausgeht, dass die richtige release-aquire-Semantik für ptr gilt und Instruktion nicht zu sehr umgeordnet werden). Das Mutex-Objekt wird dort nämlich auch funktionslokal erzeugt. Und dessen Konstruktion dürfte eher nicht trivial sein. Für solche Zwecke muss ganz klar ein globaler Mutex her, der garantiert bereits konstruiert wurde oder man behilft sich mit einem Eigenbau, der auch mit Zeroinitialisierung noch richtig funktioniert.
-
Wie wäre es mit function local statics ganz meiden?
-
@camper
Genau.
Ist mir gar nicht aufgefallen dass seine Mutex auch function-static ist.camper schrieb:
oder man behilft sich mit einem Eigenbau, der auch mit Zeroinitialisierung noch richtig funktioniert.
Jupp.
Oder man verwendet was fertiges wie boost::call_once.
-
Hallo zusammen,
falls jemand jetzt einen threadsicheren Singleton sucht:
http://www.c-plusplus.net/forum/279968#2004357Gruß,
XSpille
-
XSpille schrieb:
Hallo zusammen,
falls jemand jetzt einen threadsicheren Singleton sucht:
http://www.c-plusplus.net/forum/279968#2004357Gruß,
XSpilleKeine Ahnung ob das sinnvoll ist. Ich würde erwarten, dass eine Implementation, die <atomic> bereitstellt, bereits in der Lage ist, funktionslokale statische Objekte threadsicher zu initialisieren.
-
camper schrieb:
XSpille schrieb:
Hallo zusammen,
falls jemand jetzt einen threadsicheren Singleton sucht:
http://www.c-plusplus.net/forum/279968#2004357Gruß,
XSpilleKeine Ahnung ob das sinnvoll ist. Ich würde erwarten, dass eine Implementation, die <atomic> bereitstellt, bereits in der Lage ist, funktionslokale statische Objekte threadsicher zu initialisieren.
Ich meine mich zu erinnern, dass der GCC dies macht, jedoch der MSVC machte es nicht. Ob die aktuellsten Versionen es jedoch nun machen, weiß ich leider auch nicht, aber verlassen würde ich mich (ohne Recherche) auf diese Annahme nicht.
-
Ja, GCC macht es, und ja, MSVC 2010 macht es nicht.
MSVC 2010 hat aber auch kein <atomic>.