00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017 #ifndef OVR_ThreadCommandQueue_h
00018 #define OVR_ThreadCommandQueue_h
00019
00020 #include "Kernel/OVR_Types.h"
00021 #include "Kernel/OVR_List.h"
00022 #include "Kernel/OVR_Atomic.h"
00023 #include "Kernel/OVR_Threads.h"
00024
00025 namespace OVR {
00026
00027 class ThreadCommand;
00028 class ThreadCommandQueue;
00029
00030
00031
00032
00033
00034
00035 class ThreadCommand
00036 {
00037 public:
00038
00039
00040
00041 class NotifyEvent : public ListNode<NotifyEvent>, public NewOverrideBase
00042 {
00043 Event E;
00044 public:
00045 NotifyEvent() { }
00046
00047 void Wait() { E.Wait(); }
00048 void PulseEvent() { E.PulseEvent(); }
00049 };
00050
00051
00052
00053 class PopBuffer
00054 {
00055 enum { MaxSize = 256 };
00056
00057 UPInt Size;
00058 union {
00059 UByte Buffer[MaxSize];
00060 UPInt Align;
00061 };
00062
00063 ThreadCommand* toCommand() const { return (ThreadCommand*)Buffer; }
00064
00065 public:
00066 PopBuffer() : Size(0) { }
00067 ~PopBuffer();
00068
00069 void InitFromBuffer(void* data);
00070
00071 bool HasCommand() const { return Size != 0; }
00072 UPInt GetSize() const { return Size; }
00073 bool NeedsWait() const { return toCommand()->NeedsWait(); }
00074 NotifyEvent* GetEvent() const { return toCommand()->pEvent; }
00075
00076
00077
00078 void Execute();
00079 };
00080
00081 UInt16 Size;
00082 bool WaitFlag;
00083 bool ExitFlag;
00084 NotifyEvent* pEvent;
00085
00086 ThreadCommand(UPInt size, bool waitFlag, bool exitFlag = false)
00087 : Size((UInt16)size), WaitFlag(waitFlag), ExitFlag(exitFlag), pEvent(0) { }
00088 virtual ~ThreadCommand() { }
00089
00090 bool NeedsWait() const { return WaitFlag; }
00091 UPInt GetSize() const { return Size; }
00092
00093 virtual void Execute() const = 0;
00094
00095 virtual ThreadCommand* CopyConstruct(void* p) const = 0;
00096 };
00097
00098
00099
00100
00101
00102
00103 template<class T> struct CleanType { typedef T Type; };
00104 template<class T> struct CleanType<T&> { typedef T Type; };
00105 template<class T> struct CleanType<const T> { typedef T Type; };
00106 template<class T> struct CleanType<const T&> { typedef T Type; };
00107
00108
00109
00110
00111 template<class T> struct SelfType { typedef T Type; };
00112
00113
00114
00115
00116
00117
00118
00119
00120 struct Void
00121 {
00122 Void() {}
00123 Void(int) {}
00124 };
00125
00126
00127 template<class C, class R>
00128 class ThreadCommandMF0 : public ThreadCommand
00129 {
00130 typedef R (C::*FnPtr)();
00131 C* pClass;
00132 FnPtr pFn;
00133 R* pRet;
00134
00135 void executeImpl() const
00136 {
00137 pRet ? (void)(*pRet = (pClass->*pFn)()) :
00138 (void)(pClass->*pFn)();
00139 }
00140
00141 public:
00142 ThreadCommandMF0(C* pclass, FnPtr fn, R* ret, bool needsWait)
00143 : ThreadCommand(sizeof(ThreadCommandMF0), needsWait),
00144 pClass(pclass), pFn(fn), pRet(ret) { }
00145
00146 virtual void Execute() const { executeImpl(); }
00147 virtual ThreadCommand* CopyConstruct(void* p) const
00148 { return Construct<ThreadCommandMF0>(p, *this); }
00149 };
00150
00151
00152
00153 template<class C, class R, class A0>
00154 class ThreadCommandMF1 : public ThreadCommand
00155 {
00156 typedef R (C::*FnPtr)(A0);
00157 C* pClass;
00158 FnPtr pFn;
00159 R* pRet;
00160 typename CleanType<A0>::Type AVal0;
00161
00162 void executeImpl() const
00163 {
00164 pRet ? (void)(*pRet = (pClass->*pFn)(AVal0)) :
00165 (void)(pClass->*pFn)(AVal0);
00166 }
00167
00168 public:
00169 ThreadCommandMF1(C* pclass, FnPtr fn, R* ret, A0 a0, bool needsWait)
00170 : ThreadCommand(sizeof(ThreadCommandMF1), needsWait),
00171 pClass(pclass), pFn(fn), pRet(ret), AVal0(a0) { }
00172
00173 virtual void Execute() const { executeImpl(); }
00174 virtual ThreadCommand* CopyConstruct(void* p) const
00175 { return Construct<ThreadCommandMF1>(p, *this); }
00176 };
00177
00178
00179 template<class C, class R, class A0, class A1>
00180 class ThreadCommandMF2 : public ThreadCommand
00181 {
00182 typedef R (C::*FnPtr)(A0, A1);
00183 C* pClass;
00184 FnPtr pFn;
00185 R* pRet;
00186 typename CleanType<A0>::Type AVal0;
00187 typename CleanType<A1>::Type AVal1;
00188
00189 void executeImpl() const
00190 {
00191 pRet ? (void)(*pRet = (pClass->*pFn)(AVal0, AVal1)) :
00192 (void)(pClass->*pFn)(AVal0, AVal1);
00193 }
00194
00195 public:
00196 ThreadCommandMF2(C* pclass, FnPtr fn, R* ret, A0 a0, A1 a1, bool needsWait)
00197 : ThreadCommand(sizeof(ThreadCommandMF2), needsWait),
00198 pClass(pclass), pFn(fn), pRet(ret), AVal0(a0), AVal1(a1) { }
00199
00200 virtual void Execute() const { executeImpl(); }
00201 virtual ThreadCommand* CopyConstruct(void* p) const
00202 { return Construct<ThreadCommandMF2>(p, *this); }
00203 };
00204
00205
00206
00207
00208
00209
00210
00211
00212
00213
00214 class ThreadCommandQueue
00215 {
00216 public:
00217
00218 ThreadCommandQueue();
00219 virtual ~ThreadCommandQueue();
00220
00221
00222
00223
00224
00225 bool PopCommand(ThreadCommand::PopBuffer* popBuffer);
00226
00227
00228
00229 bool PushCommand(const ThreadCommand& command);
00230
00231
00232 void PushExitCommand(bool wait);
00233
00234
00235 bool IsExiting() const;
00236
00237
00238
00239
00240 virtual void OnPushNonEmpty_Locked() { }
00241 virtual void OnPopEmpty_Locked() { }
00242
00243
00244
00245
00246
00247
00248
00249 template<class C, class R>
00250 bool PushCall(R (C::*fn)(), bool wait = false)
00251 { return PushCommand(ThreadCommandMF0<C,R>(static_cast<C*>(this), fn, 0, wait)); }
00252 template<class C, class R, class A0>
00253 bool PushCall(R (C::*fn)(A0), typename SelfType<A0>::Type a0, bool wait = false)
00254 { return PushCommand(ThreadCommandMF1<C,R,A0>(static_cast<C*>(this), fn, 0, a0, wait)); }
00255 template<class C, class R, class A0, class A1>
00256 bool PushCall(R (C::*fn)(A0, A1),
00257 typename SelfType<A0>::Type a0, typename SelfType<A1>::Type a1, bool wait = false)
00258 { return PushCommand(ThreadCommandMF2<C,R,A0,A1>(static_cast<C*>(this), fn, 0, a0, a1, wait)); }
00259
00260
00261
00262 template<class C, class R>
00263 bool PushCall(C* p, R (C::*fn)(), bool wait = false)
00264 { return PushCommand(ThreadCommandMF0<C,R>(p, fn, 0, wait)); }
00265 template<class C, class R, class A0>
00266 bool PushCall(C* p, R (C::*fn)(A0), typename SelfType<A0>::Type a0, bool wait = false)
00267 { return PushCommand(ThreadCommandMF1<C,R,A0>(p, fn, 0, a0, wait)); }
00268 template<class C, class R, class A0, class A1>
00269 bool PushCall(C* p, R (C::*fn)(A0, A1),
00270 typename SelfType<A0>::Type a0, typename SelfType<A1>::Type a1, bool wait = false)
00271 { return PushCommand(ThreadCommandMF2<C,R,A0,A1>(p, fn, 0, a0, a1, wait)); }
00272
00273
00274
00275
00276
00277
00278 template<class C, class R>
00279 bool PushCallAndWaitResult(R (C::*fn)(), R* ret)
00280 { return PushCommand(ThreadCommandMF0<C,R>(static_cast<C*>(this), fn, ret, true)); }
00281 template<class C, class R, class A0>
00282 bool PushCallAndWaitResult(R (C::*fn)(A0), R* ret, typename SelfType<A0>::Type a0)
00283 { return PushCommand(ThreadCommandMF1<C,R,A0>(static_cast<C*>(this), fn, ret, a0, true)); }
00284 template<class C, class R, class A0, class A1>
00285 bool PushCallAndWaitResult(R (C::*fn)(A0, A1), R* ret,
00286 typename SelfType<A0>::Type a0, typename SelfType<A1>::Type a1)
00287 { return PushCommand(ThreadCommandMF2<C,R,A0,A1>(static_cast<C*>(this), fn, ret, a0, a1, true)); }
00288
00289
00290 template<class C, class R>
00291 bool PushCallAndWaitResult(C* p, R (C::*fn)(), R* ret)
00292 { return PushCommand(ThreadCommandMF0<C,R>(p, fn, ret, true)); }
00293 template<class C, class R, class A0>
00294 bool PushCallAndWaitResult(C* p, R (C::*fn)(A0), R* ret, typename SelfType<A0>::Type a0)
00295 { return PushCommand(ThreadCommandMF1<C,R,A0>(p, fn, ret, a0, true)); }
00296 template<class C, class R, class A0, class A1>
00297 bool PushCallAndWaitResult(C* p, R (C::*fn)(A0, A1), R* ret,
00298 typename SelfType<A0>::Type a0, typename SelfType<A1>::Type a1)
00299 { return PushCommand(ThreadCommandMF2<C,R,A0,A1>(p, fn, ret, a0, a1, true)); }
00300
00301 private:
00302 class ThreadCommandQueueImpl* pImpl;
00303 };
00304
00305
00306 }
00307
00308 #endif // OVR_ThreadCommandQueue_h