Bike-X  0.8
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros
OVR_ThreadCommandQueue.h
Go to the documentation of this file.
1 /************************************************************************************
2 
3 PublicHeader: None
4 Filename : OVR_ThreadCommandQueue.h
5 Content : Command queue for operations executed on a thread
6 Created : October 29, 2012
7 Author : Michael Antonov
8 
9 Copyright : Copyright 2014 Oculus VR, Inc. All Rights reserved.
10 
11 Licensed under the Oculus VR Rift SDK License Version 3.1 (the "License");
12 you may not use the Oculus VR Rift SDK except in compliance with the License,
13 which is provided at the time of installation or download, or which
14 otherwise accompanies this software in either electronic or hard copy form.
15 
16 You may obtain a copy of the License at
17 
18 http://www.oculusvr.com/licenses/LICENSE-3.1
19 
20 Unless required by applicable law or agreed to in writing, the Oculus VR SDK
21 distributed under the License is distributed on an "AS IS" BASIS,
22 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
23 See the License for the specific language governing permissions and
24 limitations under the License.
25 
26 ************************************************************************************/
27 
28 #ifndef OVR_ThreadCommandQueue_h
29 #define OVR_ThreadCommandQueue_h
30 
31 #include "Kernel/OVR_Types.h"
32 #include "Kernel/OVR_List.h"
33 #include "Kernel/OVR_Atomic.h"
34 #include "Kernel/OVR_Threads.h"
35 
36 namespace OVR {
37 
38 class ThreadCommand;
39 class ThreadCommandQueue;
40 
41 
42 //-------------------------------------------------------------------------------------
43 // ***** ThreadCommand
44 
45 // ThreadCommand is a base class implementation for commands stored in ThreadCommandQueue.
47 {
48 public:
49 
50  // NotifyEvent is used by ThreadCommandQueue::PushCallAndWait to notify the
51  // calling (producer) thread when command is completed or queue slot is available.
52  class NotifyEvent : public ListNode<NotifyEvent>, public NewOverrideBase
53  {
55  public:
57 
58  void Wait() { E.Wait(); }
59  void PulseEvent() { E.PulseEvent(); }
60  };
61 
62  // ThreadCommand::PopBuffer is temporary storage for a command popped off
63  // by ThreadCommandQueue::PopCommand.
64  class PopBuffer
65  {
66  enum { MaxSize = 256 };
67 
69  union {
70  UByte Buffer[MaxSize];
71  UPInt Align;
72  };
73 
74  ThreadCommand* toCommand() const { return (ThreadCommand*)Buffer; }
75 
76  public:
77  PopBuffer() : Size(0) { }
78  ~PopBuffer();
79 
80  void InitFromBuffer(void* data);
81 
82  bool HasCommand() const { return Size != 0; }
83  UPInt GetSize() const { return Size; }
84  bool NeedsWait() const { return toCommand()->NeedsWait(); }
85  NotifyEvent* GetEvent() const { return toCommand()->pEvent; }
86 
87  // Execute the command and also notifies caller to finish waiting,
88  // if necessary.
89  void Execute();
90  };
91 
93  bool WaitFlag;
94  bool ExitFlag; // Marks the last exit command.
96 
97  ThreadCommand(UPInt size, bool waitFlag, bool exitFlag = false)
98  : Size((UInt16)size), WaitFlag(waitFlag), ExitFlag(exitFlag), pEvent(0) { }
99  virtual ~ThreadCommand() { }
100 
101  bool NeedsWait() const { return WaitFlag; }
102  UPInt GetSize() const { return Size; }
103 
104  virtual void Execute() const = 0;
105  // Copy constructor used for serializing this to memory buffer.
106  virtual ThreadCommand* CopyConstruct(void* p) const = 0;
107 };
108 
109 
110 //-------------------------------------------------------------------------------------
111 
112 // CleanType is a template that strips 'const' and '&' modifiers from the argument type;
113 // for example, typename CleanType<A&>::Type is equivalent to A.
114 template<class T> struct CleanType { typedef T Type; };
115 template<class T> struct CleanType<T&> { typedef T Type; };
116 template<class T> struct CleanType<const T> { typedef T Type; };
117 template<class T> struct CleanType<const T&> { typedef T Type; };
118 
119 // SelfType is a template that yields the argument type. This helps avoid conflicts with
120 // automatic template argument deduction for function calls when identical argument
121 // is already defined.
122 template<class T> struct SelfType { typedef T Type; };
123 
124 
125 
126 //-------------------------------------------------------------------------------------
127 // ThreadCommand specializations for member functions with different number of
128 // arguments and argument types.
129 
130 // Used to return nothing from a ThreadCommand, to avoid problems with 'void'.
131 struct Void
132 {
133  Void() {}
134  Void(int) {}
135 };
136 
137 // ThreadCommand for member function with 0 arguments.
138 template<class C, class R>
140 {
141  typedef R (C::*FnPtr)();
142  C* pClass;
144  R* pRet;
145 
146  void executeImpl() const
147  {
148  pRet ? (void)(*pRet = (pClass->*pFn)()) :
149  (void)(pClass->*pFn)();
150  }
151 
152 public:
153  ThreadCommandMF0(C* pclass, FnPtr fn, R* ret, bool needsWait)
154  : ThreadCommand(sizeof(ThreadCommandMF0), needsWait),
155  pClass(pclass), pFn(fn), pRet(ret) { }
156 
157  virtual void Execute() const { executeImpl(); }
158  virtual ThreadCommand* CopyConstruct(void* p) const
159  { return Construct<ThreadCommandMF0>(p, *this); }
160 };
161 
162 
163 // ThreadCommand for member function with 1 argument.
164 template<class C, class R, class A0>
166 {
167  typedef R (C::*FnPtr)(A0);
168  C* pClass;
170  R* pRet;
172 
173  void executeImpl() const
174  {
175  pRet ? (void)(*pRet = (pClass->*pFn)(AVal0)) :
176  (void)(pClass->*pFn)(AVal0);
177  }
178 
179 public:
180  ThreadCommandMF1(C* pclass, FnPtr fn, R* ret, A0 a0, bool needsWait)
181  : ThreadCommand(sizeof(ThreadCommandMF1), needsWait),
182  pClass(pclass), pFn(fn), pRet(ret), AVal0(a0) { }
183 
184  virtual void Execute() const { executeImpl(); }
185  virtual ThreadCommand* CopyConstruct(void* p) const
186  { return Construct<ThreadCommandMF1>(p, *this); }
187 };
188 
189 // ThreadCommand for member function with 2 arguments.
190 template<class C, class R, class A0, class A1>
192 {
193  typedef R (C::*FnPtr)(A0, A1);
194  C* pClass;
196  R* pRet;
199 
200  void executeImpl() const
201  {
202  pRet ? (void)(*pRet = (pClass->*pFn)(AVal0, AVal1)) :
203  (void)(pClass->*pFn)(AVal0, AVal1);
204  }
205 
206 public:
207  ThreadCommandMF2(C* pclass, FnPtr fn, R* ret, A0 a0, A1 a1, bool needsWait)
208  : ThreadCommand(sizeof(ThreadCommandMF2), needsWait),
209  pClass(pclass), pFn(fn), pRet(ret), AVal0(a0), AVal1(a1) { }
210 
211  virtual void Execute() const { executeImpl(); }
212  virtual ThreadCommand* CopyConstruct(void* p) const
213  { return Construct<ThreadCommandMF2>(p, *this); }
214 };
215 
216 
217 //-------------------------------------------------------------------------------------
218 // ***** ThreadCommandQueue
219 
220 // ThreadCommandQueue is a queue of executable function-call commands intended to be
221 // serviced by a single consumer thread. Commands are added to the queue with PushCall
222 // and removed with PopCall; they are processed in FIFO order. Multiple producer threads
223 // are supported and will be blocked if internal data buffer is full.
224 
226 {
227 public:
228 
230  virtual ~ThreadCommandQueue();
231 
232 
233  // Pops the next command from the thread queue, if any is available.
234  // The command should be executed by calling popBuffer->Execute().
235  // Returns 'false' if no command is available at the time of the call.
236  bool PopCommand(ThreadCommand::PopBuffer* popBuffer);
237 
238  // Generic implementaion of PushCommand; enqueues a command for execution.
239  // Returns 'false' if push failed, usually indicating thread shutdown.
240  bool PushCommand(const ThreadCommand& command);
241 
242  //
243  void PushExitCommand(bool wait);
244 
245  // Returns 'true' once ExitCommand has been processed, so the thread can shut down.
246  bool IsExiting() const;
247 
248 
249  // These two virtual functions serve as notifications for derived
250  // thread waiting.
251  virtual void OnPushNonEmpty_Locked() { }
252  virtual void OnPopEmpty_Locked() { }
253 
254 
255  // *** PushCall with no result
256 
257  // Enqueue a member function of 'this' class to be called on consumer thread.
258  // By default the function returns immediately; set 'wait' argument to 'true' to
259  // wait for completion.
260  template<class C, class R>
261  bool PushCall(R (C::*fn)(), bool wait = false)
262  { return PushCommand(ThreadCommandMF0<C,R>(static_cast<C*>(this), fn, 0, wait)); }
263  template<class C, class R, class A0>
264  bool PushCall(R (C::*fn)(A0), typename SelfType<A0>::Type a0, bool wait = false)
265  { return PushCommand(ThreadCommandMF1<C,R,A0>(static_cast<C*>(this), fn, 0, a0, wait)); }
266  template<class C, class R, class A0, class A1>
267  bool PushCall(R (C::*fn)(A0, A1),
268  typename SelfType<A0>::Type a0, typename SelfType<A1>::Type a1, bool wait = false)
269  { return PushCommand(ThreadCommandMF2<C,R,A0,A1>(static_cast<C*>(this), fn, 0, a0, a1, wait)); }
270  // Enqueue a specified member function call of class C.
271  // By default the function returns immediately; set 'wait' argument to 'true' to
272  // wait for completion.
273  template<class C, class R>
274  bool PushCall(C* p, R (C::*fn)(), bool wait = false)
275  { return PushCommand(ThreadCommandMF0<C,R>(p, fn, 0, wait)); }
276  template<class C, class R, class A0>
277  bool PushCall(C* p, R (C::*fn)(A0), typename SelfType<A0>::Type a0, bool wait = false)
278  { return PushCommand(ThreadCommandMF1<C,R,A0>(p, fn, 0, a0, wait)); }
279  template<class C, class R, class A0, class A1>
280  bool PushCall(C* p, R (C::*fn)(A0, A1),
281  typename SelfType<A0>::Type a0, typename SelfType<A1>::Type a1, bool wait = false)
282  { return PushCommand(ThreadCommandMF2<C,R,A0,A1>(p, fn, 0, a0, a1, wait)); }
283 
284 
285  // *** PushCall with Result
286 
287  // Enqueue a member function of 'this' class call and wait for call to complete
288  // on consumer thread before returning.
289  template<class C, class R>
290  bool PushCallAndWaitResult(R (C::*fn)(), R* ret)
291  { return PushCommand(ThreadCommandMF0<C,R>(static_cast<C*>(this), fn, ret, true)); }
292  template<class C, class R, class A0>
293  bool PushCallAndWaitResult(R (C::*fn)(A0), R* ret, typename SelfType<A0>::Type a0)
294  { return PushCommand(ThreadCommandMF1<C,R,A0>(static_cast<C*>(this), fn, ret, a0, true)); }
295  template<class C, class R, class A0, class A1>
296  bool PushCallAndWaitResult(R (C::*fn)(A0, A1), R* ret,
297  typename SelfType<A0>::Type a0, typename SelfType<A1>::Type a1)
298  { return PushCommand(ThreadCommandMF2<C,R,A0,A1>(static_cast<C*>(this), fn, ret, a0, a1, true)); }
299  // Enqueue a member function call for class C and wait for the call to complete
300  // on consumer thread before returning.
301  template<class C, class R>
302  bool PushCallAndWaitResult(C* p, R (C::*fn)(), R* ret)
303  { return PushCommand(ThreadCommandMF0<C,R>(p, fn, ret, true)); }
304  template<class C, class R, class A0>
305  bool PushCallAndWaitResult(C* p, R (C::*fn)(A0), R* ret, typename SelfType<A0>::Type a0)
306  { return PushCommand(ThreadCommandMF1<C,R,A0>(p, fn, ret, a0, true)); }
307  template<class C, class R, class A0, class A1>
308  bool PushCallAndWaitResult(C* p, R (C::*fn)(A0, A1), R* ret,
309  typename SelfType<A0>::Type a0, typename SelfType<A1>::Type a1)
310  { return PushCommand(ThreadCommandMF2<C,R,A0,A1>(p, fn, ret, a0, a1, true)); }
311 
312 private:
314 };
315 
316 
317 }
318 
319 #endif // OVR_ThreadCommandQueue_h
virtual void Execute() const
virtual void Execute() const
bool PushCall(R(C::*fn)(), bool wait=false)
class ThreadCommandQueueImpl * pImpl
CleanType< A1 >::Type AVal1
ThreadCommandMF2(C *pclass, FnPtr fn, R *ret, A0 a0, A1 a1, bool needsWait)
bool PushCall(C *p, R(C::*fn)(A0), typename SelfType< A0 >::Type a0, bool wait=false)
ThreadCommandMF0(C *pclass, FnPtr fn, R *ret, bool needsWait)
virtual void Execute() const =0
uint16_t UInt16
Definition: OVR_Types.h:251
bool PushCallAndWaitResult(C *p, R(C::*fn)(), R *ret)
bool Wait(unsigned delay=OVR_WAIT_INFINITE)
bool PushCall(R(C::*fn)(A0), typename SelfType< A0 >::Type a0, bool wait=false)
size_t UPInt
Definition: OVR_Types.h:218
bool PushCommand(const ThreadCommand &command)
uint8_t UByte
Definition: OVR_Types.h:249
bool PushCall(C *p, R(C::*fn)(), bool wait=false)
bool PushCallAndWaitResult(C *p, R(C::*fn)(A0, A1), R *ret, typename SelfType< A0 >::Type a0, typename SelfType< A1 >::Type a1)
virtual ThreadCommand * CopyConstruct(void *p) const
bool PushCallAndWaitResult(C *p, R(C::*fn)(A0), R *ret, typename SelfType< A0 >::Type a0)
virtual ThreadCommand * CopyConstruct(void *p) const
virtual ThreadCommand * CopyConstruct(void *p) const
bool PopCommand(ThreadCommand::PopBuffer *popBuffer)
bool PushCall(R(C::*fn)(A0, A1), typename SelfType< A0 >::Type a0, typename SelfType< A1 >::Type a1, bool wait=false)
ThreadCommand(UPInt size, bool waitFlag, bool exitFlag=false)
bool PushCallAndWaitResult(R(C::*fn)(A0, A1), R *ret, typename SelfType< A0 >::Type a0, typename SelfType< A1 >::Type a1)
ThreadCommandMF1(C *pclass, FnPtr fn, R *ret, A0 a0, bool needsWait)
bool PushCall(C *p, R(C::*fn)(A0, A1), typename SelfType< A0 >::Type a0, typename SelfType< A1 >::Type a1, bool wait=false)
bool PushCallAndWaitResult(R(C::*fn)(A0), R *ret, typename SelfType< A0 >::Type a0)
CleanType< A0 >::Type AVal0
CleanType< A0 >::Type AVal0
virtual void Execute() const
ThreadCommand * toCommand() const
void PulseEvent()
Definition: OVR_Threads.h:170
bool PushCallAndWaitResult(R(C::*fn)(), R *ret)
virtual ThreadCommand * CopyConstruct(void *p) const =0