00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012 #ifndef __MODULE__H__
00013 #define __MODULE__H__
00014
00015 #include <wx/thread.h>
00016 #include "flexilog.h"
00017 #include "eventhandler.h"
00018 #include "guienvironment.h"
00019
00020
00021 #define CREATE_INSTANCE_FUNC_ARGS (int * version, void ** instance, VRUT::EventHandler * evtHandler, const VRUT::MODULE_ID & id)
00022 #define RELEASE_INSTANCE_FUNC_ARGS (void *)
00023
00024 #define IMPORT_CREATE_INSTANCE_FUNC extern "C" DLLIMPORT void CREATE_INSTANCE_FUNC CREATE_INSTANCE_FUNC_ARGS
00025 #define IMPORT_RELEASE_INSTANCE_FUNC extern "C" DLLIMPORT void RELEASE_INSTANCE_FUNC RELEASE_INSTANCE_FUNC_ARGS
00026
00027 #define EXPORT_VRUT_MODULE_FUNCTIONS( moduleClassName ) \
00028 extern "C" DLLEXPORT void CREATE_INSTANCE_FUNC CREATE_INSTANCE_FUNC_ARGS \
00029 { \
00030 if (*instance) \
00031 { \
00032 delete (VRUT::moduleClassName *)instance; \
00033 *instance = 0; \
00034 } \
00035 \
00036 if (*version != VRUT::MODULE_VERSION) \
00037 *version = VRUT::MODULE_VERSION; \
00038 else \
00039 *instance = new VRUT::moduleClassName(id, wxT( # moduleClassName ), evtHandler); \
00040 } \
00041 \
00042 extern "C" DLLEXPORT void RELEASE_INSTANCE_FUNC(void * instance) \
00043 { \
00044 if (instance) \
00045 delete (VRUT::moduleClassName *)instance; \
00046 }
00047
00048 #ifndef REGISTER_LISTENER
00049 #define REGISTER_LISTENER(evtType) \
00050 { \
00051 kernelMsgSink->RegisterListener(GetID(), evtType); \
00052 }
00053 #endif
00054
00055 namespace VRUT
00056 {
00058 class Module
00059 {
00060 private:
00062 const MODULE_ID id;
00064 const wxString name;
00066 const unsigned type;
00068 bool isLooping;
00071 bool isDone;
00073 mutable wxMutex mutexDone;
00075 bool acceptEvents;
00077 mutable wxMutex mutexAcceptEvents;
00079 mutable wxMutex evtArrivedMutex;
00081 mutable wxCondition conditionEvtArrived;
00082
00083 protected:
00085 EventHandler * kernelMsgSink;
00087 MessageQueue<wxCommandEvent> evtQueue;
00093 long eventTimeout;
00095 Parameter::ParameterIdentificator eventTimeoutParamID;
00096
00099 virtual void processEvent(wxCommandEvent & evt)
00100 {
00101 switch (evt.GetEventType())
00102 {
00103 case Event::EVT_LOG_SET:
00104 wxLog::SetActiveTarget((wxLog *)evt.GetClientData());
00105 break;
00106 case Event::EVT_LOG_LEVEL_SET:
00107 wxLog::SetLogLevel(evt.GetInt());
00108 break;
00109 case Event::EVT_EXIT:
00110 isLooping = false;
00111 break;
00112 case Event::EVT_PARAM_SET:
00113 UPDATE_PARAM_FROM_EVENT_LONG(eventTimeoutParamID, eventTimeout, evt);
00114 break;
00115 default:
00116 break;
00117 }
00118 }
00121 virtual void processNextEvent()
00122 {
00123 MessageQueueError err;
00124 wxCommandEvent evt = evtQueue.ReceiveTimeout(eventTimeout, err);
00125 if (err == wxMSGQUEUE_NO_ERROR)
00126 {
00127 processEvent(evt);
00128 kernelMsgSink->ReleaseEvent(evt, true);
00129 }
00130 }
00132 void releasePendingEvents()
00133 {
00134 wxMutexLocker accEvtLocker(mutexAcceptEvents);
00135 acceptEvents = false;
00136 while (evtQueue.GetSize())
00137 {
00138 MessageQueueError err;
00139 wxCommandEvent evt = evtQueue.ReceiveTimeout(0, err);
00140 if (err == wxMSGQUEUE_NO_ERROR)
00141 kernelMsgSink->ReleaseEvent(evt, true);
00142 }
00143 }
00146 virtual void run()
00147 {
00148 }
00150 void * loop()
00151 {
00152 mutexDone.Lock();
00153 isDone = false;
00154 mutexDone.Unlock();
00155 isLooping = true;
00156 while (isLooping)
00157 {
00158 processNextEvent();
00159 run();
00160 }
00161 wxMutexLocker doneLock(mutexDone);
00162 releasePendingEvents();
00163 isDone = true;
00164 return 0;
00165 }
00166
00167 public:
00169 Module(const MODULE_ID & _id, const wxString & _name, unsigned _type, EventHandler * msgSink)
00170 : id(_id),
00171 name(_name),
00172 type(_type),
00173 isLooping(false),
00174 isDone(true),
00175 acceptEvents(true),
00176 kernelMsgSink(msgSink),
00177 eventTimeoutParamID(_name, wxT("eventTimeout"), _id),
00178 conditionEvtArrived(evtArrivedMutex)
00179 {
00181 wxLog::DontCreateOnDemand();
00182 wxASSERT_MSG(mutexDone.IsOk(), wxT("<Module>Failed to create mutex"));
00183 wxASSERT_MSG(mutexAcceptEvents.IsOk(), wxT("<Module>Failed to create mutex"));
00184 wxASSERT_MSG(conditionEvtArrived.IsOk(), wxT("<Module>Failed to create condition"));
00185 wxASSERT_MSG(evtArrivedMutex.IsOk(), wxT("<Module>Failed to create mutex"));
00187 eventTimeout = 1000;
00188 REGISTER_PARAM(eventTimeoutParamID, wxT("1000"));
00190 REGISTER_LISTENER(Event::EVT_EXIT);
00191 REGISTER_LISTENER(Event::EVT_LOG_LEVEL_SET);
00192 REGISTER_LISTENER(Event::EVT_LOG_SET);
00193 REGISTER_LISTENER(Event::EVT_PARAM_SET);
00194 }
00196 virtual ~Module()
00197 {
00198 kernelMsgSink->UnregisterListener(id);
00199 }
00200
00202 MODULE_ID GetID() const
00203 {
00204 return id;
00205 }
00207 bool IsActive() const
00208 {
00209 wxMutexLocker doneLock(mutexDone);
00210 return !isDone;
00211 }
00215 void PostEvent(wxCommandEvent & evt, bool highPriority = false)
00216 {
00217 wxMutexLocker accEvtLocker(mutexAcceptEvents);
00218 if (!acceptEvents)
00219 return;
00220 if (evt.GetEventType() == Event::EVT_EXIT)
00221 {
00222 wxMutexLocker doneLock(mutexDone);
00223 if (isDone)
00224 return;
00225 }
00226 wxMutexLocker evtLocker(evtArrivedMutex);
00227 MessageQueueError err = evtQueue.Post(evt, highPriority);
00228 wxASSERT_MSG(err == wxMSGQUEUE_NO_ERROR, wxT("<Module>Error posting event - exceeded message queue limit"));
00229 conditionEvtArrived.Signal();
00230 }
00232 void PostToKernel(wxCommandEvent & evt, bool highPriority = false)
00233 {
00234 evt.SetExtraLong(id.GetID());
00235 kernelMsgSink->PostEvent(evt, highPriority);
00236 }
00244 wxCommandEvent WaitForEvent(wxEventType evtType, long timeout, int evtID = -1, int evtInt = -1, const wxString evtStr = wxEmptyString)
00245 {
00246 wxMutexLocker evtLocker(evtArrivedMutex);
00247 const wxMilliClock_t waitUntil = wxGetLocalTimeMillis() + timeout;
00248 wxMilliClock_t now;
00249 do
00250 {
00251 wxCondError result = conditionEvtArrived.WaitTimeout(timeout);
00252 if (result == wxCOND_NO_ERROR)
00253 {
00254 wxCommandEvent newEvt = evtQueue.GetLast();
00255 if (newEvt.GetEventType() == Event::EVT_EXIT)
00256 return wxCommandEvent();
00257 if ((newEvt.GetEventType() == evtType)
00258 && ( (evtID == -1) || (evtID == newEvt.GetId()) )
00259 && ( (evtInt == -1) || (evtInt == newEvt.GetInt()) )
00260 && ( evtStr.IsEmpty() || evtStr.IsSameAs(newEvt.GetString()) ))
00261 {
00263 return evtQueue.GetLast(true);
00264 }
00265 }
00266 else
00267 return wxCommandEvent();
00268
00269 now = wxGetLocalTimeMillis();
00270 timeout = (waitUntil - now).ToLong();
00271 } while (now < waitUntil);
00272 return wxCommandEvent();
00273 }
00277 bool TestExit() const
00278 {
00279 return evtQueue.CheckFirst().GetEventType() == Event::EVT_EXIT;
00280 }
00282 const wxString & GetName() const
00283 {
00284 return name;
00285 }
00287 virtual wxString GetDesc() const = 0;
00289 bool IsOfType(MODULE_TYPE _type) const
00290 {
00291 return ( type & _type ) != 0;
00292 }
00293
00294 friend class ModuleThread;
00295 };
00296
00298 class ModuleThread : public wxThread
00299 {
00300 protected:
00302 Module * module;
00303
00304 public:
00306 ModuleThread(Module * _module) : wxThread(), module(_module) {}
00308 virtual ~ModuleThread() {}
00309
00311 virtual ExitCode Entry()
00312 {
00313 ExitCode ret = 0;
00314 if (module && !module->IsActive())
00315 ret = module->loop();
00316
00317 return ret;
00318 }
00319 };
00320
00321 typedef void (* CREATE_INSTANCE_FUNC_PROTO)CREATE_INSTANCE_FUNC_ARGS;
00322 typedef void (* RELEASE_INSTANCE_FUNC_PROTO)RELEASE_INSTANCE_FUNC_ARGS;
00323 };
00324
00325
00326 #endif