[C++] Speicherfreigabe bei statischem Singleton

Programmiersprachen, APIs, Bibliotheken, Open Source Engines, Debugging, Quellcode Fehler und alles was mit praktischer Programmierung zu tun hat.
CrystalCoder
Beiträge: 54
Registriert: 03.03.2002, 17:51
Kontaktdaten:

Re: [C++] Speicherfreigabe bei statischem Singleton

Beitrag von CrystalCoder »

Chromanoid hat geschrieben:Dieser Editor soll dann mehrere Instanzen des Spiels direkt erstellen und ansprechen können.
Sowas gehört vorher eingeplant. Nach der Planung sollte man möglichst nichts mehr an den Strukturen ändern sonst bricht das Chaos los.
Wenn ein Konzept nicht zur Planung passt dann muss man eben ein anderes anwenden.
Übrigens spricht nichts dagegen den Editor zwei mal aufzurufen, wenn man mal wirklich sowas brauchen sollte (wobei ich eigentlich gar keinen Sinn darin sehe).
Chromanoid hat geschrieben:Wenn man es dann schon kapselt, würde eine Variante ohne Singleton doch einen viel höheren Mehrwert bedeuten
Nicht, wenn man die Kapselung nur dazu nutzt ein unikates Objek zu erzeugen.


dot hat geschrieben:Denn anstatt die Abhängigkeiten explizit im Code zu haben, sind die dann schön versteckt, sodass sie erst auffallen, wenn der Singleton zum Problem wird, sodass du ihn dann mühsam herausoperieren darfst.
Das Konzept ist ausreichend gut durchdacht dass es schon in viele Anwendungen Platz gefunden hat (laut ihm in so einigen Spieletiteln an denen der Buchautor mitgearbeitet hat).
Wenn es irgendwann mal nicht mehr ausreicht, so wird sich was neues ausgedacht wie mit allen anderen Konstrukten auch.
Davon mal abgesehen: Inwiefern macht das einen Unterschied zu dem Zugriff über eine Globale?
dot hat geschrieben:Thread hier mal aufmerksam zu lesen, wir haben das imo wirklich schon zur Genüge diskutiert
Genau das habe ich bereits gemacht, weswegen ich eigentlich schon eine Vorstellung hatte wie man auf meine Anfrage regaieren würde.
Ich habe keine deutliche (Begründete) Aussage finden können, die exakt beschreibt, warum man "niemals Singletons benutzen" sollte.
Alles was ich hier fand war nur "Singletons sind einfach nur sch..._nicht_so_gut".
dot hat geschrieben:Es hat Nachteile ohne einen Vorteil zu bieten
Sorry aber das sagt für mich garnichts aus. Davon abgesehen hat es sehr wohl seine Vorteile (auch wenn es nur "Bequemlichkeiten" sind wie du es nennst).
Außerdem würde man das in der Praxis nicht einsetzen wenn dem wirklich so wäre.
dot hat geschrieben:"Meine Wohnung ist das Zentrum meines täglichen Lebens. Darum darf es in meinem Leben um jeden Preis bis ans Ende aller Tage nur eine Wohnung haben."
Der Vergleich scheint mir aus der Luft gegriffen zu sein. Ich habe nicht von dem Muster allgemein gesprochen, sondern für diese eine Anwendung.
dot hat geschrieben:Wenn man das will. Aber warum sollte man das hier wollen?
Um es explizit hervorzuheben
dot hat geschrieben:Wer sagt, dass eine globale Variable die Alternative ist?
Welche gäbe es denn noch, wenn man nicht extra eine Referenz auf das Objekt in jeder einzelnen Komponente haben will?
Ich mag mich vielleicht nicht günstig ausgedrückt haben: Ich meinte nicht, dass Singletons ein Ersatz für globale Variablen sind. Mit einem Singleton kann man diese jedoch "umgehen".
Ich will nicht sagen, dass das immer sinnvoll ist, jedoch ist es ein "netter" Nebeneffekt, wenn man das Design sowieso schon so aufbauen will (oder auch nicht, jedem das seine).
dot hat geschrieben:Und eines Tages will man, dass eine Komponente in ein andres Log logged als der Rest. Gute Nacht.
Der Log ist kein Singleton und jede Komponente die ein eigenes Log haben will kann sich eine egene Instanz erstellen. Anderen Komponenten bleiben unangetastet, Problem gelöst, guten morgen!
dot hat geschrieben:Und zwar genau so lange, bis man merkt wie unpraktisch es eigentlich ist
Diese Aussage trifft auf so ziemlich alles zu.


waigie hat geschrieben:Das liegt aber nur daran das sich jeder bei Singletons an diese Namenkonvention hält.
Falsch, es geht hier nicht um irgendjemandes Konstrukt, sondern um das Eigene. Wenn man sich nicht mal selbst an eigene Konventionen hält, dann kann man sich das alles eigentlich auch sparen (genauso überhaupt irgendwelche Gedanken über die Softwarearchitektur).
waigie hat geschrieben:Bei dem einen weiß ich genau worum es sich handelt beim anderen nicht.
Warum sollte man bei dem einen nicht wissen worum es sich handelt?
waigie hat geschrieben:Singletons eigentlich immer Fehl am Platz sind.
Das wage ich jetzt mal zu bezweifeln. Es ist eine Sache die man mit ziemlicher Sicherheit nicht beweisen kann. Ich lasse mich jedoch gern mit handfesten Argumenten vom Gegenteil überzeugen.


-------

Zu der Frage, warum ich gegen eine globale Variable bin:
Eine globale Variable, sei diese noch so gut benannt, kann nicht per IntelliSense erreicht werden (und nein ich will kein extra Namespace da drum machen).
Ein GameApp::getInstance() Aufruf kann ich übrigens viel leichter im Code erkennen, als g_myGame (weil der Zugriffsoperator :: kaum zu übersehen ist und der Funktionsaufruf dahinter wird bei mir mit Visual Assist extra eingefärbt).

------
Ich hätte da noch einen Grund warum ein Singleton für diesen Anwendungsfall angebracht sein kann:
Ein GameApp Objekt verwaltet im Prinzip alles was in der Applikation so drin ist. Dazu verbraucht es sehr viel Ressourcen des Systems und nimmt sich alles was es kriegen kann.
Erlaube ich eine zweite, komplett andere Instanz, dann müssen sich die beiden Objekte die Ressourcen teilen was erstmal nicht so schlimm wäre wenn man aber:
Habe ich z.B. eine selbst verwaltende SceneManager Komponente, welche Daten von der Festplatte streamen kann und ich habe jetzt eine weitere Instanz der Containerklasse dann habe ich zwei SceneManager welche sich gegenseitig stören und quasi, wenn überhaupt, nur schwer synchronisiert werden können und somit gleichzeitig die Festplatte und den Datenbus in die Knie zwingen (sofern man Multithreading benutzt und wenn nicht dann hat man nur die halbe Rechenzeit).
Beide GameApp Objekte würden sich um den Grafikadapter streiten, und ihre Geometrie (nach jedem "restore") zum Rendern schicken. Ist die Anwendung Multithreaded würde man die Grafikkarte schon allein durch ständiges (und überflüssiges) wechseln der Materialien ausbremsen.
Wenn ich also sowieso nur Probleme mit mehreren Objekten habe, warum dann nicht ausschließen, dass so etwas vorkommt?
Benutzeravatar
CodingCat
Establishment
Beiträge: 1857
Registriert: 02.03.2009, 21:25
Wohnort: Student @ KIT
Kontaktdaten:

Re: [C++] Speicherfreigabe bei statischem Singleton

Beitrag von CodingCat »

CrystalCoder hat geschrieben:
dot hat geschrieben:Thread hier mal aufmerksam zu lesen, wir haben das imo wirklich schon zur Genüge diskutiert
Genau das habe ich bereits gemacht, weswegen ich eigentlich schon eine Vorstellung hatte wie man auf meine Anfrage regaieren würde.
Ich habe keine deutliche (Begründete) Aussage finden können, die exakt beschreibt, warum man "niemals Singletons benutzen" sollte.
Alles was ich hier fand war nur "Singletons sind einfach nur sch..._nicht_so_gut".
WIE BITTE?

http://zfx.info/viewtopic.php?p=23024#p23024
http://zfx.info/viewtopic.php?p=23055#p23055
http://zfx.info/viewtopic.php?p=23077#p23077

Ich gebe ja zu, dass der Thread sehr lang ist, zwischendurch abschweift, und ich am Anfang selbst die Begriffe Singleton und globale Instanz durcheinander geworfen habe, aber ich habe mir wirklich alle Mühe gegeben, das gerade zu rücken. Und bevor wir hier nicht die gleiche Diskussionsgrundlage haben, habe ich auch keine Lust, mitzudiskutieren.
alphanew.net (last updated 2011-07-02) | auf Twitter | Source Code: breeze 2 | lean C++ library | D3D Effects Lite
Benutzeravatar
dot
Establishment
Beiträge: 1734
Registriert: 06.03.2004, 18:10
Echter Name: Michael Kenzel
Kontaktdaten:

Re: [C++] Speicherfreigabe bei statischem Singleton

Beitrag von dot »

CrystalCoder hat geschrieben:
Chromanoid hat geschrieben:Dieser Editor soll dann mehrere Instanzen des Spiels direkt erstellen und ansprechen können.
Sowas gehört vorher eingeplant. Nach der Planung sollte man möglichst nichts mehr an den Strukturen ändern sonst bricht das Chaos los.
Wenn ein Konzept nicht zur Planung passt dann muss man eben ein anderes anwenden.
Übrigens spricht nichts dagegen den Editor zwei mal aufzurufen, wenn man mal wirklich sowas brauchen sollte (wobei ich eigentlich gar keinen Sinn darin sehe).
In meinem Editor möchte ich vielleicht neben der 3D-Ansicht auch noch Auf-, Grund- und Seitenriss haben. Wenn meine Renderingkomponente in Singleton ist, könnte es da schon wieder schwierig werden. Warum sollte ein Ressourcen-Manager ein Singleton sein? Warum sollte es nur einen geben und vor allem: Ein Manager für alle Ressourcen? In den verschiedensten Komponenten hast du die verschiedensten Arten von Ressourcen, die alle auf völlig verschiedene Arten und Weisen gemanaged werden müssen. Ein einzelner globaler Manager kann doch schon allein unter diesem Gesichtspunkt keine gute Idee sein!?
CrystalCoder hat geschrieben:
Chromanoid hat geschrieben:Wenn man es dann schon kapselt, würde eine Variante ohne Singleton doch einen viel höheren Mehrwert bedeuten
Nicht, wenn man die Kapselung nur dazu nutzt ein unikates Objek zu erzeugen.
Das kapier ich nicht.
CrystalCoder hat geschrieben:
dot hat geschrieben:Denn anstatt die Abhängigkeiten explizit im Code zu haben, sind die dann schön versteckt, sodass sie erst auffallen, wenn der Singleton zum Problem wird, sodass du ihn dann mühsam herausoperieren darfst.
Das Konzept ist ausreichend gut durchdacht dass es schon in viele Anwendungen Platz gefunden hat (laut ihm in so einigen Spieletiteln an denen der Buchautor mitgearbeitet hat).
Wenn es irgendwann mal nicht mehr ausreicht, so wird sich was neues ausgedacht wie mit allen anderen Konstrukten auch.
Und der ganze Code neu geschrieben...
CrystalCoder hat geschrieben:Davon mal abgesehen: Inwiefern macht das einen Unterschied zu dem Zugriff über eine Globale?
Ich versteh nicht, wieso du immer denkst, dass eine globale Variable das einzige ist, was man außer Singleton machen kann. Die beiden Dinge haben überhaupt nichts miteinander zu tun. Aber was die Verschleierung von Abhängigkeiten angeht hast du recht: Sowohl Singletons als auch globale Variablen verstecken Abhängigkeiten schön überall verteilt im Code, anstatt sie in den Schnittstellen offenzulegen.
CrystalCoder hat geschrieben:
dot hat geschrieben:Thread hier mal aufmerksam zu lesen, wir haben das imo wirklich schon zur Genüge diskutiert
Genau das habe ich bereits gemacht, weswegen ich eigentlich schon eine Vorstellung hatte wie man auf meine Anfrage regaieren würde.
Ich habe keine deutliche (Begründete) Aussage finden können, die exakt beschreibt, warum man "niemals Singletons benutzen" sollte.
Alles was ich hier fand war nur "Singletons sind einfach nur sch..._nicht_so_gut".
Dann hast du offenbar nur verstanden, was du verstehen wolltest. In dem Fall ist es natürlich sinnlos, noch weiter zu diskutieren...
CrystalCoder hat geschrieben:
dot hat geschrieben:Es hat Nachteile ohne einen Vorteil zu bieten
Sorry aber das sagt für mich garnichts aus. Davon abgesehen hat es sehr wohl seine Vorteile (auch wenn es nur "Bequemlichkeiten" sind wie du es nennst).
Außerdem würde man das in der Praxis nicht einsetzen wenn dem wirklich so wäre.
Natürlich, denn in der Praxis sind alle Programmierer perfekt, stets hoch motiviert und arbeiten niemals unter Zeitdruck. Ich kann dir nur empfehlen, mal im originalen GoF Buch auf Seite 127 nachzuschlagen. Dort wurde der Singleton Pattern zum ersten Mal beschrieben. Die dort als Voraussetzung für den Einsatz eines Singleton genannten Punkte, treffen auf 99.999999% aller in der Praxis existierenden Singletons nicht zu. Der Punkt ist nicht, dass der Singleton Pattern immer fehl am Platz ist. Der Punkt ist, dass Singleton praktisch immer aus dem falschen Grund eingesetzt wird: Vermeintliche Bequemlichkeit. Wieso sollte ich auch Zeit damit verschwenden, mir Gedanken darüber zu machen, wann welche Komponenten wie genau interagieren müssen, wenn ich doch einfach von überall auf alles zugreifen kann? Am Ende würde da statt einem monolithischen Haufen noch ein richtig flexibles Design rauskommen. Das wollen wir lieber nicht riskieren...
Hast du dich noch nie gefragt, wies das geben kann, dass so viele "professionelle" Spiele die rauskommen vor dem zweiten Patch praktisch bis zur Unspielbarkeit verbugged sind? Es liegt jedenfalls sicher nicht daran, dass besonders viel Wert auf saubere und durchdachte Softwarearchitektur gelegt wurde...
CrystalCoder hat geschrieben:
dot hat geschrieben:"Meine Wohnung ist das Zentrum meines täglichen Lebens. Darum darf es in meinem Leben um jeden Preis bis ans Ende aller Tage nur eine Wohnung haben."
Der Vergleich scheint mir aus der Luft gegriffen zu sein. Ich habe nicht von dem Muster allgemein gesprochen, sondern für diese eine Anwendung.
Ich wollte nur demonstrieren, dass irgendeine eben mal so getätigte Feststellung eben genau kein überzeugendes Argument für ein Singleton ist.
CrystalCoder hat geschrieben:
dot hat geschrieben:Wenn man das will. Aber warum sollte man das hier wollen?
Um es explizit hervorzuheben
Und wieso sollte man eine Eigenschaft forcieren, die man rein logisch betrachtet eben genau nicht braucht? Was hast du davon, dass du explizit verhinderst, dass es jemals zwei Instanzen deiner Komponenten geben kann? Es bringt dir im Moment keinen Vorteil, aber in der Zukunft evtl. einen riesigen Nachteil. Zwischen "Ich brauch im Moment nur eins davon" und "Es darf bis ans Ende der Zeit um jeden Preis auf keinen Fall jemals mehr als eins davon geben" gibts eben einen wesentlichen Unterschied. Singleton ist genau für Letzteres gedacht. Und genau darum praktisch immer fehl am Platz. So einen Fall hat man eben praktisch nie.
CrystalCoder hat geschrieben:
dot hat geschrieben:Wer sagt, dass eine globale Variable die Alternative ist?
Welche gäbe es denn noch, wenn man nicht extra eine Referenz auf das Objekt in jeder einzelnen Komponente haben will?
Genau das wäre eigentlich die gute Lösung: Wenn eine Komponente eine andere referenziert, dann soll sie gefälligst auch eine Referenz darauf halten. So kann man die Komponente nicht nur beliebig austauschen, was die Flexibilität des resultierenden Systems um ca. 100 Größenordnungen erhöht. Initialisierungsreihenfolgen etc. folgen auch implizit aus der sich ergebenden Schnittstelle, was irgendwelche Uneindeutigkeiten bei der Initialisierung der Komponenten schon rein prinzipiell ausschließt, da problematischer Code gar nicht erst kompiliert. Schau dir mal an, was man unter Dependency Injection versteht. Überleg z.B. mal, wie du einzelne Komponenten deines Systems isoliert testen würdest. Singletons machen Qualitätssicherung dieser Art praktisch unmöglich. Aber eben gerade in der "wirklichen Welt" wird sowas essentiell.
CrystalCoder hat geschrieben:Ich mag mich vielleicht nicht günstig ausgedrückt haben: Ich meinte nicht, dass Singletons ein Ersatz für globale Variablen sind. Mit einem Singleton kann man diese jedoch "umgehen".
Nein kann man nicht, da ein Singleton in seiner üblichen Implementierung auch nur eine globale Variable verwendet. Und eine bunte Verpackung ändert nichts am Inhalt.
CrystalCoder hat geschrieben:
dot hat geschrieben:Und eines Tages will man, dass eine Komponente in ein andres Log logged als der Rest. Gute Nacht.
Der Log ist kein Singleton und jede Komponente die ein eigenes Log haben will kann sich eine egene Instanz erstellen. Anderen Komponenten bleiben unangetastet, Problem gelöst, guten morgen!
Aber genau das ist doch der Punkt. Das Log war bis hierhin ein Singleton. Jetzt kann es plötzlich keines mehr sein. Das bedeutet, dass du nun sämtlichen Code durchforsten kannst, und jeden Aufruf von Singleton::getInstance() herausoperieren und durch entsprechende Referenzen ersetzen musst. Viel Spaß :)
Hättest du stattdessen von vornherein Referenzen übergeben, dann bräuchtest du der einen Komponente nun einfach nur ein andres Log reichen und fertig.
CrystalCoder hat geschrieben:Erlaube ich eine zweite, komplett andere Instanz, dann müssen sich die beiden Objekte die Ressourcen teilen
Das ist doch genau eine der künstlichen Einschränkungen, die du dir mit deinem Singleton erst erschaffst.
CrystalCoder hat geschrieben:Habe ich z.B. eine selbst verwaltende SceneManager Komponente, welche Daten von der Festplatte streamen kann und ich habe jetzt eine weitere Instanz der Containerklasse dann habe ich zwei SceneManager welche sich gegenseitig stören und quasi, wenn überhaupt, nur schwer synchronisiert werden können und somit gleichzeitig die Festplatte und den Datenbus in die Knie zwingen (sofern man Multithreading benutzt und wenn nicht dann hat man nur die halbe Rechenzeit).
Multithreading ist doch gerade, wo Singletons so richtig zum Problem werden, weil du dir mit jedem Singleton einen globalen Synchonisierungspunkt erschaffst!? Das zeigt nur, dass man mit Singletons heutzutage noch viel vorsichtiger sein muss, als noch vor ein paar Jahren, wo Multicore CPUs noch nicht die Norm waren...
CrystalCoder hat geschrieben:Beide GameApp Objekte würden sich um den Grafikadapter streiten, und ihre Geometrie (nach jedem "restore") zum Rendern schicken. Ist die Anwendung Multithreaded würde man die Grafikkarte schon allein durch ständiges (und überflüssiges) wechseln der Materialien ausbremsen.
Man sieht, dass du offenbar keine Ahnung hast, wovon du hier redest.
Zuletzt geändert von dot am 30.10.2011, 01:19, insgesamt 1-mal geändert.
CrystalCoder
Beiträge: 54
Registriert: 03.03.2002, 17:51
Kontaktdaten:

Re: [C++] Speicherfreigabe bei statischem Singleton

Beitrag von CrystalCoder »

@CodingCat:

Vielleicht ist das hier etwas untergegangen: Ich meinte nicht dass ich ein Singleton dazu missbrauchen würde, nur wegen dem globalen Zugriff (das wäre ja verschwendete Rechenzeit)
Primär steht eben die Konstruktionsbeschränkung im Vordergrund und der globale Zugriff ist ein Nebeneffekt davon.

Aber inwiefern habe ich Singeletons und globale Instanzen durcheinander geworfen? Ich habe von Zugriffen auf globale Objektvariablen gesprochen und den Zugriff via getInstance() gegenübergestellt.

dot hat geschrieben:In meinem Editor möchte ich vielleicht neben der 3D-Ansicht auch noch Auf-, Grund- und Seitenriss haben. Wenn meine Renderingkomponente in Singleton ist, könnte es da schon wieder schwierig werden. Warum sollte ein Ressourcen-Manager ein Singleton sein? Warum sollte es nur einen geben und vor allem: Ein Manager für alle Ressourcen? In den verschiedensten Komponenten hast du die verschiedensten Arten von Ressourcen, die alle auf völlig verschiedene Arten und Weisen gemanaged werden müssen. Ein einzelner globaler Manager kann doch schon allein unter diesem Gesichtspunkt keine gute Idee sein!?
Mooooment. Ich habe niemals davon gesprochen, dass irgendeine andere Klasse ein Singleton sein soll außer der einen GameApp Klasse, die alle anderen Klassen Gruppiert miteinander kombinieren soll.
Der Punkt ist nicht, dass der Singleton Pattern immer fehl am Platz ist. Der Punkt ist, dass Singleton praktisch immer aus dem falschen Grund eingesetzt wird
Mit der Aussage kann ich mich schon eher anfreunden. Man kann sowas eigentlcih auch garnicht verallgemeintern weil man garnicht alle Fälle kennt.
Nein kann man nicht, da ein Singleton in seiner üblichen Implementierung auch nur eine globale Variable verwendet. Und eine bunte Verpackung ändert nichts am Inhalt.
Das "umgehen" stand schon nicht ohne Grund in anführungszeichen. Mir ist schon klar dass man die Globalen damit nicht einfach wegzaubern kann. Aber der Zugriff darauf ist anders im Code, was mir wesentlich besser gefällt weil es die Lesbarkeit erhöht.
dot hat geschrieben:Aber genau das ist doch der Punkt. Das Log war bis hierhin ein Singleton
Dann hast du mich misverstanden. Die Logklasse ist kein Singleton, sondern nur (und ausschließlich) die GameApp Klasse, welche eine Basisinstanz für ein Zentrales Log enthält.
dot hat geschrieben:Das ist doch genau eine der künstlichen Einschränkungen, die du dir mit deinem Singleton erst erschaffst.
Damit war der Fall gemeint: Angenommen ich mache kein Singleton sondern nur eine normale Klasse.


Anscheinend wurde ich hier an einem wichtigen Punkt misverstanden. Nicht jede Klasse ist ein Singleton für die oben genannte Anwendung (das wäre ja unnütz und ein pures Durcheinander).

Also Beispiel: Ich habe einige Klassen

Code: Alles auswählen

CGraphics
CSceneManager
CResourceHandler
CEventHandler
CInput
//....
und ein Singleton

Code: Alles auswählen

S_CGameApp
{
/// das übliche singleton Zeug
private:
   // Instzanzen von oben genannen Klassen
}
Sollte man jetzt irgendwann mal sehen dass das Singleton Probleme macht, so kann man das ohne großen Aufwand ändern

Deswegen hab ich den Begriff "Gruppierung" gebraucht. Man verbindet sozusagen alle Klassen zu einem großen Ganzen.
Zuletzt geändert von CrystalCoder am 30.10.2011, 01:25, insgesamt 1-mal geändert.
Benutzeravatar
dot
Establishment
Beiträge: 1734
Registriert: 06.03.2004, 18:10
Echter Name: Michael Kenzel
Kontaktdaten:

Re: [C++] Speicherfreigabe bei statischem Singleton

Beitrag von dot »

D.h. dein Singleton ist also nichts anderes als ein globaler Container für globale Variablen? Verzeih meinen Sarkasmus, aber: Das klingt natürlich Super, ein Traum wird wahr! Endlich wurde es geschafft, die beiden prototypischen Anti-Pattern schlechthin zu kombinieren... ;)
CrystalCoder hat geschrieben:
dot hat geschrieben:Das ist doch genau eine der künstlichen Einschränkungen, die du dir mit deinem Singleton erst erschaffst.
Damit war der Fall gemeint: Angenommen ich mache kein Singleton sondern nur eine normale Klasse.
Und wieso solltest du gerade dann den Fall haben, dass alle Instanzen dieser Klasse irgendwie einen globalen Zustand teilen!?
CrystalCoder hat geschrieben:Sollte man jetzt irgendwann mal sehen dass das Singleton Probleme macht, so kann man das ohne großen Aufwand ändern
So? Wie würdest du das denn einfach ändern, wo doch dein ganzer Code voller Aufrufe an Singleton::getInstance() ist?
Zuletzt geändert von dot am 30.10.2011, 01:30, insgesamt 1-mal geändert.
CrystalCoder
Beiträge: 54
Registriert: 03.03.2002, 17:51
Kontaktdaten:

Re: [C++] Speicherfreigabe bei statischem Singleton

Beitrag von CrystalCoder »

D.h. dein Singleton ist also nichts anderes als ein Container für globale Variablen? Verzeih meinen Sarkasmus, aber: Das klingt natürlich Super, ein Traum wird wahr! Endlich wurde es geschafft, die beiden prototypischen Anti-Pattern schlechthin zu kombinieren... ;)
Das war ja jetzt keine Feststellung, dass man es ja so machen könnte, sondern ich wollte wissen wie ihr dazu steht sowas zu machen.
dot hat geschrieben:
CrystalCoder hat geschrieben:
dot hat geschrieben:Das ist doch genau eine der künstlichen Einschränkungen, die du dir mit deinem Singleton erst erschaffst.
Damit war der Fall gemeint: Angenommen ich mache kein Singleton sondern nur eine normale Klasse.
Und wieso solltest du gerade dann den Fall haben, dass alle Instanzen dieser Klasse irgendwie einen globalen Zustand teilen!?
Muss nicht so sein, aber ich will es nicht ausschließen
So? Wie würdest du das denn einfach ändern, wo doch dein ganzer Code voller Aufrufe an Singleton::getInstance() ist?
Nicht so einfach wie ich mir das gerade gedacht habe. Je nach Anzahl der Komponenten könnte es evtl doch hässlich werden, aber eigentlich sehe ich garkeinen Sinn dass wieder umstellen zu müssen. Das ist ja im Prinzip der Grundgedanke wo alles drauf aufbaut.
Zuletzt geändert von CrystalCoder am 30.10.2011, 01:44, insgesamt 3-mal geändert.
Benutzeravatar
dot
Establishment
Beiträge: 1734
Registriert: 06.03.2004, 18:10
Echter Name: Michael Kenzel
Kontaktdaten:

Re: [C++] Speicherfreigabe bei statischem Singleton

Beitrag von dot »

CrystalCoder hat geschrieben:Das ist ja im Prinzip der Grundgedanke wo alles drauf aufbaut.
Und genau diesen Grundgedanken würde ich an deiner Stelle aufs Heftigste hinterfragen...
CrystalCoder
Beiträge: 54
Registriert: 03.03.2002, 17:51
Kontaktdaten:

Re: [C++] Speicherfreigabe bei statischem Singleton

Beitrag von CrystalCoder »

dot hat geschrieben:
CrystalCoder hat geschrieben:Das ist ja im Prinzip der Grundgedanke wo alles drauf aufbaut.
Und genau diesen Grundgedanken würde ich an deiner Stelle aufs Heftigste hinterfragen...
Weswegen?
Benutzeravatar
dot
Establishment
Beiträge: 1734
Registriert: 06.03.2004, 18:10
Echter Name: Michael Kenzel
Kontaktdaten:

Re: [C++] Speicherfreigabe bei statischem Singleton

Beitrag von dot »

Einfach mal so...
Benutzeravatar
CodingCat
Establishment
Beiträge: 1857
Registriert: 02.03.2009, 21:25
Wohnort: Student @ KIT
Kontaktdaten:

Re: [C++] Speicherfreigabe bei statischem Singleton

Beitrag von CodingCat »

CrystalCoder hat geschrieben:Aber inwiefern habe ich Singeletons und globale Instanzen durcheinander geworfen? Ich habe von Zugriffen auf globale Objektvariablen gesprochen und den Zugriff via getInstance() gegenübergestellt.
Zwischen dem Zugriff auf eine beliebige globale Instanz und eine Singleton-Instanz via getInstance() besteht kein Unterschied. Genau hier wirfst du sie durcheinander, WEIL das Singleton-Muster alleine der Konstruktionsbeschränkung dient, und NICHT dem globalen Zugriff, den du genauso mit wie ohne Singleton haben kannst.
CrystalCoder hat geschrieben:Dann hast du mich misverstanden. Die Logklasse ist kein Singleton, sondern nur (und ausschließlich) die GameApp Klasse, welche eine Basisinstanz für ein Zentrales Log enthält.
[...]
Anscheinend wurde ich hier an einem wichtigen Punkt misverstanden. Nicht jede Klasse ist ein Singleton für die oben genannte Anwendung (das wäre ja unnütz und ein pures Durcheinander).
Das ändert aber nichts. In beiden Fällen verschleierst du mit jedem Aufruf von getInstance() globalen Zugriff und rennst in die Falle von unabsehbaren Seiteneffekte, undurchsichtigen Abhängigkeiten, geringerer Flexibilität, geringer Wiederverwendbarkeit.

Wenn du eine GameApp-Klasse tatsächlich alleine mit der Absicht der Konstruktionsbeschränkung als Singleton implementieren wolltest, dann wäre das einzig Richtige, getInstance() genau einmal zu Beginn des Programms aufzurufen, und die zurückgegebene Instanz von da an nur noch als Argument weiterzugeben. Und ich frage mich wirklich, ob du dann das Singleton noch brauchst. ;)

- ENDE SINGLETON -

Wenn wir schon dabei sind, bringen wir die Sache auch noch konsequent zu Ende: Nachdem wir das Singleton losgeworden sind, bleibt der GameApp-Container. Auch derlei Sammelkonstrukte sind, soweit ich das beurteilen kann, recht verbreitet. Tatsächlich wird es mit der Zeit lästig, all die Abhängigkeiten stets einzeln an die jeweiligen Komponenten zu übergeben - ein Problem, bei dem eine solche Container-Klasse leicht Abhilfe schaffen kann - jedoch auch hier mit nicht zu unterschätzenden Auswirkungen.

Auch wenn dot schon darauf eingegangen ist, möchte ich deshalb deine Aussagen nochmal kurz unter diesem Aspekt kommentieren.
CrystalCoder hat geschrieben:Habe ich z.B. eine selbst verwaltende SceneManager Komponente, welche Daten von der Festplatte streamen kann und ich habe jetzt eine weitere Instanz der Containerklasse dann habe ich zwei SceneManager welche sich gegenseitig stören und quasi, wenn überhaupt, nur schwer synchronisiert werden können und somit gleichzeitig die Festplatte und den Datenbus in die Knie zwingen (sofern man Multithreading benutzt und wenn nicht dann hat man nur die halbe Rechenzeit).
Wie dot sagt, sind prinzipiell zwei UNABHÄNGIGE SceneManager-Instanzen genau das, was man möchte, weil sie KEINE anwendungsseitige Synchronisation erfordern. Dass sich dabei beide Instanzen die Kapazitäten des Systems teilen, ist auch vollkommen in Ordnung, schließlich wurden zwei gleichberechtigte Anfragen zur gleichen Zeit gestellt, die nun bei gleicher (halber) Geschwindigkeit gleichberechtigt abgearbeitet werden.

Der Fall, den du beschreibst, wäre, zusätzliches Wissen über die Priorität oder Kohärenz der Anfragen zu nutzen, um bestimmte Anfragen bevorzugen oder geteilte Anfragen beschleunigen zu können. Man beachte, dass dieser Fall ggf. aufwändige anwendungsseitige Synchronisation erfordert, welche den Code wesentlich verkompliziert und ggf. den Normalfall des synchronen Programmablaufs verlangsamt.

Erscheint diese Art der Teilung mit mehreren GameApp-Instanzen zunächst unmöglich, so zeigt sich der eigentliche Entwurfsfehler dieses Objekts: Es forciert entweder vollständige Teilung oder vollständige Trennung ALLER enthaltenen Komponenten. Gewisse Komponenten möchte man aber auf gar keinen Fall teilen:
CrystalCoder hat geschrieben:Beide GameApp Objekte würden sich um den Grafikadapter streiten, und ihre Geometrie (nach jedem "restore") zum Rendern schicken. Ist die Anwendung Multithreaded würde man die Grafikkarte schon allein durch ständiges (und überflüssiges) wechseln der Materialien ausbremsen.
Wenn ich also sowieso nur Probleme mit mehreren Objekten habe, warum dann nicht ausschließen, dass so etwas vorkommt?
Wie dot schon sagte, ist das absoluter Blödsinn. Dieses Verhalten hast du nämlich GENAU DANN, WENN sich Komponenten in mehreren Threads denselben Device-Context (oder auch nur dasselbe Device, je nach Grafik-API) teilen.

Richtig wäre, jedem Thread ein eigenes Device-Context (oder Device) zu geben, welches jeweils für sich die gemachten API-Calls aufzeichnet, und am Ende snychronisiert in den Kommando-Puffer des Systems überträgt, wo die jeweils aufgezeichneten Kommandos korrekt nacheinander ausgeführt würden.

Was lernen wir daraus? Das Teilen von Komponenten ist im Allgemeinen nie wünschenswert. In wenigen Einzelfällen kann es jedoch sinnvoll sein, weswegen guter Entwurf Teilbarkeit weder forcieren noch ausschließen sollte. Eine GameApp-Klasse lässt sich problemlos entsprechend anpassen, dass die gespeicherten Komponenten jede für sich ENTWEDER neu erstellt ODER geteilt werden können. Ich selbst versuche jedoch, solche Container-Klassen zu vermeiden, weil sie für jede damit arbeitende Klasse zusätzliche Abhängigkeiten zu allen enthaltenen geteilten Komponenten einführt, obwohl die Klasse in der Regel nur ein winziges Subset dieser tatsächlich nutzt.
alphanew.net (last updated 2011-07-02) | auf Twitter | Source Code: breeze 2 | lean C++ library | D3D Effects Lite
CrystalCoder
Beiträge: 54
Registriert: 03.03.2002, 17:51
Kontaktdaten:

Re: [C++] Speicherfreigabe bei statischem Singleton

Beitrag von CrystalCoder »

CodingCat hat geschrieben:Zwischen dem Zugriff auf eine beliebige globale Instanz und eine Singleton-Instanz via getInstance() besteht kein Unterschied. Genau hier wirfst du sie durcheinander, WEIL das Singleton-Muster alleine der Konstruktionsbeschränkung dient, und NICHT dem globalen Zugriff, den du genauso mit wie ohne Singleton haben kannst.
Das ist mir bewusst, es ging mir nie darum Globales loszuwerden, sondern den Zugriff zu verändern, so dass er leichter im Code herauszulesen ist.
Der Zweck des Singletons ist hier auch die Konstruktionsbeschränkung. Der globale Zugriff ist eine Folge davon.
CodingCat hat geschrieben:Wenn du eine GameApp-Klasse tatsächlich alleine mit der Absicht der Konstruktionsbeschränkung als Singleton implementieren wolltest, dann wäre das einzig Richtige, getInstance() genau einmal zu Beginn des Programms aufzurufen, und die zurückgegebene Instanz von da an nur noch als Argument weiterzugeben. Und ich frage mich wirklich, ob du dann das Singleton noch brauchst.
Sowas hab ich mir auch schon überlegt. Ich versuche globale Zugriffe eigentlich immer so gering wie möglich zu halten (sei es nun ein Singleton oder eine globale Instanzvariable).
CodingCat hat geschrieben:Tatsächlich wird es mit der Zeit lästig, all die Abhängigkeiten stets einzeln an die jeweiligen Komponenten zu übergeben - ein Problem, bei dem eine solche Container-Klasse leicht Abhilfe schaffen kann - jedoch auch hier mit nicht zu unterschätzenden Auswirkungen.
Etwas ähnliches hat Mike in seinem Buch auch als einen der Gründe genannt.
CodingCat hat geschrieben:Wie dot schon sagte, ist das absoluter Blödsinn. Dieses Verhalten hast du nämlich GENAU DANN, WENN sich Komponenten in mehreren Threads denselben Device-Context (oder auch nur dasselbe Device, je nach Grafik-API) teilen.

Richtig wäre, jedem Thread ein eigenes Device-Context (oder Device) zu geben, welches jeweils für sich die gemachten API-Calls aufzeichnet, und am Ende snychronisiert in den Kommando-Puffer des Systems überträgt, wo die jeweils aufgezeichneten Kommandos korrekt nacheinander ausgeführt würden.
Eigentlich bin ich davon ausgeangen, dass es Probleme geben würde, wenn ich zwei Grafikkomponenten gleichzeitig erzeuge, weil jede eigene Renderpuffer erzeugt und auch die Grafikeinstellungen vornimmt, wie Auflösung, etc.
Allerdings hab ich noch kein Miltithreaded Rendering versucht und weiß nicht exakt wie man das anstellt.
CodingCat hat geschrieben:Was lernen wir daraus? Das Teilen von Komponenten ist im Allgemeinen nie wünschenswert. In wenigen Einzelfällen kann es jedoch sinnvoll sein, weswegen guter Entwurf Teilbarkeit weder forcieren noch ausschließen sollte. Eine GameApp-Klasse lässt sich problemlos entsprechend anpassen, dass die gespeicherten Komponenten jede für sich ENTWEDER neu erstellt ODER geteilt werden können. Ich selbst versuche jedoch, solche Container-Klassen zu vermeiden, weil sie für jede damit arbeitende Klasse zusätzliche Abhängigkeiten zu allen enthaltenen geteilten Komponenten einführt, obwohl die Klasse in der Regel nur ein winziges Subset dieser tatsächlich nutzt.
Für bestimmte Sachen wie z.B. Event Management ist es aber dann kaum möglich Abhängigkeiten gering zu halten, weil im Prinzip fast jede andere Komponente seine Kommunikation damit ausführt, dass es dem EventManager einen Listener hinzufügen müsste. Wenn ich jetzt jeder einzelnen Klasse ein gemeinsames Objekt des Event Managers geben müsste, nur für den Zweck, einen Listener registrieren zu können, dann wär das auch schon mal garnicht so schön mitanzusehen (und umzusetzen).
Wenn dann noch mehr solche Sachen hinzukommen (wie z.B. ein Prozess Manager) dann häuft sich das. Ich find das Designtechnisch mindestens genauso unschön, als wenn ich ein Sammelobjekt verwenden würde.
Benutzeravatar
dot
Establishment
Beiträge: 1734
Registriert: 06.03.2004, 18:10
Echter Name: Michael Kenzel
Kontaktdaten:

Re: [C++] Speicherfreigabe bei statischem Singleton

Beitrag von dot »

CrystalCoder hat geschrieben:
CodingCat hat geschrieben:Was lernen wir daraus? Das Teilen von Komponenten ist im Allgemeinen nie wünschenswert. In wenigen Einzelfällen kann es jedoch sinnvoll sein, weswegen guter Entwurf Teilbarkeit weder forcieren noch ausschließen sollte. Eine GameApp-Klasse lässt sich problemlos entsprechend anpassen, dass die gespeicherten Komponenten jede für sich ENTWEDER neu erstellt ODER geteilt werden können. Ich selbst versuche jedoch, solche Container-Klassen zu vermeiden, weil sie für jede damit arbeitende Klasse zusätzliche Abhängigkeiten zu allen enthaltenen geteilten Komponenten einführt, obwohl die Klasse in der Regel nur ein winziges Subset dieser tatsächlich nutzt.
Für bestimmte Sachen wie z.B. Event Management ist es aber dann kaum möglich Abhängigkeiten gering zu halten, weil im Prinzip fast jede andere Komponente seine Kommunikation damit ausführt, dass es dem EventManager einen Listener hinzufügen müsste. Wenn ich jetzt jeder einzelnen Klasse ein gemeinsames Objekt des Event Managers geben müsste, nur für den Zweck, einen Listener registrieren zu können, dann wär das auch schon mal garnicht so schön mitanzusehen (und umzusetzen).
Wenn dann noch mehr solche Sachen hinzukommen (wie z.B. ein Prozess Manager) dann häuft sich das. Ich find das Designtechnisch mindestens genauso unschön, als wenn ich ein Sammelobjekt verwenden würde.
Wofür sollte man all diese Manager überhaupt brauchen? Meiner Erfahrung nach sagt eine Klasse, deren Name auf "Manager" endet, fast immer folgendes: "Ich hab eigentlich keine Ahnung wohin damit, also stell ich erstmal alles dort ins Eck". In sauber designetem Code, sieht man solche Klassen verdächtig selten...
CrystalCoder
Beiträge: 54
Registriert: 03.03.2002, 17:51
Kontaktdaten:

Re: [C++] Speicherfreigabe bei statischem Singleton

Beitrag von CrystalCoder »

dot hat geschrieben:Wofür sollte man all diese Manager überhaupt brauchen? Meiner Erfahrung nach sagt eine Klasse, deren Name auf "Manager" endet, fast immer folgendes: "Ich hab eigentlich keine Ahnung wohin damit, also stell ich erstmal alles dort ins Eck". In sauber designetem Code, sieht man solche Klassen verdächtig selten...
Sinn davon ist doch die Vereinfachung der entsprechenden Sachen die gemanaged werden sollen und Effizienzsteigerung, wenn man es geschickt anstellt.
Eigentlich ist es doch recht üblich für Events, Ressourcen, Prozesse, Module, etc. managen zu lassen.
Ich will den Code einmal schreiben und später einfach darauf zurückgreifen und diesen möglichst nicht mehr anfassen zu müssen.
Ich finde es jedenfalls besser eine spiezialisierte Klasse zu haben, die, wenn richtig implementiert, sämliche Schmutzarbeit abnimmt, sodass ich mich um das eigentliche Ziel kümmern kann.

EDIT: Am Beispiel des Event Managers würde man erstmal alle in seiner Applikation möglichen Events registrieren und während der Programmlaufzeit können verschiedene Komponenten einen oder mehrere Listener bei ihm registrieren.
Der Eventmanager soll nun alle eingehenden Events an die registrierten Listener (der einzelnen Komponenten) verteilen.
Ich hab z.B. eine Input Klasse, die einen Mausklick registriert und daraufhin ein Event sendet. Nun hat man z.B. zwei Komponenten, die auf derartige Events warten. 1. eine GUI-Komponente, die prüft ob ein Button geklickt wurde. Und 2. eine Sound Komponente, die bei jedem Klick einen Sound ausgeben will.

Es wäre doch extrem unflexibel, wenn jede Komponente selbstständig die Input States prüfen müsste.
Angenommen der Sound soll nur kommen, wenn die GUI-Komponente keinen Button-Klick feststellt. Dann Würde die GUI entsprechend bei Button-Klicks das Event aufbrauchen und quasi verhindern dass andere Komponenten das Event bekommen. Das könnte man dann nicht so einfach machen, wenn man Input States in jeder Komponente selbst prüft.
Zuletzt geändert von CrystalCoder am 30.10.2011, 15:18, insgesamt 1-mal geändert.
Benutzeravatar
dot
Establishment
Beiträge: 1734
Registriert: 06.03.2004, 18:10
Echter Name: Michael Kenzel
Kontaktdaten:

Re: [C++] Speicherfreigabe bei statischem Singleton

Beitrag von dot »

Ich finds besser auf Schmutzarbeit ganz zu verzichten ;)
Benutzeravatar
CodingCat
Establishment
Beiträge: 1857
Registriert: 02.03.2009, 21:25
Wohnort: Student @ KIT
Kontaktdaten:

Re: [C++] Speicherfreigabe bei statischem Singleton

Beitrag von CodingCat »

CrystalCoder hat geschrieben:Der Zweck des Singletons ist hier auch die Konstruktionsbeschränkung. Der globale Zugriff ist eine Folge davon.
Globaler Zugriff ist nie eine Folge von Singletons, sondern von falscher Benutzung derselben.
CrystalCoder hat geschrieben:Sowas hab ich mir auch schon überlegt. Ich versuche globale Zugriffe eigentlich immer so gering wie möglich zu halten (sei es nun ein Singleton oder eine globale Instanzvariable).
Genau.
CrystalCoder hat geschrieben:
CodingCat hat geschrieben:Tatsächlich wird es mit der Zeit lästig, all die Abhängigkeiten stets einzeln an die jeweiligen Komponenten zu übergeben - ein Problem, bei dem eine solche Container-Klasse leicht Abhilfe schaffen kann - jedoch auch hier mit nicht zu unterschätzenden Auswirkungen.
Etwas ähnliches hat Mike in seinem Buch auch als einen der Gründe genannt.
Na dann. Ich hoffe es wurde klar, dass das nur die Einleitung war, und ich schlussendlich kein Freund der Verbreitung solcher Container-Klassen bin, siehe vorangegangenen Post.
CrystalCoder hat geschrieben:Eigentlich bin ich davon ausgeangen, dass es Probleme geben würde, wenn ich zwei Grafikkomponenten gleichzeitig erzeuge, weil jede eigene Renderpuffer erzeugt und auch die Grafikeinstellungen vornimmt, wie Auflösung, etc.
Allerdings hab ich noch kein Miltithreaded Rendering versucht und weiß nicht exakt wie man das anstellt.
Probleme gibt es nur, wenn du dieselbe Grafikkomponente einfach so in verschiedenen Threads teilst, nie bei mehreren Komponenten.
CrystalCoder hat geschrieben:Für bestimmte Sachen wie z.B. Event Management ist es aber dann kaum möglich Abhängigkeiten gering zu halten, weil im Prinzip fast jede andere Komponente seine Kommunikation damit ausführt, dass es dem EventManager einen Listener hinzufügen müsste. Wenn ich jetzt jeder einzelnen Klasse ein gemeinsames Objekt des Event Managers geben müsste, nur für den Zweck, einen Listener registrieren zu können, dann wär das auch schon mal garnicht so schön mitanzusehen (und umzusetzen).
Wenn dann noch mehr solche Sachen hinzukommen (wie z.B. ein Prozess Manager) dann häuft sich das. Ich find das Designtechnisch mindestens genauso unschön, als wenn ich ein Sammelobjekt verwenden würde.
Ich verstehe das Problem nicht mal, aber ich versuche trotzdem, darauf einzugehen: Ein zentraler Event-Manager ist Unsinn. Welche Events sollten das denn bitte sein, die für alle Objekte übereinstimmen? Ich hoffe, du strebst kein Nachrichtensystem nach Windows-Vorbild an, in dem alles per untypisiertem Zeiger mittels switch/case an die richtigen Methoden weitergeleitet wird. Jedes Subsystem hat in der Regel sein eigenes Set von Nachrichten, die vollständig typisiert sind und ausschließlich innerhalb des Subsystems ausgetauscht werden müssen.

Was ein Prozess-Manager tun sollte, ist mir ebenfalls schleierhaft, in allen Fällen würden in einer guten Architektur jegliche Managers nur von sehr bestimmten Objekten gebraucht, an welche diese sich sehr wohl als Argument durchreichen ließen.
alphanew.net (last updated 2011-07-02) | auf Twitter | Source Code: breeze 2 | lean C++ library | D3D Effects Lite
CrystalCoder
Beiträge: 54
Registriert: 03.03.2002, 17:51
Kontaktdaten:

Re: [C++] Speicherfreigabe bei statischem Singleton

Beitrag von CrystalCoder »

Ein zentraler Event-Manager ist Unsinn.
Eigentlich macht das sehr wohl sinn, weil damit die Kommunikation zwischen beliebigen Komponenten ermöglicht wird.
Ich hoffe, du strebst kein Nachrichtensystem nach Windows-Vorbild an, in dem alles per untypisiertem Zeiger mittels switch/case an die richtigen Methoden weitergeleitet wird.
Nein, es ist alles voll typisiert über Event Interfaces. Es kommt aber einem Nachrichtensystem sehr nahe.
Was ein Prozess-Manager tun sollte, ist mir ebenfalls schleierhaft, in allen Fällen würden in einer guten Architektur jegliche Managers nur von sehr bestimmten Objekten gebraucht, an welche diese sich sehr wohl als Argument durchreichen ließen.
Mit Prozess ist ein vorgang gemeint, der sich über mehrere Frames verteilt.

Z.B. Intro: Man startet ein Video und das läuft einige Zeit (oder man macht irgendwas anderes mit selbst gerenderten Sachen, was auch immer). Ist das Video vorbei wird der Prozess als beendet erklärt und man kann wenn man will einen weiteren Prozess anhängen via "next";
Man kann damit ganze Ketten von Prozessen erzeugen und am schluß könnte man ein Event verschicken wie "ProcessQuit" oder was auch immer.


Das ganze ist übrigens nicht mein eigenes Design. Ich erkläre hier nur wie Mike es verwendet.
Benutzeravatar
dot
Establishment
Beiträge: 1734
Registriert: 06.03.2004, 18:10
Echter Name: Michael Kenzel
Kontaktdaten:

Re: [C++] Speicherfreigabe bei statischem Singleton

Beitrag von dot »

CrystalCoder hat geschrieben:
Ein zentraler Event-Manager ist Unsinn.
Eigentlich macht das sehr wohl sinn, weil damit die Kommunikation zwischen beliebigen Komponenten ermöglicht wird.
Und wofür braucht es da einen EventManager? Wenn zwei Komponenten miteiander kommunizieren müssen, dann sollen sie das doch bitte einfach direkt tun!? Dein Eventmanager ist schon wieder nur ein unnötiger, globaler Synchronisierungspunkt.
Zuletzt geändert von dot am 30.10.2011, 15:40, insgesamt 1-mal geändert.
Benutzeravatar
Chromanoid
Moderator
Beiträge: 4263
Registriert: 16.10.2002, 19:39
Echter Name: Christian Kulenkampff
Wohnort: Lüneburg

Re: [C++] Speicherfreigabe bei statischem Singleton

Beitrag von Chromanoid »

Naja Publish/Subscribe-artige Strukturen sind schon sinnvoll. Aber man muss so einen "EventBus" nicht unbedingt als Singleton implementieren. Singletons sind praktisch, wenn es schnell gehen muss, aber eigentlich reichen dann auch globale Variablen. Der Umstieg von Singleton auf eine flexiblere Struktur ist allerdings evt. leichter als von globalen Variablen wegzukommen.
Zuletzt geändert von Chromanoid am 30.10.2011, 15:41, insgesamt 1-mal geändert.
Benutzeravatar
dot
Establishment
Beiträge: 1734
Registriert: 06.03.2004, 18:10
Echter Name: Michael Kenzel
Kontaktdaten:

Re: [C++] Speicherfreigabe bei statischem Singleton

Beitrag von dot »

Ich seh absolut nicht den Nutzen im gegebenen Kontext.
Benutzeravatar
Chromanoid
Moderator
Beiträge: 4263
Registriert: 16.10.2002, 19:39
Echter Name: Christian Kulenkampff
Wohnort: Lüneburg

Re: [C++] Speicherfreigabe bei statischem Singleton

Beitrag von Chromanoid »

Naja man kann damit die Beobachter von den Nachrichtproduzenten entkoppeln. Komponenten müssen dann nur noch wissen welche Events sie brauchen, nicht wo sie sich dafür eintragen müssen bzw. es liegt eben eine allgemeine Stelle dafür vor.
http://guava-libraries.googlecode.com/s ... mmary.html ist vielleicht ganz interessant in diesem Zusammenhang. Im FAQ wird auch gleich beantwortet, warum das ganze nicht als Singleton implementiert wurde.
Why must I create my own Event Bus, rather than using a singleton?
The Event Bus doesn't specify how you use it; there's nothing stopping your application from having separate EventBus instances for each component, or using separate instances to separate events by context or topic. This also makes it trivial to set up and tear down EventBus objects in your tests.
Of course, if you'd like to have a process-wide EventBus singleton, there's nothing stopping you from doing it that way. Simply have your container (such as Guice) create the EventBus as a singleton at global scope (or stash it in a static field, if you're into that sort of thing).

In short, the EventBus is not a singleton because we'd rather not make that decision for you. Use it how you like.
Man registriert Objekte bei beliebig vielen EventBus-Objekten. Diese suchen sich per Reflexion aus den registrierten Objekten die receiveMessage Methoden raus. Die Methoden bekommen dann natürlich nur Nachrichten ab, die dem Typ des Parameters entsprechen. In C++ müsste man das mit Templates oder so eigentlich auch so hinbekommen...
Benutzeravatar
dot
Establishment
Beiträge: 1734
Registriert: 06.03.2004, 18:10
Echter Name: Michael Kenzel
Kontaktdaten:

Re: [C++] Speicherfreigabe bei statischem Singleton

Beitrag von dot »

Und was genau hat man davon? Man könnte stattdessen die Methoden der Komponenten direkt aufrufen. Das wäre einfach, effizient und unkompliziert.
Benutzeravatar
Chromanoid
Moderator
Beiträge: 4263
Registriert: 16.10.2002, 19:39
Echter Name: Christian Kulenkampff
Wohnort: Lüneburg

Re: [C++] Speicherfreigabe bei statischem Singleton

Beitrag von Chromanoid »

Naja dann müssen die Objekte ja irgendwie von einander wissen. Wie wäre es mit sowas: Eine Wache soll in Alarmbereitschaft gehen, wenn bestimmte Dinge im Spiel passieren. Zum Beispiel wenn eine Tür in gewisser Entfernung eingeschlagen wird. Jetzt will man ja nicht jeden Wachmann bei jeder Tür als Observer eintragen. Die Türen vermelden das Einschlagsereignis bei einem "gemeinsamen" Bekannten (der Wachmann braucht von seiner Bekanntheit nichts wissen)... Oder wie würdest du das lösen?
Zuletzt geändert von Chromanoid am 30.10.2011, 17:11, insgesamt 1-mal geändert.
Benutzeravatar
Krishty
Establishment
Beiträge: 8268
Registriert: 26.02.2009, 11:18
Benutzertext: state is the enemy
Kontaktdaten:

Re: [C++] Speicherfreigabe bei statischem Singleton

Beitrag von Krishty »

Indem jede Wache bei jeder Aktualisierung alle emittierten Geräusche verarbeitet und die KI den Zustand ändert, falls sie dabei ein Scheppergeräusch wahrnimmt?

Events sind scheiße und nur für absolute Ausnahmefälle notwendig. Event-Systeme zu moellieren macht das nur noch irrsinniger.
seziert Ace Combat, Driver, und S.T.A.L.K.E.R.   —   rendert Sterne
Benutzeravatar
Chromanoid
Moderator
Beiträge: 4263
Registriert: 16.10.2002, 19:39
Echter Name: Christian Kulenkampff
Wohnort: Lüneburg

Re: [C++] Speicherfreigabe bei statischem Singleton

Beitrag von Chromanoid »

Wie bekommen die Wachen denn die "emittierten Geräusche" mit? Ist das nicht auch ein verkapptes Eventsystem?
Benutzeravatar
Krishty
Establishment
Beiträge: 8268
Registriert: 26.02.2009, 11:18
Benutzertext: state is the enemy
Kontaktdaten:

Re: [C++] Speicherfreigabe bei statischem Singleton

Beitrag von Krishty »

Jeder Funktionsaufruf; gar jedes Mnemonic ist ein verkapptes Ereignis. Wenn du damit unbedingt recht haben willst, bitte ;)

Mitbekommen erledigen dann eben fünf Zeilen Quelltext an der Stelle, die sowieso dafür sorgt, dass die KI irgendwann weiteriteriert. Und nicht eine 2000 Zeilen schwere Bibliothek. Und, vor allem: viel einfacher einschätzbar betreffend Wirkung und Laufzeit.
(Nur so: Falls gefordert, kann man das zu einem Äthersystem ausbauen – wenn bspw. Funksprüche auf verschiedenen Frequenzen ausgesandt und durch Umgebungswirkung wie Atmosphäre und Terrain beeinträchtigt werden müssen. Ist ganz geil.)
seziert Ace Combat, Driver, und S.T.A.L.K.E.R.   —   rendert Sterne
Benutzeravatar
Chromanoid
Moderator
Beiträge: 4263
Registriert: 16.10.2002, 19:39
Echter Name: Christian Kulenkampff
Wohnort: Lüneburg

Re: [C++] Speicherfreigabe bei statischem Singleton

Beitrag von Chromanoid »

Naja in diesem Fall ist das ganze doch mehr ein Eventsystem als normales Methoden aufrufen. Schließlich gibt es doch sicher eine Art Liste mit den geposteten Geräuschen (Events). Diese Liste wird dann immutable einmal an alle, die sich dafür interessieren übergeben. So ein Konzept kann man dann doch auch gleich ein bisschen abstrahieren und in ein allgemeines System überführen. Ich finde das Google Guava Zeug ziemlich elegant. Und ohne die Utility Abhängigkeiten wie einen Cache oder Multimap ist der Code vom EventBus sehr schlank siehe EventBus.java bzw. com.google.common.eventbus. Btw sorry für das Offtopic...
Benutzeravatar
Krishty
Establishment
Beiträge: 8268
Registriert: 26.02.2009, 11:18
Benutzertext: state is the enemy
Kontaktdaten:

Re: [C++] Speicherfreigabe bei statischem Singleton

Beitrag von Krishty »

Chromanoid hat geschrieben:Naja in diesem Fall ist das ganze doch mehr ein Eventsystem als normales Methoden aufrufen.
Nö:
Chromanoid hat geschrieben:Schließlich gibt es doch sicher eine Art Queue mit den geposteten Geräuschen (Events). Diese Queue wird dann immutable einmal an alle, die sich dafür interessieren übergeben.
Nö, an alle. Das ist ja genau der Unterschied – weder kennen Geräusche Wachen, noch kennen Wachen Geräusche, noch kennt der Äther persönliche Interessen der Wachen, die sich in ihm bewegen.
Chromanoid hat geschrieben:So ein Konzept kann man dann doch auch gleich ein bisschen abstrahieren und in ein allgemeines System überführen.
Das Konzept heißt Feld mit for_each. Ich weiß nicht, was es da noch sinnvoll zu abstrahieren gäbe.
Chromanoid hat geschrieben:kann man dann doch auch gleich
Das ist haargenau das Problem bei allen überfrachteten, gewucherten, unwartbar gewordenen Architekturen, mit denen ich ständig zu tun habe: Das die Leute nicht kapieren, dass es beim Programmentwurf nicht darum geht, festzulegen, was das Programm können soll, sondern darum, was es nicht können soll und dass man nichts tun sollte, nur, weil man es kann.
seziert Ace Combat, Driver, und S.T.A.L.K.E.R.   —   rendert Sterne
Benutzeravatar
Chromanoid
Moderator
Beiträge: 4263
Registriert: 16.10.2002, 19:39
Echter Name: Christian Kulenkampff
Wohnort: Lüneburg

Re: [C++] Speicherfreigabe bei statischem Singleton

Beitrag von Chromanoid »

Krishty hat geschrieben:
Chromanoid hat geschrieben:kann man dann doch auch gleich
Das ist haargenau das Problem bei allen überfrachteten, gewucherten, unwartbar gewordenen Architekturen, mit denen ich ständig zu tun habe: Das die Leute nicht kapieren, dass es beim Programmentwurf nicht darum geht, festzulegen, was das Programm können soll, sondern darum, was es nicht können soll und dass man nichts tun sollte, nur, weil man es kann.
Es gibt viele Stellen an denen das stimmt, ich selbst tendiere dazu zu viel zu abstrahieren. Es gilt doch ein Gleichgewicht zwischen Abstraktion und Funktionalität zu finden. An dieser Stelle halte ich das für sinnvoll.
Kannst du mir mehr von deinem Äther erzählen? Bisher halte ich ihn für entweder einen globalen EventBus oder einen noch gruseligeren monolithischen Komplex, der sich nur für Spieleentwicklung eignet :).
Benutzeravatar
Krishty
Establishment
Beiträge: 8268
Registriert: 26.02.2009, 11:18
Benutzertext: state is the enemy
Kontaktdaten:

Re: [C++] Speicherfreigabe bei statischem Singleton

Beitrag von Krishty »

Chromanoid hat geschrieben:Kannst du mir mehr von deinem Äther erzählen? Bisher halte ich ihn für entweder einen globalen EventBus oder einen noch gruseligeren monolithischen Komplex, der sich nur für Spieleentwicklung eignet :).
Einfach ein Array mit den Geräuschen, die im aktuellen Frame so vorgefallen sind :)

(Oder, falls du dich speziell auf den beziehst, den ich geschrieben habe: Den werde ich im Kontext dieser Diskussion garantiert nicht als Beispiel heranziehen, weil die Anforderungen ein bisschen anders als im Wache-Tür-Beispiel sind und ich ihn auf einem XAudio2-Filter-Objekt aufbauen musste ;) )
seziert Ace Combat, Driver, und S.T.A.L.K.E.R.   —   rendert Sterne
Benutzeravatar
Chromanoid
Moderator
Beiträge: 4263
Registriert: 16.10.2002, 19:39
Echter Name: Christian Kulenkampff
Wohnort: Lüneburg

Re: [C++] Speicherfreigabe bei statischem Singleton

Beitrag von Chromanoid »

Und wie löst du Dinge aufgrund dieses Arrays aus, wenn folgendes gilt?
Krishty hat geschrieben:weder kennen Geräusche Wachen, noch kennen Wachen Geräusche, noch kennt der Äther persönliche Interessen der Wachen, die sich in ihm bewegen.
Zur Abstraktion/Entkopplung noch ein netter webcomic ^^
Bild
Antworten