1 /*****************************************************************
2 |
3 |   Neptune - Threads
4 |
5 | Copyright (c) 2002-2008, Axiomatic Systems, LLC.
6 | All rights reserved.
7 |
8 | Redistribution and use in source and binary forms, with or without
9 | modification, are permitted provided that the following conditions are met:
10 |     * Redistributions of source code must retain the above copyright
11 |       notice, this list of conditions and the following disclaimer.
12 |     * Redistributions in binary form must reproduce the above copyright
13 |       notice, this list of conditions and the following disclaimer in the
14 |       documentation and/or other materials provided with the distribution.
15 |     * Neither the name of Axiomatic Systems nor the
16 |       names of its contributors may be used to endorse or promote products
17 |       derived from this software without specific prior written permission.
18 |
19 | THIS SOFTWARE IS PROVIDED BY AXIOMATIC SYSTEMS ''AS IS'' AND ANY
20 | EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
21 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
22 | DISCLAIMED. IN NO EVENT SHALL AXIOMATIC SYSTEMS BE LIABLE FOR ANY
23 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
24 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
25 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
26 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
28 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29 |
30  ****************************************************************/
31 
32 #ifndef _NPT_THREADS_H_
33 #define _NPT_THREADS_H_
34 
35 /*----------------------------------------------------------------------
36 |   includes
37 +---------------------------------------------------------------------*/
38 #include "NptTypes.h"
39 #include "NptConstants.h"
40 #include "NptInterfaces.h"
41 
42 /*----------------------------------------------------------------------
43 |   error codes
44 +---------------------------------------------------------------------*/
45 const int NPT_ERROR_CALLBACK_HANDLER_SHUTDOWN = NPT_ERROR_BASE_THREADS-0;
46 const int NPT_ERROR_CALLBACK_NOTHING_PENDING  = NPT_ERROR_BASE_THREADS-1;
47 
48 /*----------------------------------------------------------------------
49 |   constants
50 +---------------------------------------------------------------------*/
51 const int NPT_THREAD_PRIORITY_MIN           = -15;
52 const int NPT_THREAD_PRIORITY_IDLE          = -15;
53 const int NPT_THREAD_PRIORITY_LOWEST        =  -2;
54 const int NPT_THREAD_PRIORITY_BELOW_NORMAL  =  -1;
55 const int NPT_THREAD_PRIORITY_NORMAL        =   0;
56 const int NPT_THREAD_PRIORITY_ABOVE_NORMAL  =   1;
57 const int NPT_THREAD_PRIORITY_HIGHEST       =   2;
58 const int NPT_THREAD_PRIORITY_TIME_CRITICAL =  15;
59 const int NPT_THREAD_PRIORITY_MAX           =  15;
60 
61 /*----------------------------------------------------------------------
62 |   NPT_MutexInterface
63 +---------------------------------------------------------------------*/
64 class NPT_MutexInterface
65 {
66  public:
67     // methods
~NPT_MutexInterface()68     virtual           ~NPT_MutexInterface() {}
69     virtual NPT_Result Lock()   = 0;
70     virtual NPT_Result Unlock() = 0;
71 };
72 
73 /*----------------------------------------------------------------------
74 |   NPT_Mutex
75 +---------------------------------------------------------------------*/
76 class NPT_Mutex : public NPT_MutexInterface
77 {
78  public:
79     // methods
80                NPT_Mutex();
~NPT_Mutex()81               ~NPT_Mutex() { delete m_Delegate; }
Lock()82     NPT_Result Lock()   { return m_Delegate->Lock();   }
Unlock()83     NPT_Result Unlock() { return m_Delegate->Unlock(); }
84 
85  private:
86     // members
87     NPT_MutexInterface* m_Delegate;
88 };
89 
90 /*----------------------------------------------------------------------
91 |   NPT_AutoLock
92 +---------------------------------------------------------------------*/
93 class NPT_AutoLock
94 {
95  public:
96     // methods
NPT_AutoLock(NPT_Mutex & mutex)97      NPT_AutoLock(NPT_Mutex &mutex) : m_Mutex(mutex)   {
98         m_Mutex.Lock();
99     }
~NPT_AutoLock()100     ~NPT_AutoLock() {
101         m_Mutex.Unlock();
102     }
103 
104  private:
105     // members
106     NPT_Mutex& m_Mutex;
107 };
108 
109 /*----------------------------------------------------------------------
110 |   NPT_Lock
111 +---------------------------------------------------------------------*/
112 template <typename T>
113 class NPT_Lock : public T,
114                  public NPT_Mutex
115 {
116 };
117 
118 /*----------------------------------------------------------------------
119 |   NPT_SingletonLock
120 +---------------------------------------------------------------------*/
121 class NPT_SingletonLock
122 {
123 public:
GetInstance()124     static NPT_Mutex& GetInstance() {
125         return Instance;
126     }
127 
128 private:
129     static NPT_Mutex Instance;
130 };
131 
132 /*----------------------------------------------------------------------
133 |   NPT_SharedVariableInterface
134 +---------------------------------------------------------------------*/
135 class NPT_SharedVariableInterface
136 {
137  public:
138     // methods
~NPT_SharedVariableInterface()139     virtual           ~NPT_SharedVariableInterface() {}
140     virtual void       SetValue(int value)= 0;
141     virtual int        GetValue()         = 0;
142     virtual NPT_Result WaitUntilEquals(int value, NPT_Timeout timeout = NPT_TIMEOUT_INFINITE) = 0;
143     virtual NPT_Result WaitWhileEquals(int value, NPT_Timeout timeout = NPT_TIMEOUT_INFINITE) = 0;
144 };
145 
146 /*----------------------------------------------------------------------
147 |   NPT_SharedVariable
148 +---------------------------------------------------------------------*/
149 class NPT_SharedVariable : public NPT_SharedVariableInterface
150 {
151  public:
152     // methods
153                NPT_SharedVariable(int value = 0);
~NPT_SharedVariable()154               ~NPT_SharedVariable() { delete m_Delegate; }
SetValue(int value)155     void SetValue(int value) {
156         m_Delegate->SetValue(value);
157     }
GetValue()158     int GetValue() {
159         return m_Delegate->GetValue();
160     }
161     NPT_Result WaitUntilEquals(int value, NPT_Timeout timeout = NPT_TIMEOUT_INFINITE) {
162         return m_Delegate->WaitUntilEquals(value, timeout);
163     }
164     NPT_Result WaitWhileEquals(int value, NPT_Timeout timeout = NPT_TIMEOUT_INFINITE) {
165         return m_Delegate->WaitWhileEquals(value, timeout);
166     }
167 
168  private:
169     // members
170     NPT_SharedVariableInterface* m_Delegate;
171 };
172 
173 /*----------------------------------------------------------------------
174 |   NPT_AtomicVariableInterface
175 +---------------------------------------------------------------------*/
176 class NPT_AtomicVariableInterface
177 {
178  public:
179     // methods
~NPT_AtomicVariableInterface()180     virtual      ~NPT_AtomicVariableInterface() {}
181     virtual  int  Increment() = 0;
182     virtual  int  Decrement() = 0;
183     virtual  int  GetValue()  = 0;
184     virtual  void SetValue(int value)  = 0;
185 };
186 
187 /*----------------------------------------------------------------------
188 |   NPT_AtomicVariable
189 +---------------------------------------------------------------------*/
190 class NPT_AtomicVariable : public NPT_AtomicVariableInterface
191 {
192  public:
193     // methods
194          NPT_AtomicVariable(int value = 0);
~NPT_AtomicVariable()195         ~NPT_AtomicVariable() { delete m_Delegate;             }
Increment()196     int  Increment()          { return m_Delegate->Increment();}
Decrement()197     int  Decrement()          { return m_Delegate->Decrement();}
SetValue(int value)198     void SetValue(int value)  { m_Delegate->SetValue(value);   }
GetValue()199     int  GetValue()           { return m_Delegate->GetValue(); }
200 
201  private:
202     // members
203     NPT_AtomicVariableInterface* m_Delegate;
204 };
205 
206 /*----------------------------------------------------------------------
207 |   NPT_Runnable
208 +---------------------------------------------------------------------*/
209 class NPT_Runnable
210 {
211 public:
~NPT_Runnable()212     virtual ~NPT_Runnable() {}
213     virtual void Run() = 0;
214 };
215 
216 /*----------------------------------------------------------------------
217 |   NPT_ThreadInterface
218 +---------------------------------------------------------------------*/
219 class NPT_ThreadInterface: public NPT_Runnable, public NPT_Interruptible
220 {
221  public:
222     // methods
~NPT_ThreadInterface()223     virtual           ~NPT_ThreadInterface() {}
224     virtual NPT_Result Start() = 0;
225     virtual NPT_Result Wait(NPT_Timeout timeout = NPT_TIMEOUT_INFINITE) = 0;
SetPriority(int)226     virtual NPT_Result SetPriority(int /*priority*/) { return NPT_SUCCESS; }
227     virtual NPT_Result GetPriority(int& priority) = 0;
228 };
229 
230 /*----------------------------------------------------------------------
231 |   NPT_Thread
232 +---------------------------------------------------------------------*/
233 class NPT_Thread : public NPT_ThreadInterface
234 {
235  public:
236     // types
237     typedef unsigned long ThreadId;
238 
239     // class methods
240     static ThreadId GetCurrentThreadId();
241     static NPT_Result SetCurrentThreadPriority(int priority);
242     static NPT_Result GetCurrentThreadPriority(int& priority);
243 
244     // methods
245     explicit NPT_Thread(bool detached = false);
246     explicit NPT_Thread(NPT_Runnable& target, bool detached = false);
~NPT_Thread()247    ~NPT_Thread() { delete m_Delegate; }
248 
249     // NPT_ThreadInterface methods
Start()250     NPT_Result Start() {
251         return m_Delegate->Start();
252     }
253     NPT_Result Wait(NPT_Timeout timeout = NPT_TIMEOUT_INFINITE)  {
254         return m_Delegate->Wait(timeout);
255     }
SetPriority(int priority)256     NPT_Result SetPriority(int priority) {
257         return m_Delegate->SetPriority(priority);
258     }
GetPriority(int & priority)259     NPT_Result GetPriority(int& priority) {
260         return m_Delegate->GetPriority(priority);
261     }
262 
263     // NPT_Runnable methods
Run()264     virtual void Run() {}
265 
266     // NPT_Interruptible methods
Interrupt()267     virtual NPT_Result Interrupt() { return m_Delegate->Interrupt(); }
268 
269  private:
270     // members
271     NPT_ThreadInterface* m_Delegate;
272 };
273 
274 
275 /*----------------------------------------------------------------------
276 |   NPT_ThreadCallbackReceiver
277 +---------------------------------------------------------------------*/
278 class NPT_ThreadCallbackReceiver
279 {
280 public:
~NPT_ThreadCallbackReceiver()281     virtual ~NPT_ThreadCallbackReceiver() {}
282     virtual void OnCallback(void* args) = 0;
283 };
284 
285 /*----------------------------------------------------------------------
286 |   NPT_ThreadCallbackSlot
287 +---------------------------------------------------------------------*/
288 class NPT_ThreadCallbackSlot
289 {
290 public:
291     // types
292     class NotificationHelper {
293     public:
~NotificationHelper()294         virtual ~NotificationHelper() {};
295         virtual void Notify(void) = 0;
296     };
297 
298     // constructor
299     NPT_ThreadCallbackSlot();
300 
301     // methods
302     NPT_Result ReceiveCallback(NPT_ThreadCallbackReceiver& receiver, NPT_Timeout timeout = 0);
303     NPT_Result SendCallback(void* args);
304     NPT_Result SetNotificationHelper(NotificationHelper* helper);
305     NPT_Result Shutdown();
306 
307 protected:
308     // members
309     volatile void*      m_CallbackArgs;
310     volatile bool       m_Shutdown;
311     NPT_SharedVariable  m_Pending;
312     NPT_SharedVariable  m_Ack;
313     NPT_Mutex           m_ReadLock;
314     NPT_Mutex           m_WriteLock;
315     NotificationHelper* m_NotificationHelper;
316 };
317 
318 #endif // _NPT_THREADS_H_
319