Suche boost-Events
-
Hi!
Ich suche eine bestimmte Funktionalität in Boost, von der ich überzeugt bin, dass sie drin ist. Und zwar suche ich eine ähnliche Funktionalität wie die von den Windows Events, also irgendeine Art Objekt, das ich "signal"en kann und auf das ich warten kann.
Am Besten ich skizziere einfach mal die Situation:class XXX { public: ~XXX() { ev.signal_or_set_or_something(); m_thread.join(); } void thread_func() { for ( bool running=true; running; ) { // Mache etwas, was nur alle X Minuten gemacht werden muss ... // Entweder X Minuten warten oder vom Destruktor aus dem Schlaf reißen lassen if ( TIMEOUT != wait_for_event_timeout( ev, X_MINUTES ) ) running = false; } } private: event ev; };boost::condition scheint nicht geeignet zu sein, hat einen Mutex mit drin. (boost: A condition object is always used in conjunction with a mutex object [...] The mutex object must be locked prior to waiting on the condition,...).
Ansonsten hab ich mir noch boost::signal angeguckt, aber das ist ja was ganz ganz anderes
Wisst ihr was ich meine und kennt die entsprechende Klasse?
-
Und was stört dich an einem Mutex? Wenn du auf ein Event wartest, dann wird ja wohl ein anderer Thread mit im Spiel sein, wodurch Mutex und Condition genau das richtige sind. Kannst auch nur eine Zeitlang warten usw. usf.
Ob das Event gesetzt ist oder nicht, bzw. das Setzen, muss sowieso synchronisiert werden und genau den Mutex kannst du auch für die Condition verwenden.Deine Anforderungen entsprechend im übrigen überhaupt nicht den Windows Events. Auf ein Windows Event kannst du nicht warten. Die Events befinden sich in einer Liste und werden von einem Thread abgearbeitet. Dieser Thread wartet nie auf ein Event, ausser es hat keine Events in der Liste. Dann macht der Thread ein Condition-Wait

Grüssli
-
Dravere schrieb:
Und was stört dich an einem Mutex? Wenn du auf ein Event wartest, dann wird ja wohl ein anderer Thread mit im Spiel sein, wodurch Mutex und Condition genau das richtige sind.
Ok, hab mir grad noch mal etwas mehr zu condition durchgelesen, hatte es falsch verstanden
Naja, nichtsdestotrotz hätte ich Mutex und Event lieber gelöst voneinander. Und ich habe ja zwar auch einen Mutex, auf den ich immer mit boost::mutex::scoped_lock warte. Wenn ich's diesmal richtig verstehe, verhält sich condition::wait diesbezüglich aber anders, oder?Dravere schrieb:
Ob das Event gesetzt ist oder nicht, bzw. das Setzen, muss sowieso synchronisiert werden und genau den Mutex kannst du auch für die Condition verwenden.
Ne, das Event brauche ich eigentlich nur, um dem Thread mitzuteilen, dass er sich beenden soll. Ich würde auch eine bool-Variable verwenden, aber die kann mich nicht aus einem langen Sleep rausreißen. Das Warten im Thread ist ja ein quasi-Sleep, nur bei dem wirklichen Sleep müsste der Destruktor beim "join" recht lange warten, was die ganze Programmausführung unvorteilhafterweise um ~eine Minute verhindert

Dravere schrieb:
Deine Anforderungen entsprechend im übrigen überhaupt nicht den Windows Events. Auf ein Windows Event kannst du nicht warten. Die Events befinden sich in einer Liste und werden von einem Thread abgearbeitet. Dieser Thread wartet nie auf ein Event, ausser es hat keine Events in der Liste. Dann macht der Thread ein Condition-Wait

Dann meinen wir aber unterschiedliche Events
Meine durchleben eigentlich immer CreateEvent, WaitForSingleObject und CloseHandle. edit: Und was meinst du mit "Events befinden sich in einer Liste und werden von einem Thread abgearbeitet"?
-
Badestrand schrieb:
Ok, hab mir grad noch mal etwas mehr zu condition durchgelesen, hatte es falsch verstanden
Naja, nichtsdestotrotz hätte ich Mutex und Event lieber gelöst voneinander. Und ich habe ja zwar auch einen Mutex, auf den ich immer mit boost::mutex::scoped_lock warte. Wenn ich's diesmal richtig verstehe, verhält sich condition::wait diesbezüglich aber anders, oder?Die Condition gibt den Lock auf und legt den Thread schlafen, bis ein
notify_oneodernotify_allaufgerufen wird.Badestrand schrieb:
Ne, das Event brauche ich eigentlich nur, um dem Thread mitzuteilen, dass er sich beenden soll.
Wie wäre es mit thread::interrupt?
Badestrand schrieb:
Dann meinen wir aber unterschiedliche Events
Meine durchleben eigentlich immer CreateEvent, WaitForSingleObject und CloseHandle. edit: Und was meinst du mit "Events befinden sich in einer Liste und werden von einem Thread abgearbeitet"?Ach, die meinst du

Bei Windows Events muss ich an die Windows Nachrichten denken
WM_* und co.
Deine beschriebenen sind für mich eher WinAPI Thread Events. WaitForSingleObject und das Event machen im übrigen ja dann auch nichts anderes als ein Condition-Wait. Zumindest ist das bei mir irgendwie so im Hinterkopf gespeichert.Grüssli
-
Dravere schrieb:
Wie wäre es mit thread::interrupt?
Wow, danke, das ist ja genau das, was ich gebrauchen kann
Wusste gar nicht, dass es sowas wie "interrupt" und "Interruption Points" bei Threads gibt! Obwohl mir das mit der Exception nicht hundertprozentig gefällt, aber man kann ja nicht alles haben..Dravere schrieb:
Deine beschriebenen sind für mich eher WinAPI Thread Events. WaitForSingleObject und das Event machen im übrigen ja dann auch nichts anderes als ein Condition-Wait. Zumindest ist das bei mir irgendwie so im Hinterkopf gespeichert.
Die lassen halt das 'lock'en weg, deshalb war ich erst auch ein wenig verwirrt von condition. Fande ich irgendwie eine ungewöhnliche Kombination, oder halt unpassend in meinem Zusammenhang.
edit: Meine Threads haben gar keine interrupt-Funktion

edit2: Oha, sind wohl neu, sind ja wirklich fleißig die boost-Leutchens, bringen jeden zweiten Monat 'ne neue Version raus.
edit3: Doch nicht neu, mein Compiler spinnt nur..
edit4: Ok, der Compiler findet sie jetzt (ja ich weiß, der Typ 30 cm vor'm Bildschirm und so...)
-
Achso, nur noch aus Interesse, eine boost-Klasse, die nur die WinAPI-Thread-Events (
) nachbildet/kapselt gibt's nicht, oder?
-
@Badestrand:
Auf eine "Event" Klasse wurde in Boost.Thread absichtlich verzichtet, da solche Event Klassen recht schwer richtig zu verwenden sind.
Condition-Variablen richtig zu verwenden ist da ein Stück einfacher.Was dein Thread-Beenden angeht: wenn du mit einer aktuellen Boost-Version arbeitest kannst du die "kooperative Thread-Cancellation" verwenden. Ansonsten kann man das recht einfach über eine Condition-Variable + bool-Flag lösen.
-
"Thread-Cancellation" müsste doch das von Dravere vorgeschlagene interrupt sein, oder? (Mailing-List-Diskussion um Name Cancellation<->Interruption)
hustbaer schrieb:
Auf eine "Event" Klasse wurde in Boost.Thread absichtlich verzichtet, da solche Event Klassen recht schwer richtig zu verwenden sind.
Schade und ich glaube ich hätte sie schon richtig verwendet, aber wer weiß

hustbaer schrieb:
Ansonsten kann man das recht einfach über eine Condition-Variable + bool-Flag lösen.
Momentan hab ich's über das Interrupt-System, aber so richtig gefällt's mir nicht, wegen dem try-catch um das sleep. Und ich hab keine Ahnung warum, aber irgendwie tue ich mich mit dem Verstehen der Condition-Variablen echt schwer.. Na gut, kannst/könnt du/ihr mir sagen, ob das so richtig wäre?
// Skizziert class XXX { public: ~XXX() { { // Acquire mutex boost::mutex::scoped_lock( m_mutex ); ... } m_cond.notify_one(); m_thread.join(); } void irgendwas() { // Acquire mutex boost::mutex::scoped_lock( m_mutex ); ... } void thread_func() { for ( bool running=true; running; ) { boost::unique_lock<boost::mutex> lock( m_mutex ); // Mache etwas, was nur alle X Minuten gemacht werden muss lock.lock(); ... lock.unlock(); // Entweder X Minuten warten oder vom Destruktor aus dem Schlaf reißen lassen if ( m_cond.timed_wait( lock, ... ) ) running = false; } } private: boost::mutex m_mutex; boost::condition m_cond; };
-
Na mal schauen, wie wach ich noch bin. Ich mache mal selber ein Beispiel:
class Foo { // Attributes // private: bool m_isRunning; boost::thread m_thread; boost::mutex m_syncMutex; boost::condition_variable m_breakCondition; // Constructors & Destructor // public: Foo() : m_isRunning(true) , m_thread(boost::bind(&Foo::run_thread, this)) , m_syncMutex() , m_breakCondition() { } ~Foo() { { boost::lock_guard<boost::mutex> lock(m_syncMutex); m_isRunning = false; } m_breakCondition.notify_one(); m_thread.join(); } // Methods // private: void run_thread() { // Accquire lock boost::unique_lock<boost::mutex> lock(m_syncMutex); do { // Do some stuff. } while(!m_breakCondition.timed_wait(lock, boost::posix_time::seconds(x) && m_isRunning); // Cleanup } };Glaube so sollte das gehen. Aber ruhig ein skeptischer Blick drauf werfen, bin ziemlich müde

Grüssli
-
Warum nicht boost::signals benutzen?
-
Dravere schrieb:
Glaube so sollte das gehen. Aber ruhig ein skeptischer Blick drauf werfen, bin ziemlich müde

Scheint zu funktionieren, danke dir!

boost__signals schrieb:
Warum nicht boost::signals benutzen?
Weil das doch eher Callbacks-Aufrufer sind: http://www.boost.org/doc/libs/1_35_0/doc/html/signals/tutorial.html#id1277113
