mutex schreiben
-
Man ist immer auf Hilfe vom OS/Compiler/... angeweisen, da C++ (noch) keine Atomaren Operationen kennt, sowie auch (noch) keine fertigen Mutexen o.Ä.
Es gibt mehrere Proposals solche Dinge im Standard anzubieten, aber im Standard sowie AFAIK auch in TR1 ist da noch nichts dabei.Man braucht in der Regel 3 Dinge:
- Die atomic instruction "compare and swap" (aka. InterlockedComapreExchange in Windows, bzw. abgekürzt einfach CAS)
- Eine CPU Memory Barrier
- Eine Compiler Memory Barrier
Oft sind alle 3 in einer OS Funktion zusammengefasst, wie eben unter Windows in InterlockedComapreExchange, theoretisch könnten alle 3 aber auch getrennt sein. (1 impliziert fast immer 2, muss aber nicht so sein.)
(BTW: 3 wird meist einfach dadurch erreicht dass eine OS Funktion aufgerufen wird, der Compiler keine Annahmen über OS Funktionen trifft, und daher vor und nach *allen* OS Funktionen eine "Compiler Memory Barrier" setzt.)Manche Compiler bieten allerdings auch eine ausreichend mächtige inline Assembler Syntax an mit deren Hilfe sich 1-3 implementieren lässt (gcc kann das soweit ich weiss).
Damit kann man sich dann erstmal einen Spin-Lock basteln. Wenn man statt einem Spin-Lock einen Sleep-Lock will braucht man noch irgendeinen Mechanismus um einen Thread kontrolliert Schlafenzulegen und (aus einem anderen Thread heraus) wieder aufzuwecken.
Dazu muss man im Normalfall wieder das OS bemühen. Verwenden kann man hierfür z.B. Events oder Semaphoren oder ähnliches.
Theoretisch auch Condition-Variablen, obwohl die Verwendung einer Condition-Variable impliziert dass man bereits eine OS Mutex verwendet. Der einzige Grund der mir einfällt dann nicht gleich die OS Mutex unverändert zu verwenden wäre wenn man ein "timed_lock" braucht (welches bei pthreads Mutexen leider fehlt).
-
BorisDieKlinge schrieb:
[windowscode]locker schrieb:
in reinem c++

-
hustbaer schrieb:
Man ist immer auf Hilfe vom OS/Compiler/... angeweisen, da C++ (noch) keine Atomaren Operationen kennt, sowie auch (noch) keine fertigen Mutexen o.Ä.
ok, dachte ich mir schon. thx für die info.
hintergrund ist: ich hätte gern ein mutex dass für schreib- und lesezugriffe getrennt gelockt werden kann (schreibzugriff soll blockieren bis nicht mehr gelesen und geschrieben wird, lesezugriff nur bis nicht mehr geschrieben wird). criticalsections scheinen das nicht leisten zu können.
-
warum nimmst du nicht einfach 2 critical sections/mutexe: eine für lesen und eine für schreiben. also so in der art:
class blub { CriticalSection cs_read; CriticalSection cs_write; // ... public: void read() { lock(cs_write); // ... } void write() { lock(cs_read); lock(cs_write); // ... } // ... };
-
Für x86 Architekturen kannst du dir bestimmt ein Mutex in Assembler mit der TSL (Test - Set - Lock) Anweiseisung schreiben.
-
dot schrieb:
warum nimmst du nicht einfach 2 critical sections/mutexe: eine für lesen und eine für schreiben.
weil die einfachste nicht unbedingt auch die beste/schönste/eleganteste/schnellste/whatever lösung sein muss.
-
hä?
-
dot schrieb:
hä?
ich meinte, vielleicht gibts ja eine bessere lösung als die triviale aus deinem vorschlag.
dein ansatz hat zudem das problem, dass lesezugriff von mehreren threads gleichzeitig nicht funktioniert, weil read() dann blockiert.
-
stimmt
-
locker schrieb:
hintergrund ist: ich hätte gern ein mutex dass für schreib- und lesezugriffe getrennt gelockt werden kann (schreibzugriff soll blockieren bis nicht mehr gelesen und geschrieben wird, lesezugriff nur bis nicht mehr geschrieben wird). criticalsections scheinen das nicht leisten zu können.
Schonmal über Semaphore nachgedacht?
-
CStoll schrieb:
Schonmal über Semaphore nachgedacht?
noch nicht wirklich - sah auf den ersten blick in windows recht aufwendig und potenziell langsam aus. ich schaus mir mal genauer an.
-
locker schrieb:
sah auf den ersten blick in windows recht aufwendig und potenziell langsam aus
das sind mutexe auch :p
-
ist mein code nich rein C++?
-
Nein, der nutzt die WinAPI. Reines C++ kennt keine Multithreading-Ansätze und keine Synchronisation.
-
Read-Write-Mutexen sind IMO grundsätzlich problematisch.
Spätestens dann wenn man die Möglichkeit will einen Read-Lock auf einen Write-Lock "upzugraden". Dann muss nämlich (in manchen Fällen) der Read-Lock temporär hergegeben werden, bis ein Write-Lock geholt werden kann. Und das ist etwas was Programmierer die mit der fertigen Klasse arbeiten gerne übersehen werden - d.h. die werden davon ausgehen dass das was sie vor dem "upgrade" gelesen haben auch nach dem "upgrade" noch so ist -- was aber eben nicht so sein muss.
-
ich habe jetzt mal http://doc.trolltech.com/qq/qq11-mutex.html mit windows-mitteln umgesetzt. gibts daran irgendwas auszusetzen? vielleicht irgendwelche nicht offensichtlichen fallen?
der thread ist hier mittlerweile offtopic, kann gerne nach winapi verschoben werden.
-
BorisDieKlinge schrieb:
ist mein code nich rein C++?
Schlag doch einfach mal im C++-Standard oder www.cppreference.com folgende Ausdücke nach:
BorisDieKlinge schrieb:
... CRITICAL_SECTION ... InitializeCriticalSection... DeleteCriticalSection... EnterCriticalSection... LeaveCriticalSection... TryEnterCriticalSection...
Gruß,
Simon2.
-
um mir mal schizomäßig selbst zu antworten:
locker schrieb:
vielleicht irgendwelche nicht offensichtlichen fallen?
in criticalsections kann der selbe thread mehrfach eintreten ohne zu blockieren. bei semaphoren geht das nicht.

-
Klar geht das bei semaphoren.
-
Tyrdal schrieb:
Klar geht das bei semaphoren.
nicht bei windows-semaphoren, dazu müsste ich wohl meine eigene schreiben.