#ifndef messageThread_H_ #define messageThread_H_ #include "thread.h" #include "MT_stl.h" #include #ifdef _WIN32 #include #else #include #endif #ifndef _WIN32 #define _ASSERTE assert #endif ///////////////////////////////////////////////////////////////// //* templates that allow you to build a message driven thread //* //* //* define a class that is your handler. It must have a type //* message_t which is the message type, and a method //* bool operator()(const message_t &m) which is the message handler. //* this method should return false when all processing is done and //* the thread should shutdown //* /* example class mh { string m_string; public: struct message { int m_v; message(int v):m_v(v){} }; typedef message message_t; protected: bool operator()(const message_t &mm) { if (!mm.m_v) return false; // if value is zero, then we are done ::MessageBox(0,tos(mm.m_v).c_str(),m_string.c_str(),MB_OK); return true; } mh(const string &s):m_string(s){} }; main() { messageThread m("this is a test"); m.start(); m.postMessage(m::message(1)); m.postMessage(m::message(2)); m.postMessage(m::message(3)); m.postMessage(m::message(4)); m.postMessage(m::message(0)); m.join(); } */ template class messageHandler: public Handler { private: Queue m_queue; protected: unsigned operator()() throw() { unsigned result = (unsigned)-1; try { while (true) { typename Queue::value_type m = m_queue.get(); if (!Handler::operator()(m)) break; } result = 0; } catch(...){} return result; } public: inline void postMessage(const typename Queue::message_t &m) { m_queue.push(m); } inline typename Queue::size_type pendingMessages() const throw() { return m_queue.size(); } inline void clearMessageQueue() throw() { m_queue.clear(); } messageHandler(){} template messageHandler(const P1 &p1):Handler(p1){} template messageHandler(const P1 &p1,const P2 &p2):Handler(p1,p2){} template messageHandler(const P1 &p1,const P2 &p2,const P3 &p3):Handler(p1,p2,p3){} template messageHandler(const P1 &p1,const P2 &p2,const P3 &p3,const P4 &p4):Handler(p1,p2,p3,p4){} template messageHandler(const P1 &p1,const P2 &p2,const P3 &p3,const P4 &p4,const P5 &p5):Handler(p1,p2,p3,p4,p5){} template messageHandler(const P1 &p1,const P2 &p2,const P3 &p3,const P4 &p4,const P5 &p5,const P6 &p6):Handler(p1,p2,p3,p4,p5,p6){} template messageHandler(const P1 &p1,const P2 &p2,const P3 &p3,const P4 &p4,const P5 &p5,const P6 &p6,const P7 &p7):Handler(p1,p2,p3,p4,p5,p6,p7){} template messageHandler(P1 &p1):Handler(p1){} }; template class messageThread: public Tthread > > { public: messageThread(){} template messageThread(const P1 &p1):Tthread > >(p1){} template messageThread(const P1 &p1,const P2 &p2):Tthread > >(p1,p2){} template messageThread(const P1 &p1,const P2 &p2,const P3 &p3):Tthread > >(p1,p2,p3){} template messageThread(const P1 &p1,const P2 &p2,const P3 &p3,const P4 &p4):Tthread > >(p1,p2,p3,p4){} template messageThread(const P1 &p1,const P2 &p2,const P3 &p3,const P4 &p4,const P5 &p5):Tthread > >(p1,p2,p3,p4,p5){} template messageThread(const P1 &p1,const P2 &p2,const P3 &p3,const P4 &p4,const P5 &p5,const P6 &p6):Tthread > >(p1,p2,p3,p4,p5,p6){} template messageThread(const P1 &p1,const P2 &p2,const P3 &p3,const P4 &p4,const P5 &p5,const P6 &p6,const P7 &p7):Tthread > >(p1,p2,p3,p4,p5,p6,p7){} template messageThread(P1 &p1):Tthread > >(p1){} }; //////////////// Finite state machine template class fsm: public Handler { public: typedef RETVAL (Handler::*state)(const typename Handler::message_t &m);// throw(); // should not throw an exception // this is broken in VC 7, so trans must be made public //friend class Handler; public: RETVAL operator()(const typename Handler::message_t &m) throw() { _ASSERTE(m_State);return (this->*m_State)(m); } void trans(state target) throw() { if (target == m_State) return; _ASSERTE(m_State); #ifndef NDEBUG state tmp = m_State; #endif (this->*m_State)(Handler::message_t::exitStateMessage()); #ifndef NDEBUG // sanity check - don't change states in exit_sig _ASSERTE(tmp == m_State); #endif m_State = target; (this->*m_State)(Handler::message_t::enterStateMessage()); _ASSERTE(m_State == target); // don't change states in enter_sig } public: fsm():m_State(&fsm::initialState){} template fsm(const P1 &p1): Handler(p1),m_State(&fsm::initialState){} template fsm(P1 &p1): Handler(p1),m_State(&fsm::initialState){} template fsm(const P1 &p1,const P2 &p2): Handler(p1,p2),m_State(&fsm::initialState){} template fsm(const P1 &p1,P2 &p2): Handler(p1,p2),m_State(&fsm::initialState){} template fsm(P1 &p1,P2 &p2): Handler(p1,p2),m_State(&fsm::initialState){} template fsm(const P1 &p1,const P2 &p2,const P3 &p3): Handler(p1,p2,p3),m_State(&fsm::initialState){} template fsm(const P1 &p1,const P2 &p2,const P3 &p3,const P4 &p4): Handler(p1,p2,p3,p4),m_State(&fsm::initialState){} template fsm(const P1 &p1,const P2 &p2,const P3 &p3,const P4 &p4,const P5 &p5): Handler(p1,p2,p3,p4,p5),m_State(&fsm::initialState){} template fsm(const P1 &p1,const P2 &p2,const P3 &p3,const P4 &p4,const P5 &p5,const P6 &p6): Handler(p1,p2,p3,p4,p5,p6),m_State(&fsm::initialState){} template fsm(const P1 &p1,const P2 &p2,const P3 &p3,const P4 &p4,const P5 &p5,const P6 &p6,const P7 &p7): Handler(p1,p2,p3,p4,p5,p6,p7),m_State(&fsm::initialState){} private: state m_State; }; #endif