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(bool recursive = false);
~NPT_Mutex()81               ~NPT_Mutex() override { delete m_Delegate; }
Lock()82     NPT_Result Lock() override   { return m_Delegate->Lock();   }
Unlock()83     NPT_Result Unlock() override { 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() override { delete m_Delegate; }
SetValue(int value)155     void SetValue(int value) override {
156         m_Delegate->SetValue(value);
157     }
GetValue()158     int GetValue() override {
159         return m_Delegate->GetValue();
160     }
161     NPT_Result WaitUntilEquals(int value, NPT_Timeout timeout = NPT_TIMEOUT_INFINITE) override {
162         return m_Delegate->WaitUntilEquals(value, timeout);
163     }
164     NPT_Result WaitWhileEquals(int value, NPT_Timeout timeout = NPT_TIMEOUT_INFINITE) override {
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() override { delete m_Delegate;             }
Increment()196     int  Increment() override          { return m_Delegate->Increment();}
Decrement()197     int  Decrement() override          { return m_Delegate->Decrement();}
SetValue(int value)198     void SetValue(int value) override  { m_Delegate->SetValue(value);   }
GetValue()199     int  GetValue() override           { 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               ~NPT_ThreadInterface() override {}
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 CancelBlockerSocket() = 0;
228     virtual NPT_Result GetPriority(int& priority) = 0;
229 };
230 
231 /*----------------------------------------------------------------------
232 |   NPT_Thread
233 +---------------------------------------------------------------------*/
234 class NPT_Thread : public NPT_ThreadInterface
235 {
236  public:
237     // types
238     typedef NPT_UInt64 ThreadId;
239 
240     // class methods
241     static ThreadId   GetCurrentThreadId();
242     static NPT_Result SetCurrentThreadPriority(int priority);
243     static NPT_Result GetCurrentThreadPriority(int& priority);
244 
245     // methods
246     explicit NPT_Thread(bool detached = false);
247     explicit NPT_Thread(NPT_Runnable& target, bool detached = false);
~NPT_Thread()248    ~NPT_Thread() override { delete m_Delegate; }
249 
250     // cancel any socket that this thread may be waiting for
CancelBlockerSocket()251     NPT_Result CancelBlockerSocket() override { return m_Delegate->CancelBlockerSocket(); }
252 
253     // NPT_ThreadInterface methods
Start()254     NPT_Result Start() override {
255         return m_Delegate->Start();
256     }
257     NPT_Result Wait(NPT_Timeout timeout = NPT_TIMEOUT_INFINITE) override  {
258         return m_Delegate->Wait(timeout);
259     }
SetPriority(int priority)260     NPT_Result SetPriority(int priority) override {
261         return m_Delegate->SetPriority(priority);
262     }
GetPriority(int & priority)263     NPT_Result GetPriority(int& priority) override {
264         return m_Delegate->GetPriority(priority);
265     }
266 
267     // NPT_Runnable methods
Run()268     void Run() override {}
269 
270     // NPT_Interruptible methods
Interrupt()271     NPT_Result Interrupt() override { return m_Delegate->Interrupt(); }
272 
273  private:
274     // members
275     NPT_ThreadInterface* m_Delegate;
276 };
277 
278 
279 /*----------------------------------------------------------------------
280 |   NPT_ThreadCallbackReceiver
281 +---------------------------------------------------------------------*/
282 class NPT_ThreadCallbackReceiver
283 {
284 public:
~NPT_ThreadCallbackReceiver()285     virtual ~NPT_ThreadCallbackReceiver() {}
286     virtual void OnCallback(void* args) = 0;
287 };
288 
289 /*----------------------------------------------------------------------
290 |   NPT_ThreadCallbackSlot
291 +---------------------------------------------------------------------*/
292 class NPT_ThreadCallbackSlot
293 {
294 public:
295     // types
296     class NotificationHelper {
297     public:
~NotificationHelper()298         virtual ~NotificationHelper() {};
299         virtual void Notify(void) = 0;
300     };
301 
302     // constructor
303     NPT_ThreadCallbackSlot();
304 
305     // methods
306     NPT_Result ReceiveCallback(NPT_ThreadCallbackReceiver& receiver, NPT_Timeout timeout = 0);
307     NPT_Result SendCallback(void* args);
308     NPT_Result SetNotificationHelper(NotificationHelper* helper);
309     NPT_Result Shutdown();
310 
311 protected:
312     // members
313     volatile void*      m_CallbackArgs;
314     volatile bool       m_Shutdown;
315     NPT_SharedVariable  m_Pending;
316     NPT_SharedVariable  m_Ack;
317     NPT_Mutex           m_ReadLock;
318     NPT_Mutex           m_WriteLock;
319     NotificationHelper* m_NotificationHelper;
320 };
321 
322 #endif // _NPT_THREADS_H_
323