winamp/Src/Plugins/DSP/sc_serv3/nmrCommon/threading/messageThread.h
2024-09-24 14:54:57 +02:00

185 lines
6.9 KiB
C++

#ifndef messageThread_H_
#define messageThread_H_
#include "thread.h"
#include "MT_stl.h"
#include <deque>
#ifdef _WIN32
#include <crtdbg.h>
#else
#include <assert.h>
#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<mh> 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 Handler,class Queue>
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 <class P1> messageHandler(const P1 &p1):Handler(p1){}
template <class P1,class P2> messageHandler(const P1 &p1,const P2 &p2):Handler(p1,p2){}
template <class P1,class P2,class P3> messageHandler(const P1 &p1,const P2 &p2,const P3 &p3):Handler(p1,p2,p3){}
template <class P1,class P2,class P3,class P4> messageHandler(const P1 &p1,const P2 &p2,const P3 &p3,const P4 &p4):Handler(p1,p2,p3,p4){}
template <class P1,class P2,class P3,class P4,class P5> messageHandler(const P1 &p1,const P2 &p2,const P3 &p3,const P4 &p4,const P5 &p5):Handler(p1,p2,p3,p4,p5){}
template <class P1,class P2,class P3,class P4,class P5,class P6> 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 <class P1,class P2,class P3,class P4,class P5,class P6,class P7> 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 <class P1> messageHandler(P1 &p1):Handler(p1){}
};
template<class Handler,class Message = typename Handler::message_t>
class messageThread: public Tthread<messageHandler<Handler,MT_queue<Message> > >
{
public:
messageThread(){}
template <class P1> messageThread(const P1 &p1):Tthread<messageHandler<Handler,MT_queue<Message> > >(p1){}
template <class P1,class P2> messageThread(const P1 &p1,const P2 &p2):Tthread<messageHandler<Handler,MT_queue<Message> > >(p1,p2){}
template <class P1,class P2,class P3> messageThread(const P1 &p1,const P2 &p2,const P3 &p3):Tthread<messageHandler<Handler,MT_queue<Message> > >(p1,p2,p3){}
template <class P1,class P2,class P3,class P4> messageThread(const P1 &p1,const P2 &p2,const P3 &p3,const P4 &p4):Tthread<messageHandler<Handler,MT_queue<Message> > >(p1,p2,p3,p4){}
template <class P1,class P2,class P3,class P4,class P5> messageThread(const P1 &p1,const P2 &p2,const P3 &p3,const P4 &p4,const P5 &p5):Tthread<messageHandler<Handler,MT_queue<Message> > >(p1,p2,p3,p4,p5){}
template <class P1,class P2,class P3,class P4,class P5,class P6> messageThread(const P1 &p1,const P2 &p2,const P3 &p3,const P4 &p4,const P5 &p5,const P6 &p6):Tthread<messageHandler<Handler,MT_queue<Message> > >(p1,p2,p3,p4,p5,p6){}
template <class P1,class P2,class P3,class P4,class P5,class P6,class P7> messageThread(const P1 &p1,const P2 &p2,const P3 &p3,const P4 &p4,const P5 &p5,const P6 &p6,const P7 &p7):Tthread<messageHandler<Handler,MT_queue<Message> > >(p1,p2,p3,p4,p5,p6,p7){}
template <class P1> messageThread(P1 &p1):Tthread<messageHandler<Handler,MT_queue<Message> > >(p1){}
};
//////////////// Finite state machine
template <class Handler,typename RETVAL = bool>
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<Handler,RETVAL>::initialState){}
template <class P1> fsm(const P1 &p1):
Handler(p1),m_State(&fsm<Handler,RETVAL>::initialState){}
template <class P1> fsm(P1 &p1):
Handler(p1),m_State(&fsm<Handler,RETVAL>::initialState){}
template <class P1,class P2> fsm(const P1 &p1,const P2 &p2):
Handler(p1,p2),m_State(&fsm<Handler,RETVAL>::initialState){}
template <class P1,class P2> fsm(const P1 &p1,P2 &p2):
Handler(p1,p2),m_State(&fsm<Handler,RETVAL>::initialState){}
template <class P1,class P2> fsm(P1 &p1,P2 &p2):
Handler(p1,p2),m_State(&fsm<Handler,RETVAL>::initialState){}
template <class P1,class P2,class P3> fsm(const P1 &p1,const P2 &p2,const P3 &p3):
Handler(p1,p2,p3),m_State(&fsm<Handler,RETVAL>::initialState){}
template <class P1,class P2,class P3,class P4> fsm(const P1 &p1,const P2 &p2,const P3 &p3,const P4 &p4):
Handler(p1,p2,p3,p4),m_State(&fsm<Handler,RETVAL>::initialState){}
template <class P1,class P2,class P3,class P4,class P5> 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<Handler,RETVAL>::initialState){}
template <class P1,class P2,class P3,class P4,class P5,class P6> 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<Handler,RETVAL>::initialState){}
template <class P1,class P2,class P3,class P4,class P5,class P6,class P7> 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<Handler,RETVAL>::initialState){}
private:
state m_State;
};
#endif