#include "msgqueue.h" #include #include // usleep #include // PRIO_PROCESS // -------------------------------------------------------------------------- // // This creates the Message queue thread, // MsgQueue::MsgQueue() : fBreak(0) { fMp = new unsigned char; pthread_create(&fThread, NULL, MapThread, this); } // -------------------------------------------------------------------------- // // The destructor terminates the thread. // MsgQueue::~MsgQueue() { cout << "~MsgQueue::MsgQueue" << endl; pthread_cancel(fThread); delete (unsigned char*)fMp; } // -------------------------------------------------------------------------- // // 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. // void *MsgQueue::Proc(int msg, void *mp) { return NULL; } // -------------------------------------------------------------------------- // // This is the thread mapper. // void *MsgQueue::MapThread(void *arg) { pthread_detach(pthread_self()); setpriority(PRIO_PROCESS, 0, -5); ((MsgQueue*)arg)->Thread(); return NULL; } // -------------------------------------------------------------------------- // // 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() { // // Tell the poster that processing is done // fStart = 0; while (!fBreak) usleep(1); while(1) { while (!fStart) usleep(1); fStart = 0; // // This makes sure that also a very fast Break() after // a PostMsg is processed correctly // pthread_mutex_lock(&fMuxMsg); fBreak = 0; pthread_mutex_unlock(&fMuxMsg); cout << "Processing Msg 0x" << hex << fMsg << endl; // --- bool quit = fMsg==WM_QUIT; fRc=Proc(fMsg, fMp); cout << "Msg 0x" << hex << fMsg << " processed." << endl; // --- if (quit) // --- break; } // --- fStart = 0; // --- cout << "WM_QUIT posted... leaving msg queue." << endl; } // -------------------------------------------------------------------------- // // 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) { // // Lock Mutex, put msg on stack and tell thread to process message // // // Make sure that only one Proc() is running and can be stopped // stopped and the messages are processed serialized // cout << "Locking MsgQueue mutex..." << flush; pthread_mutex_lock(&fMuxMsg); cout << "done." << endl; // // Set break state and wait until Proc() returned (break state deleted) // This means, that a new command is invoked and (if forseen) the // running command should stop execution. // // This is some kind of controlled user break without using signals // fBreak = 1; // // copy return code from Proc() and set new message // void *rc = fRc; fMsg = msg; delete (unsigned char*)fMp; fMp = new unsigned char[size]; memcpy(fMp, mp, size); // // Start Proc() // fStart = 1; cout << "Releasing MsgQueue mutex..." << flush; pthread_mutex_unlock(&fMuxMsg); cout << "done." << endl; while (fStart) usleep(1); cout << "Returning rc = 0x" << hex << rc << endl; return rc; }