#include "msgqueue.h" #include using namespace std; // -------------------------------------------------------------------------- // // This creates the Message queue thread, // MsgQueue::MsgQueue() : fState(kRun), fThread(std::bind(&MsgQueue::Thread, this)) { } // -------------------------------------------------------------------------- // // The destructor terminates the thread. // MsgQueue::~MsgQueue() { CancelThread(); } void MsgQueue::CancelThread() { const std::lock_guard lock(fMutex); if (fState!=kIdle) return; fState = kAbort; fCond.notify_one(); fThread.join(); } // -------------------------------------------------------------------------- // // This is the function which must be overloaded. // Here you process the messages. mp is a pointer which you can // specify when posting the message. // // If a new messages is posted while the old one is not yet // finished the fBreak flag is set. Please test this flag with // Break() and try to finish (or stop) the current action as soon // as possible. This makes sure, that before a new action is started // the old action can be finished correctly by the user. // int MsgQueue::Proc(int msg, void *mp) { return 0; } int MsgQueue::Break() const { return fSize>0 || fState!=kRun; } // -------------------------------------------------------------------------- // // This is the thread which handles the processing. // As soon as a message is posted the fBreak flag is set (see PostMsg) // And as soon as the current action is finished the new action is executed // in this thread. This makes sure, that the calling program is not stalled. // void MsgQueue::Thread() { std::unique_lock lock(fMutex); while (1) { while (fList.empty() && fState==kRun) fCond.wait(lock); if (fState==kAbort) break; if (fState==kStop && fList.empty()) break; const auto &val = fList.front(); fSize--; lock.unlock(); Proc(val.first, const_cast(val.second.data())); lock.lock(); fList.pop_front(); } fList.clear(); fSize = 0; fState = kIdle; } // -------------------------------------------------------------------------- // // Use this function to post a message. // mp can be a pointer to a data structure. size should be the size of it. // size bytes of this structure are copied and a pointer to the copy // is forwarded to the Proc function. // void *MsgQueue::PostMsg(int msg, void *mp, int size) { const std::lock_guard lock(fMutex); if (fState==kIdle) return false; fSize++; fList.emplace_back(msg, vector(reinterpret_cast(mp),reinterpret_cast(mp)+size)); fCond.notify_one(); return 0; }