mutex und lock_guard
-
Ja, lock ist mir schon bekannt, ich habe es hier nur "acquire" benannt, damit man die andere Variante "adopt" benennen kann um das besser zu trennen und vor allem dem Benutzer nicht vorzuschreiben, dass er einen RAII guard benutzen muss.
unique_lock hat doch dasselbe Problem, dass man immer den Typ des Mutex mit angeben muss? "auto" finde ich an dem Punkt schon schön. Darauf wollte ich ja eigentlich hinaus.
-
Geht ja recht einfach:
template <typename M> std::unique_lock<M> acquire(M& mutex) { return std::unique_lock<M>(mutex); } auto guard = acquire( mighty_mutex );Ich finde aber die explizite Typangabe gar nicht so schlecht. Weil der Namen ist völlig Wurst, die wichtige Information ist, dass es ein lock_guard ist (oft kommt eh nur ein Mutex in Frage).
Die acquire-Syntax betont das guard, das gefällt mir weniger.
-
template <class Lockable> inline std::unique_lock<Lockable> acquire(Lockable& lock) { return std::unique_lock<Lockable>(lock); } // ... auto guard = acquire(mighty_mutex);
Edit:
...
-
Na der Türsteher zieht doch den Perso auch direkt von mir ein, statt mich in eine Box zu schicken, die ihm dann meinen Perso aushändigt

Dieses acquire kann ich ja jetzt nicht in den std header packen, das heißt in jeder CU müsste ich wieder nen Header inkludisionieren oder das template neu definieren :((Noch eine andere Frage:
ist std::future<void> eine gangbare einfache Alternative für eine condition_variable, damit man nicht irgendwie noch eine geteilte Ressource mit einem Prädikat verwalten muss, zur Wappnung gegen "spurious wakeups"? Also in dem Falle, bei dem man auf ein Ereignis warten möchte und nicht sowieso schon ein "geteiltes" Prädikat zur Verfügung hat.
-
Finde dass gut so. Mutexe sollte man eher sparsam nutzen, und meistens ist task-based parallelism die bessere Alternative.
Lowlevel threading ist einfach zu fehleranfällig...
-
Lowlevel threading ist einfach zu fehleranfällig
Ist genauso wie new/delete. Die einen koennen es, die anderen nicht. Genauso wie mit Assembler, Python, gutes OOP, ...
-
Hö? Versteh ich nicht?
Wieso fehleranfällig?
Entweder man nutzt Threads richtig und dann klappt das. Oder man nutzt sie falsch und schiesst sich mit Deadlocks oder Race Conditions so dermaßen ins eigene Bein, dass man auch gleich die Nebenläufigkeit sein lassen kann.
Achja, und wenn man es richtig nutzt und dann noch Ahnung hat und etwas Erfahrung, dann holt man richtig Performance raus.
-
Skym0sh0 schrieb:
Achja, und wenn man es richtig nutzt und dann noch Ahnung hat und etwas Erfahrung, dann holt man richtig Performance raus.
Gerade bei Mutexen ist die Performance sehr oft nicht gegeben, auch wenn alles andere stimmt.
-
Die Sache mit Threading ist, dass es unheimlich viele Leute gibt die meinen es zu können, die aber in Wirklichkeit massiv viele Fehler machen.
Gerade Deadlocks und Race-Conditions sind so-gut-wie immer Timing-anhängig. D.h. man bekommt beim Testen keine Fehler, und meint alles wäre in Butter. Alles funktioniert wie es soll.
Dabei haben die Programme schwerwiegende konzeptionelle Fehler, die dann meist nicht auf die Schnelle behoben werden können wenn die Bugs anfangen sich zu manifestieren.z.B. Locks halten während man Callbacks macht/Events feuert ist ein Fehler den ich laufend sehe. Oder auch einfach gar keine Locks zu verwenden. Nach dem Motto "mit Locks hat's Probleme gegeben, also machen wir die einfach weg".
-
LuckyLocker schrieb:
Da ich mir denke, dass es den Leuten, die das entwickelt haben auch so ginge, muss es ja einen Grund geben dafür, der würde mich interessieren. Unter "mutex lock_guard cumbersome" oder ähnlichen Suchanfragen habe ich leider nichts gefunden.
Ich denke da gibt es mehrere Gründe.
- Man braucht manchmal direkt Zugriff auf die lock()/unlock() Funktionen, ohne "Guard". Das heisst natürlich nicht dass man nicht zusätzlich ne Guard-Variante anbieten kann, aber es heisst dass es nicht die einzige Möglichkeit sein darf ne Mutex zu locken.
- Zur Zeit wo diese Libraries entwickelt wurden gab's noch kein "auto".
- Zur Zeit wo diese Libraries entwickelt wurden gab's noch kein "move".
Ich finde die Variante
auto guard = lock(mutex);auch viel eleganter.LuckyLocker schrieb:
Dieses acquire kann ich ja jetzt nicht in den std header packen, das heißt in jeder CU müsste ich wieder nen Header inkludisionieren oder das template neu definieren :((
Du wirst bei jeder Sprache und jedem Framework Dinge finden die dir abgehen. Dafür schreibt man sich in jedem Projekt dann Hilfsfunktionen, die man dann an vielen Stellen verwendet.
Das Argument "ich müsste dann ja ne Header inkludieren" ist für mich irgendwie ... lächerlich (sorry, nicht böse gemeint, aber ich kanns überhaupt nicht nachvollziehen).
Ich meine, du musst ja auch Headers einbinden damit du überhaupt Mutexen verwenden kannst
Meine Projekte haben alle ein "Common.h", wo Zeugs included/deklariert wird das an vielen Stellen des Projekts immer wieder gebraucht wird. Und jedes Header-File des Projekts bindet dann als erstes die "Common.h" ein.
Noch eine andere Frage:
ist std::future<void> eine gangbare einfache Alternative *snip*Ich verstehe die Frage nicht. Wenn du was hast, auf das
std::future<void>perfekt passt, dann ja, klar, wieso solltest du dann nichtstd::future<void>dafür verwenden?