Ich möchte boost::timed_wait
verwenden, um nach 5 Sekunden auf ein Ereignis oder Timeout zu warten. Mein Problem ist, dass meine timed_wait
nur die Benachrichtigung zum ersten Mal akzeptiert.Benachrichtigen Bedingungsvariable von boost :: timed_wait funktioniert nur einmal
Um genauer zu sein:
ich eine Art von wenig Zustandsmaschine haben. Es führt nichts mehr aus, als einige Befehle asynchron auszuführen und dann zu überprüfen, ob es erfolgreich war. Dies bedeutet, dass nach dem Senden des Befehls meine Zustandsmaschine m_Condition.timed_wait(lock,timeout)
aufruft. (m_Condition
ist eine Elementvariable mit dem Typ boost::condition_variable
).
Nun, wenn dieser asynchrone Aufruf erfolgreich war, sollte er eine Callback-Funktion aufrufen, die m_Condition
benachrichtigt, damit ich weiß, dass alles in Ordnung ging. Wenn der Befehl fehlgeschlagen ist, ruft er die Callback-Funktion nicht auf und daher sollte meine timed_wait
Timeout sein. Also die Callback-Funktion tut nichts mehr und nichts weniger als m_Condition.notify_all()
aufrufen.
Das Problem ist, dass dies nur das erste Mal funktioniert. Dies bedeutet, dass nach dem ersten Aufruf von notify_all()
diese Zustandsvariable nicht mehr funktioniert. Ich habe bei meinem Rückruf nachgesehen und es ruft immer wieder notify_all()
an aber die timed_wait
kommt gerade raus.
Vielleicht sind einige Beispiel-Code es ein wenig klarer zu machen:
myClass_A.hpp
class myClass_A
{
public:
void runStateMachine(); // Starts the state machine
void callbackEvent(); // Gets called when Async Command was successful
private:
void stateMachine(); // Contains the state machine
void dispatchAsyncCommand(); // Dispatches an Asynchronous command
boost::thread m_Thread; // Thread for the state machine
boost::condition_variable m_Condition; // Condition variable for timed_wait
boost::mutex m_Mutex; // Mutex
};
myClass_A.cpp
void myClass_A::runStateMachine()
{
m_Thread = boost::thread(boost::bind(&myClass_A,this));
}
void myClass_A::dispatchAsyncCommand()
{
/* Dispatch some command Async and then return */
/* The dispatched Command will call callbackEvent() when done */
}
void myClass_A::stateMachine()
{
boost::mutex::scoped_lock lock(m_Mutex);
while(true)
{
dispatchAsynCommand();
if(!m_Condition.timed_wait(lock, boost::posix_time::milliseconds(5000)))
{
// Timeout
}
else
{
// Event
}
}
}
void myClass_A::callbackEvent()
{
boost::mutex::scoped_lock lock(m_Mutex);
m_Condition.notify_all();
}
Also, was ich jetzt tun kann? Ist es nicht möglich, die condition_variable mehrmals zu verwenden? Oder muss ich es irgendwie zurücksetzen? Irgendwelche Vorschläge sind willkommen!
Keine Antwort, weil ich nicht sicher bin, was in Ihrem Code vor sich geht, aber Zustandsvariablen sind nicht nur Signale, sie sollten verwendet werden, um eine Änderung in einem gemeinsamen Zustand zu signalisieren. Siehe dieses Beispiel: http://www.justsoftwaresolutions.co.uk/threading/implementing-a-thread-safe-queue-using-condition-variables.html – stefaanv
In Ihrem Code könnte die Bedingung eine ausgelastete Flagge sein, also stateMachine könnte "busy = true; while (beschäftigt &&! rc) {rc = m_Condition.timed_wait (...);}" – stefaanv
@stefaanv Vielen Dank für Ihre Vorschläge. Ich habe diesen Artikel gelesen, den du gepostet hast, und okay, vielleicht benutze ich den "timed_wait" nicht für den üblichen Zweck, aber trotzdem sollte es den Deal machen. Tatsächlich ist die Implementierung, die sie dort verwendeten, ziemlich die gleiche wie meine. Zu Ihrem zweiten Kommentar: Was sollte diese vielbefahrene Flagge tun? Ich meine mein Problem ist, dass mein 'timed_wait' nur mit einem Timeout und einem Rückgabewert von' false' nach dem ersten Anruf zurückkehrt. Ich kann 'notify_all()' alles, was ich will .. nichts ändern:/ – Toby