[boost] mutex und exceptions
-
Moin,
ich habe folgenden Code:
try{ IoMutex.lock(); Remover.Load(path); // throws IoMutex.unlock(); //und noch viel mehr code } catch(...) { IoMutex.lock(); //tu was }
Remover.Load könnte feststellen, dass der Pfad nicht existiert und eine Exception schmeißen. Dann wird sich aber vermutlich das Programm aufhängen, weil der Mutex im cath-block nich mehr gelockt werden kann.
Wäre Foglendes eine passable Lösung oder sollte man mit rethrow arbeiten?
try{ { boost::mutex::scoped_lock(IoMutex) lock; Remover.Load(path); // throws } //und noch viel mehr code } catch(...) { IoMutex.lock(); //tu was }
Danke!
-
Warum nicht:
{ ... IoMutex.lock(); try { Remover.Load(path); // throws //und noch viel mehr code } catch(...) { //tu was } IoMutex.unlock(); }
-
kynarion schrieb:
Wäre Foglendes eine passable Lösung oder sollte man mit rethrow arbeiten?
Man sollte immer mit den
scoped_lock
,unique_lock
usw. Klassen arbeiten. Nie direkt die Methoden der Mutex aufrufen! Genau dafür sind diese Klassen schliesslich da, da sie dir RAII geben und RAII perfekt bei Exceptions und auch vielem anderem ist.Grüssli
-
jencas: ich muss halt im catch-block was tun, was den lock zwingend erforderlich macht.
Dravere: Danke. Ich fand nur, dass die das andauernde Geklammere um einen einzigen Befehl einen ziemlich unleserlichen Code macht. Aber die Vorteile überwiegen dann halt doch.
-
kynarion schrieb:
Dravere: Danke. Ich fand nur, dass die das andauernde Geklammere um einen einzigen Befehl einen ziemlich unleserlichen Code macht. Aber die Vorteile überwiegen dann halt doch.
Wenn du willst, kannst du dir da Makros machen. Allerdings sollte man die mit Vorsicht benutzen. Aber das ginge ca. so:
#define CRITICAL_SECTION_START(x) { boost::lock_guard<boost::mutex> lock(x); { #define CRITICAL_SECTION_END } } // Zwei Klammern: Damit man die Variable lock trotzdem // als Variablenname noch benutzen darf. Es gibt dann halt eine // Überdeckung. // ... CRITICAL_SECTION_START(myMutex); // Der Code ausführen ... CRITICAL_SECTION_END;
Grüssli
-
Dravere schrieb:
kynarion schrieb:
Dravere: Danke. Ich fand nur, dass die das andauernde Geklammere um einen einzigen Befehl einen ziemlich unleserlichen Code macht. Aber die Vorteile überwiegen dann halt doch.
Wenn du willst, kannst du dir da Makros machen. Allerdings sollte man die mit Vorsicht benutzen. Aber das ginge ca. so:
#define CRITICAL_SECTION_START(x) { boost::lock_guard<boost::mutex> lock(x); { #define CRITICAL_SECTION_END } } // Zwei Klammern: Damit man die Variable lock trotzdem // als Variablenname noch benutzen darf. Es gibt dann halt eine // Überdeckung. // ... CRITICAL_SECTION_START(myMutex); // Der Code ausführen ... CRITICAL_SECTION_END;
Grüssli
haha.
nee, ein block im makro versteck ist scheiße.
-
volkard schrieb:
haha.
nee, ein block im makro versteck ist scheiße.Das ist mal wieder eine äusserst konstruktive Argumentation. Ich bin zwar selber auch nicht so der Fan von solchen Konstrukten, vor allem weil man damit extrem vorsichtig sein muss, aber manchmal sieht es einfacher schöner, bzw. lesbarer, aus.
Ich meine:BEGIN_CRITICAL_SECTION(m_inputMutex); // ... END_CRITICAL_SECTION; // vs. { // Begin critical section boost::lock_guard<boost::mutex> lock(m_inputMutex); // ... } // End critical section
Oft gehe ich allerdings eher diesen Weg:
// Irgendwo, meistens zentral. typedef boost::lock_guard<boost::mutex> Lock; // ... { // Begin critical section Lock lock(m_inputMutex); // ... } // End critical section
Grüssli
-
Was ist denn eigentlich der große Unterschied zwischen scoped_lock und lock_guard?
-
ich würd dabei bauchweh bekommen.
zum beispiel gibt mirBEGIN_CRITICAL_SECTION(m_inputMutex); int write=writepos-bufferbegin; // ... END_CRITICAL_SECTION; cout<<write;
die adresse von der write-funktion aus. welch ein grlück, daß ich schnell mit cout nachgeguckt habe, und nicht mit if(write!=0) send(socket,buffer,write) weitergemacht habe.
-
kynarion schrieb:
Was ist denn eigentlich der große Unterschied zwischen scoped_lock und lock_guard?
scoped_lock
existiert nicht:
http://www.boost.org/doc/libs/1_38_0/doc/html/thread/synchronization.html#thread.synchronization.locksBzw.
scoped_lock
ist eine Klasse aus Boost.Interprocess, hat also mit Boost.Thread nichts zu tun:
http://www.boost.org/doc/libs/1_38_0/doc/html/interprocess/synchronization_mechanisms.html#interprocess.synchronization_mechanisms.mutexes.mutexes_scoped_lock@volkard,
Deshalb habe ich ja geschrieben, extrem vorsichtig damit umgehen
Aber gut dass du dich noch dazu durchgerungen hast, einen Beitrag zu verfassen, welcher hilfreich ist. Denn die Angabe, dass etwas scheisse ist, hilft niemandem weiter.Grüssli
-
Versteh ich jetzt nicht so ganz:
http://www.boost.org/doc/libs/1_38_0/doc/html/thread/synchronization.html#thread.synchronization.locks.shared_lockIs doch auch boost::thread. Haben die das einfach von Interprocess übernommen?
-
kynarion schrieb:
Versteh ich jetzt nicht so ganz:
http://www.boost.org/doc/libs/1_38_0/doc/html/thread/synchronization.html#thread.synchronization.locks.shared_lockIs doch auch boost::thread. Haben die das einfach von Interprocess übernommen?
Das ist aber nicht
scoped_lock
:p
Und die Unterschiede der verschiedenen Klassen kannst du dort in der Dokumentation gerne nachlesenGrüssli
-
Argh, schreibt mich nicht ab, ich lern noch lesen...
aber das da gibt es: typedef unique_lock<mutex> scoped_lock;
drum geht's.