S
Ist eine Weile her, aber ich hatte viel tun (nicht nur Programmieren).
Mechanics schrieb:
seelenquell schrieb:
Ich werde das Singleton für den Global Event Manager vermutlich auch als hauptsächlich als interne statische Variable (oder Klasse) der normalen Eventmanager Klasse verwenden, damit jeder Eventmanager bestimmte Informationen an den Globalen Eventmanager weiterleiten kann (z.b. registrieren sich diese dort).
Sowas haben wir sicherlich auch öfter mal in unserer Software... Nur stört es immer, wenn man dann plötzlich mehreren Instanzen von dem ganzen System haben will. Das kann man im Voraus alles schlecht abschätzen. Irgendwann wird dein System (nochmal) viel größer, und dann gibts lauter neue Entwickler und Anforderungen, und jemand sagt, ja, dieses Event Zeugs ist cool, will ich auch verwenden, aber mein Sub System hat nichts mit dem Rest zu tun und der globale Event Manager soll davon gar nichts mitbekommen.
Jup, könnte Aufwändig werden das im nachhinein auseinander zu wurschteln.
Das dachte ich mir letztenendes auch und hab einiges umgestellt. Den GlobalEventManager selbst ist nun kein Singleton mehr (und heisst nun EventServer), die Konstruktoren sind protected. Mein Singleton EventServer der intern verwendet wird erbt einfach von der KLasse.
Das lässt sich per #define ECS3P_CUSTOM_EVENTSERVER CustomClass, auch einstellen. Der Rest ist eigentlich per Template Parameter konfigurierbar aber das ganze sah beim debuggen relativ unschön aus (bei typedef SystemManger<EventManagerBase, EventServer> EventManger; wobei der EventServer auch wieder ein Template ist wird leider immer der volle name incl aller paramter ausgegeben).
Deshalb erben EventManager und co die einzelnen Template Klassen einfach (aka class Eventmanager : public SystemManager<EventManager, EventServer_t>), EventServer_t wird dann einfach in einem #ifdef block als typedef gesetzt. Ob das so ideal ist kann ich nicht sagen, allerdings wars für die simpelste Lösung das von Benutzer konfigurierbar zu machen. Auf dem gleiche weg lassen sich auch Systeme komplett deaktivieren.
hustbaer schrieb:
seelenquell schrieb:
Technisch gesehen ist vermutlich nichts wirklich lockfrei.
Doch, lock-freie Datenstrukturen. Dinge wie try_lock bei einer Try-Mutex sind auch lock-free.
Muss ich mir mal anschauen, eigentlich waere mir STM ja am liebsten, aber bis 2017 werde ich da vermutlich noch mindestens warten müssen wenn ich keine externe lib verwenden will. Je nachdem wie lange es dauert bis die Compiler es unterstützen eher noch länger.
hustbaer schrieb:
seelenquell schrieb:
Aber versteh bitte das ich keine "richtigen" Mutexe/Locks einsetzen will, das will ich unter allen Umstaenden vermeiden. Mir gehts dabei ums Prinzip, ich will darauf hinaus am Ende keine "sichtbaren" Locks zu haben. Ich hatte vor Jahren mal zimliche schwierigkeiten mit Locks, vermutlich habe ich desswegen so lange Clojure programmiert, wo es sprachlich garkeine Möglichkeit gibt Locks zu setzen, das war eine wirkliche Offenbarung. Daher kenne ich auch die Konzepte von Atomic, STM und async recht gut, in C++ muss ich mich da allerdings nochmal richtig durchwühlen (wie bei vielen anderen dingen auch).
Sorry, aber das klingt alles nicht so als ob du genügend Grundlagen/Vorkenntnisse hättest um sowas erfolgreich auf die Beine zu stellen.
Das Projekt ist ja auch sowas wie mein "mal schauen was ich hinkrieg". Wenns nicht nach meinen Vorstellungen machbar ist muss ich eben auf ein anderes Konzept zurückgreifen. Ich hab aber nunmal mit Locks in Java (ich kenne eigentlich bisher Mutex und Lock nur synonym) relativ schlechte Erfahrungen gemacht. Nachdem ich mit Java angefangen hatte hab ich mich ne Weile mit nem Websever Projekt von nem Bekannten beschäftigt, das ist quasi ständig in nen Deadlock gerannt, irgendwann hat dann der Bekannte auch aufgehört und nochmal von vorne angefangen (da hatte ich schon lange keinen Nerf mehr). Clojure, das ja auch auf der JVM läuft und mit Java voll kompatibel ist, hat die Probleme nicht. Daten sind per se Immutable, es gibt standartmäßig keine Variablen, ändere ich eine Datenstruktur wird eine Kopie erzeugt. Um Variable Werte speichern zu können muss ich da auf Atomics, Agents oder Refs (transactional references) zurückgreifen, welche alle Thread safe sind und nicht blockieren. Clojure wurde auch mit dem Ziel entwickelt weshalbs auch relativ flott ist. Im vergleich zu anderen HTTP Servern ist der code von Clojure-Ring wohl desshalb auch zimlich einfach gehalten.
Sorry fuer den langen Text, aber ich wollte nur sagen das ich mit Concurrency in anderen Sprachen schon einiges zu tun hatte. Ob und wie sich das auf C++ übertragen lässt wird sich zeigen. Da die Benchmarks zum Thema Nebenläufigkeit in C++ die ich kenne (vor allem auf http://www.grimm-jaud.de) zimlich ernüchternd ausfallen, habe ich beschlossen innerhalb meiner Systeme weitgehend darauf zu verzichten, es hat immer nur ein Thread gleichzeitig Zugriff auf einen Verbund von Systemen (das steuert der Eventmanager), eine Ausnahme ist atm nur die Eventqueue in die von aussen gepusht werden kann, und das Positioning System, dessen variabler Teil vom Eventmanager beschrieben wird.
Vielleicht kennt ja zufällig jemand nen guten link zum Thema multithreading Performance, habe leider bisher wenig gefunden, http://www.grimm-jaud.de ist da leider auch nicht besonders aussagekräftig.