gwnavruntime/kernel/SF_Threads.h Source File

SF_Threads.h
Go to the documentation of this file.
1 /*
2 * Copyright 2015 Autodesk, Inc. All rights reserved.
3 * Use of this software is subject to the terms of the Autodesk license agreement and any attachments or Appendices thereto provided at the time of installation or download,
4 * or which otherwise accompanies this software in either electronic or hard copy form, or which is signed by you and accepted by Autodesk.
5 */
6 
7 /**************************************************************************
8 
9 PublicHeader: None
10 Filename : KY_Threads.h
11 Content : Contains thread-related (safe) functionality
12 Created : May 5, 2003
13 Authors : Michael Antonov, Andrew Reisse
14 
15 **************************************************************************/
16 
17 #ifndef INC_KY_Kernel_Threads_H
18 #define INC_KY_Kernel_Threads_H
19 
24 
25 #if defined(KY_OS_WINMETRO)
26 #include <ppl.h>
27 #if defined(KY_USE_STD11_THREADS)
28 #include <thread>
29 #endif
30 #endif
31 
32 #if defined(KY_OS_WII) || defined(KY_OS_WIIU)
33 #include <setjmp.h>
35 
36 #elif defined(KY_OS_3DS)
37 #include <setjmp.h>
38 #include <nn/os/os_Thread.h>
39 #endif
40 
41 // Defines the infinite wait delay timeout
42 #define KY_WAIT_INFINITE 0xFFFFFFFF
43 
44 
45 namespace Kaim {
46 
47 // ****** Declared classes
48 
49 // To be defined in the project configuration options
50 #ifdef KY_ENABLE_THREADS
51 
52 // Declared with thread support only:
53 class Waitable;
54 class AcquireInterface;
55 class Mutex;
56 class WaitCondition;
57 class Event;
58 class Semaphore;
59 
60 #else
61 //
62 // declare stubs for non threaded build
63 //
64 
65 typedef void* ThreadId;
66 
67 // Returns the unique Id of a thread it is called on, intended for
68 // comparison purposes.
69 ThreadId GetCurrentThreadId();
70 
71 // Mutex
72 class Mutex
73 {
74 public:
75  Mutex(bool recursive = 1, bool multiWait = 0) { KY_UNUSED2(recursive, multiWait); }
76  void DoLock() { }
77  bool TryLock() { return false; }
78  void Unlock() { }
79  bool IsLockedByAnotherThread() { return false; }
80  bool IsSignaled() const { return false; }
81  void* GetAcquireInterface() { return NULL; }
82  bool CanAcquire() { return false; }
83  bool TryAcquire() { return false; }
84  bool TryAcquireCommit() { return false; }
85  bool TryAcquireCancel() { return false; }
86 
87  class Locker
88  {
89  public:
90  Mutex *pMutex;
91  Locker(Mutex *pmutex) { KY_UNUSED(pmutex); }
92  };
93 };
94 
95 // WaitCondition
96 class WaitCondition
97 {
98 public:
99  bool Wait(Mutex *pmutex, unsigned delay = KY_WAIT_INFINITE) { KY_UNUSED2(pmutex, delay); return false; }
100  void Notify() { }
101  void NotifyAll() { }
102 };
103 
104 // Thread
105 class Thread : public RefCountBase<Thread, Stat_Default_Mem>
106 {
107 public:
108  enum ThreadState
109  {
110  NotRunning = 0,
111  Running = 1,
112  Suspended = 2
113  };
114  enum ThreadPriority
115  {
116  CriticalPriority,
117  HighestPriority,
118  AboveNormalPriority,
119  NormalPriority,
120  BelowNormalPriority,
121  LowestPriority,
122  IdlePriority,
123  };
124  typedef int (*ThreadFn)(Thread *pthread, void* h);
125  struct CreateParams
126  {
127  CreateParams(ThreadFn func = 0, void* hand = 0, UPInt ssize = 128 * 1024,
128  int proc = -1, ThreadState state = NotRunning, ThreadPriority prior = NormalPriority)
129  { KY_UNUSED6(func, hand, ssize, proc, state, prior); }
130  };
131 
132  Thread(UPInt stackSize = 128 * 1024, int processor = -1) { KY_UNUSED2(stackSize, processor); }
133  Thread(ThreadFn threadFunction, void* userHandle = 0, UPInt stackSize = 128 * 1024,
134  int processor = -1, ThreadState initialState = NotRunning) { KY_UNUSED5(threadFunction, userHandle, stackSize, processor, initialState); }
135  explicit KY_EXPORT Thread(const CreateParams& params) { KY_UNUSED(params); }
136  static void KY_CDECL FinishAllThreads() { }
137  int Run() { return 0; }
138  void OnExit(){ }
139  bool Start(ThreadState initialState = Running) { KY_UNUSED(initialState); return true; }
140  void Exit(int exitCode=0) { KY_UNUSED(exitCode); }
141  bool Suspend() { return true; }
142  bool Resume() { return true; }
143 
144  bool GetExitFlag() const { return true; }
145  void SetExitFlag(bool exitFlag) { KY_UNUSED(exitFlag); }
146  bool IsFinished() const { return true; }
147  bool IsSuspended() const { return false; }
148  ThreadState GetThreadState() const { return NotRunning; }
149  static int GetCPUCount() { return 1; }
150  KY_INLINE int GetExitCode() const { return 0; }
151 
152  // Returns an OS handle
153 #if defined(KY_OS_WIN32) || defined(KY_OS_XBOX) || defined(KY_OS_XBOX360)
154  void* GetOSHandle() const { return NULL; }
155 #elif defined(KY_OS_WII) || defined(KY_OS_WIIU)
156  OSThread * GetOSHandle() const { return NULL; }
157 #elif defined(KY_OS_PS3)
158  sys_ppu_thread_t GetOSHandle() const { return 0; }
159 #elif defined(KY_OS_PSVITA)
160  SceUID GetOSHandle() const { return 0; }
161 #elif defined(KY_OS_3DS)
162  nn::os::Thread* GetOSHandle() const { return NULL; }
163 #else
164  pthread_t GetOSHandle() const { return 0; }
165 #endif
166 
167  ThreadId GetThreadId() const { return 0; }
168 
169  static int GetOSPriority(ThreadPriority) { return 0; }
170  static bool Sleep(unsigned secs) { KY_UNUSED(secs); return false; }
171  static bool MSleep(unsigned msecs) { KY_UNUSED(msecs); return false; }
172 
173  bool IsSignaled() const { return false; }
174  void* GetAcquireInterface() { return this; }
175  bool CanAcquire() { return IsSignaled(); }
176  bool TryAcquire() { return IsSignaled(); }
177  void SetThreadName( const char* name ) { KY_UNUSED(name); }
178 #if defined(KY_OS_WII) || defined(KY_OS_WIIU)
179 public: // for Wii compiler 4.3 145
180  struct ThreadDataWii : public ListNode<ThreadDataWii>
181  {
182  OSThread ThreadHandle;
183  jmp_buf ExitJmp;
184  UByte Stack[32] __attribute__((aligned(32)));
185  };
186 #endif
187 };
188 
189 // Event
190 class Event
191 {
192 public:
193  Event(bool setInitially = 0, bool multiWait = 0) { KY_UNUSED2(setInitially, multiWait); }
194  bool Wait(unsigned delay = KY_WAIT_INFINITE) { KY_UNUSED(delay); return true; }
195  void SetEvent() { }
196  void ResetEvent(){ }
197  void PulseEvent(){ }
198  bool IsSignaled() const { return false; }
199  void* GetAcquireInterface() { return NULL; }
200  bool CanAcquire() { return false; }
201  bool TryAcquire() { return false; }
202  bool TryAcquireCommit(){ return false; }
203  bool TryAcquireCancel(){ return false; }
204 };
205 #endif
206 
207 
208 // The rest of the classes are only defined when thread support is enabled.
209 #ifdef KY_ENABLE_THREADS
210 
211 
212 // ***** Waitable and Acquisition Interface
213 
214 /*
215  AcquireInterface provides a two-stage acquisition interface for a resource. This interface is used
216  primarily to acquire multiple objects that can be shared among threads. For this reason,
217  AcquireInterface is often used together with Waitable. Whenever a waitable object changes state
218  indicating that a shared resource is potentially available, this abstract acquisition interface is used to
219  acquire the resource in a resource-independent manner.
220 
221  In the first stage of acquisition TryAcquire is called to see if the resource can be obtained. If it succeeds,
222  the resource is considered to be acquired, and TryAcquireCommit is called to confirm the ownership. If the
223  resource is, however, not needed (because, for example, acquisition of another object in a multi-object wait
224  has failed) TryAcquireCancel can be called.
225 */
226 
227 
228 class AcquireInterface
229 {
230 public:
231  KY_EXPORT virtual ~AcquireInterface() { }
232 
233  // Call this function to test if an object can be acquired
234  // Like TryAcquire() and TryAcquireCancel() pair, except does not actually try to acquire the object
235  // This function is called from a different thread then the acquisition waiting thread, it is used to check
236  // for potential availability of resource during Wait/Acquire functions
237  KY_EXPORT virtual bool CanAcquire();
238 
239  // These functions implement a two-stage acquiring protocol used by the AcquireMultiple functions.
240  // First, TryAcquire is called to capture resource. If it succeeded,
241  // TryAcquireCommit is called to permanently obtain the resource.
242  // TryAcquireCancel can be called instead of TryAcquireCommit
243  // in order to release the resource, and leave it untouched.
244  // These functions are only called from the waiter thread by the AcquireMultiple functions.
245 
246  // Try to acquire the resource, return 1 if succeeded.
247  KY_EXPORT virtual bool TryAcquire();
248  // Complete resource acquisition. Should not fail in general.
249  KY_EXPORT virtual bool TryAcquireCommit();
250  // Cancel resource acquisition. Should not fail in general.
251  KY_EXPORT virtual bool TryAcquireCancel();
252 
253  // Static function to acquire multiple objects simultaneously
254  KY_EXPORT static bool AcquireMultipleObjects(Waitable** waitList, unsigned waitCount,
255  unsigned delay = KY_WAIT_INFINITE);
256  // Static function to acquire one of multiple objects in a list
257  // Returns the index of the object acquired, -1 for fail (wait expired)
258  KY_EXPORT static int AcquireOneOfMultipleObjects(Waitable** waitList, unsigned waitCount,
259  unsigned delay = KY_WAIT_INFINITE);
260 };
261 
262 
263 
264 // Static acquire interface that doesn't do anything
265 // All acquire calls on this interface always succeed.
266 
267 class DefaultAcquireInterface : public AcquireInterface
268 {
269 public:
270  KY_EXPORT virtual ~DefaultAcquireInterface() { }
271 
272  // Does nothing
273 
274  KY_EXPORT static DefaultAcquireInterface* GetDefaultAcquireInterface();
275 };
276 
277 
278 
279 /*
280  Waitable interface is used for thread-shared objects that need to be waited on. A waitable object
281  has an associated 'Signalled' state such that an object is signaled when its associated resource is available,
282  and non-signaled when it is not available. Some objects, such as a Semaphore, can have multiple internal signaled
283  states; in this case the object is considered to be signaled if ANY amount of a resource is available, and
284  non-signaled if NO resource is available.
285 
286  Waiting on a Waitable object is achieved with help of handlers installed by the waiter threads. Whenever the
287  objects state changes from non-signaled to signaled, or from one internal gradation of signaled to another,
288  wait handlers are called (handlers should not get called when the object changes its state from signaled to
289  non-signaled). When called, wait handlers can be used to wake up a waiter thread, so that it can compete for the
290  acquisition of the object's associated resource. The actual acquisition of the resource can happen either through
291  object-specific methods for with help of an associated AcquireInterface.
292 */
293 
294 class Waitable : public RefCountBase<Waitable, Stat_Default_Mem>
295 {
296 public:
297 
298  // Wait handler type
299  typedef void (*WaitHandler)(void* pdata);
300 
301 protected:
302  class HandlerStruct
303  {
304  public:
305  WaitHandler Handler;
306  void* pUserData;
307 
308  // Default constructor - only used in garray.
309  HandlerStruct()
310  {
311  Handler = 0;
312  pUserData = 0;
313  }
314 
315  HandlerStruct(WaitHandler h, void* pd)
316  {
317  Handler = h;
318  pUserData = pd;
319  }
320  HandlerStruct(const HandlerStruct &src)
321  {
322  Handler = src.Handler;
323  pUserData = src.pUserData;
324  }
325 
326  HandlerStruct & operator = (const HandlerStruct &src)
327  {
328  Handler = src.Handler;
329  pUserData = src.pUserData;
330  return *this;
331  }
332 
333  bool operator == (const HandlerStruct &src)
334  {
335  return (Handler == src.Handler) && (pUserData==src.pUserData);
336  }
337  };
338 
339  // Handler array and lock are allocated in a separate ref-counted object
340  // so that their lifetime can be extended past the waitable object in
341  // case other threads are still executing wait handlers. HandlerArray is
342  // only allocated if multiWait was passed in a contsructor; otherwise
343  // it is null.
344  struct HandlerArray : public NewOverrideBase<Stat_Default_Mem>
345  {
346  typedef ArrayConstPolicy<0, 16, true> SizePolicyType; // MinCapacity=0, Granularity=16, NeverShrink
347  typedef Array<HandlerStruct, Stat_Default_Mem, SizePolicyType> HandlerArrayType;
348 
349  AtomicInt<SInt32> RefCount;
350  HandlerArrayType Handlers;
351  Lock HandlersLock;
352 
353  HandlerArray() { RefCount.Value = 1; }
354 
355  void AddRef() { RefCount++; }
356  // Decrement ref count. This needs to be thread-safe, since
357  // a different thread could have also decremented the ref count.
358  KY_EXPORT void Release();
359 
360  // Calls all of the installed handlers during a lock.
361  KY_EXPORT void CallWaitHandlers();
362  };
363 
364  // A pointer to handler array, only allocated if 'enabled' flag was passed
365  // in a constructor. Such setup is done to save memory and improve performance
366  // of non-multiwait Mutex. Unfortunately, lazy initialization can not
367  // be used for pHandlers, since access of this variable must be done before
368  // system mutex Unlock, and thus can occur before AddHandlers in multi-object wait.
369  HandlerArray* pHandlers;
370 
371 public:
372 
373  // Enable flag must be passed to enable WaitHandlers; if not specified the
374  // wait handlers and multi-object wait functionality is not available.
375  Waitable(bool enable);
376 
377  virtual ~Waitable();
378 
379  // Invoke the associated wait handlers; only safe if we know Waitable could not
380  // have died in response to it being signaled (otherwise GetCallableHandlers should be used).
381  KY_EXPORT void CallWaitHandlers();
382 
383  // A handle used to access wait handlers after waitable has been signaled
384  // and thus can not be accessed directly (other threads can kill the object).
385  class CallableHandlers
386  {
387  friend class Waitable;
388  Ptr<HandlerArray> pArray;
389  public:
390  CallableHandlers() { }
391  // Calls handlers in a handle.
392  inline void CallWaitHandlers() { if (pArray) pArray->CallWaitHandlers(); }
393  };
394 
395  inline void GetCallableHandlers(CallableHandlers *ph) { if (pHandlers) ph->pArray = pHandlers; }
396 
397 
398  // Register a handler to be notified when the wait is finished.
399  // The wait may be called on a different thread and is
400  // usually responsible for waking the waiting thread.
401  KY_EXPORT bool AddWaitHandler(WaitHandler handler, void* pdata);
402  KY_EXPORT bool RemoveWaitHandler(WaitHandler handler, void* pdata);
403 
404  // Wait for this object to become signaled
405  KY_EXPORT bool Wait(unsigned delay = KY_WAIT_INFINITE);
406  // Acquires the current object based on associated acquisition interface
407  KY_EXPORT bool Acquire(unsigned delay = KY_WAIT_INFINITE);
408 
409  // Returns 1 if the object is currently signaled, i.e. the associated
410  // data is available and no wait is required. Note that this state can change
411  // asynchronously based on behavior of other threads.
412  KY_EXPORT virtual bool IsSignaled() const;
413 
414  // Obtain the acquisition interface
415  KY_EXPORT virtual AcquireInterface* GetAcquireInterface();
416 };
417 
418 
419 
420 // ***** Mutex Class
421 
422 // Mutex class represents a Mutex??a synchronization object that provides access
423 // serialization between different threads, allowing one thread mutually exclusive access
424 // to a resource.
425 
426 class MutexImpl;
427 
428 class Mutex : public Waitable, public AcquireInterface
429 {
430  friend class WaitConditionImpl;
431  friend class MutexImpl;
432 
433  // Internal mutex structures
434  MutexImpl *pImpl;
435 
436 public:
437  // Constructor/destructor
438  KY_EXPORT Mutex(bool recursive = 1, bool multiWait = 0);
439  KY_EXPORT ~Mutex();
440 
441  // Locking functions
442  KY_EXPORT void DoLock();
443  KY_EXPORT bool TryLock();
444  KY_EXPORT void Unlock();
445 
446  // Returns 1 if the mutes is currently locked by another thread
447  // Returns 0 if the mutex is not locked by another thread, and can therefore be acquired.
448  KY_EXPORT bool IsLockedByAnotherThread();
449 
450  // ** Waitable overrides
451  // A mutex is only signaled if it is not locked by ANYONE, so IsSignalled() will
452  // return 0 even if it is locked by US. This means that we cannot call Wait() on
453  // a mutex that is locked by us; it will never return. However, we can call Acquire() instead.
454  KY_EXPORT virtual bool IsSignaled() const;
455  KY_EXPORT virtual AcquireInterface* GetAcquireInterface();
456 
457  // ** Acquire Interface implementation
458  KY_EXPORT virtual bool CanAcquire();
459  KY_EXPORT virtual bool TryAcquire();
460  KY_EXPORT virtual bool TryAcquireCommit();
461  KY_EXPORT virtual bool TryAcquireCancel();
462 
463  // Locker class
464  // Used for automatic locking of a mutex
465  class Locker
466  {
467  public:
468  Mutex *pMutex;
469  Locker(Mutex *pmutex)
470  { pMutex = pmutex; pMutex->DoLock(); }
471  ~Locker()
472  { pMutex->Unlock(); }
473  };
474 };
475 
476 
477 
478 // ***** WaitCondition
479 
480 /*
481  WaitCondition is a synchronization primitive that can be used to implement what is known as a monitor.
482  Dependent threads wait on a wait condition by calling Wait(), and get woken up by other threads that
483  call Notify() or NotifyAll().
484 
485  The unique feature of this class is that it provides an atomic way of first releasing a Mutex, and then
486  starting a wait on a wait condition. If both the mutex and the wait condition are associated with the same
487  resource, this ensures that any condition checked for while the mutex was locked does not change before
488  the wait on the condition is actually initiated.
489 */
490 
491 class WaitConditionImpl;
492 
493 class WaitCondition
494 {
495  friend class WaitConditionImpl;
496  // Internal implementation structure
497  WaitConditionImpl *pImpl;
498 
499 public:
500  // Constructor/destructor
501  KY_EXPORT WaitCondition();
502  KY_EXPORT ~WaitCondition();
503 
504  // Release mutex and wait for condition. The mutex is re-aquired after the wait.
505  // Delay is specified in milliseconds (1/1000 of a second).
506  KY_EXPORT bool Wait(Mutex *pmutex, unsigned delay = KY_WAIT_INFINITE);
507 
508  // Notify a condition, releasing at one object waiting
509  KY_EXPORT void Notify();
510  // Notify a condition, releasing all objects waiting
511  KY_EXPORT void NotifyAll();
512 };
513 
514 
515 
516 // ***** Event
517 
518 class Event : public Waitable, public AcquireInterface
519 {
520  // Event state, its mutex and the wait condition
521  volatile bool State;
522  volatile bool Temporary;
523  mutable Mutex StateMutex;
524  WaitCondition StateWaitCondition;
525 
526 public:
527  // Constructor/destructor
528  KY_EXPORT Event(bool setInitially = 0, bool multiWait = 0);
529  KY_EXPORT ~Event();
530 
531  // Wait on an event condition until it is set
532  // Delay is specified in milliseconds (1/1000 of a second).
533  KY_EXPORT bool Wait(unsigned delay = KY_WAIT_INFINITE);
534 
535  // Set an event, releasing objects waiting on it
536  KY_EXPORT void SetEvent();
537  // Reset an event, un-signaling it
538  KY_EXPORT void ResetEvent();
539  // Set and then reset an event once a waiter is released.
540  // If threads are already waiting, they will be notified and released
541  // If threads are not waiting, the event is set until the first thread comes in
542  KY_EXPORT void PulseEvent();
543 
544  // Signaled override, an event is signaled once it is set
545  KY_EXPORT virtual bool IsSignaled() const;
546 
547  KY_EXPORT virtual AcquireInterface* GetAcquireInterface();
548 
549  // Acquire interface implementation
550  KY_EXPORT virtual bool CanAcquire();
551  KY_EXPORT virtual bool TryAcquire();
552  KY_EXPORT virtual bool TryAcquireCommit();
553  KY_EXPORT virtual bool TryAcquireCancel();
554 };
555 
556 
557 
558 // ***** Semaphore
559 
560 // The Semaphore class represents a Semaphore??a synchronization object
561 // that allows a limited number of threads in one or more processes to access
562 // a resource. A Semaphore object maintains a count of the number of
563 // threads currently accessing a specified resource. The Semaphore class is
564 // primarily used to serialize thread execution, similar to Mutex,
565 // however, unlike a mutex, a semaphore can be accessed by more than one thread
566 // at a time.
567 
568 class Semaphore : public Waitable, public AcquireInterface
569 {
570 protected:
571 
572  // Event state, its mutex and the wait condition
573  int MaxValue;
574  volatile int Value;
575  mutable Mutex ValueMutex;
576  WaitCondition ValueWaitCondition;
577 
578 public:
579  // Constructor/destructor
580  KY_EXPORT Semaphore(int maxValue = 1, bool multiWait = 0);
581  KY_EXPORT ~Semaphore();
582 
583 
584  // Get current value and max
585  int GetMaxValue() const;
586  int GetValue() const;
587  int GetAvailable() const;
588 
589 
590  // *** Actions
591 
592  // Obtains multiple value of a semaphore.
593  // Returns 0 if query failed (count > max value error or timeout)
594  // Delay is specified in milliseconds (1/1000 of a second).
595  KY_EXPORT bool ObtainSemaphore(int count = 1, unsigned delay = KY_WAIT_INFINITE);
596  // Release semaphore values
597  // Returns success code
598  KY_EXPORT bool ReleaseSemaphore(int count = 1);
599 
600 
601  // *** Operators
602 
603  // Postfix increment/decrement, return value before operation
604  KY_EXPORT int operator ++ (int);
605  KY_EXPORT int operator -- (int);
606  // Postfix increment/decrement, return value before operation
607  KY_EXPORT int operator += (int count);
608  KY_EXPORT int operator -= (int count);
609 
610 
611  // *** Waitable objects
612 
613  // Create a semaphore acquisition object that would increment a semaphore by a user-defined count
614  // This object can be passed to AcquireMultipleObjects functions,
615  // and will acquire several values form a semaphore
616  // This object must be released before the semaphore
617  KY_EXPORT Waitable* CreateWaitableIncrement(int count);
618 
619  // Acquire interface implementation
620  // Default
621  KY_EXPORT virtual bool CanAcquire();
622  KY_EXPORT virtual bool TryAcquire();
623  KY_EXPORT virtual bool TryAcquireCommit();
624  KY_EXPORT virtual bool TryAcquireCancel();
625 
626  // GWaitable implementation
627  KY_EXPORT virtual bool IsSignaled() const;
628  KY_EXPORT virtual AcquireInterface* GetAcquireInterface();
629 
630 
631  // Locker class, used for automatic acquisition of a semaphore
632  class Locker
633  {
634  public:
635  Semaphore* pSemaphore;
636  int Count;
637  Locker(Semaphore *psemaphore, int count = 1)
638  { pSemaphore = psemaphore; Count = count;
639  pSemaphore->ObtainSemaphore(count); }
640  ~Locker()
641  { pSemaphore->ReleaseSemaphore(Count); }
642  };
643 };
644 
645 
646 // ***** Thread class
647 
648 // ThreadId uniquely identifies a thread; returned by GetCurrentThreadId() and
649 // Thread::GetThreadId.
650 #if defined(KY_OS_PS3)
651 typedef sys_ppu_thread_t ThreadId;
652 #elif defined(KY_OS_PSVITA)
653 typedef SceUID ThreadId;
654 #elif defined(KY_OS_WINMETRO)
655 #if defined(KY_USE_STD11_THREADS)
656 typedef size_t ThreadId;
657 #else
658 typedef const concurrency::task_group* ThreadId;
659 #endif
660 #else
661 typedef void* ThreadId;
662 #endif
663 
664 
665 // *** Thread flags
666 
667 // Indicates that the thread is has been started, i.e. Start method has been called, and threads
668 // OnExit() method has not yet been called/returned.
669 #define KY_THREAD_STARTED 0x01
670 // This flag is set once the thread has ran, and finished.
671 #define KY_THREAD_FINISHED 0x02
672 // This flag is set temporarily if this thread was started suspended. It is used internally.
673 #define KY_THREAD_START_SUSPENDED 0x08
674 // This flag is used to ask a thread to exit. Message driven threads will usually check this flag
675 // and finish once it is set.
676 #define KY_THREAD_EXIT 0x10
677 
678 
679 class Thread : public Waitable, public AcquireInterface
680 { // NOTE: Waitable must be the first base since it implements RefCountImpl.
681 
682 public:
683 
684  // *** Callback functions, can be used instead of overriding Run
685 
686  // Run function prototypes.
687  // Thread function and user handle passed to it, executed by the default
688  // Thread::Run implementation if not null.
689  typedef int (*ThreadFn)(Thread *pthread, void* h);
690 
691  // Thread ThreadFunction1 is executed if not 0, otherwise ThreadFunction2 is tried
692  ThreadFn ThreadFunction;
693  // User handle passes to a thread
694  void* UserHandle;
695 
696  // Thread state to start a thread with
697  enum ThreadState
698  {
699  NotRunning = 0,
700  Running = 1,
701  Suspended = 2
702  };
703 
704  // Thread priority
705  enum ThreadPriority
706  {
707  CriticalPriority,
708  HighestPriority,
709  AboveNormalPriority,
710  NormalPriority,
711  BelowNormalPriority,
712  LowestPriority,
713  IdlePriority,
714  };
715 
716  // Thread constructor parameters
717  struct CreateParams
718  {
719  CreateParams(ThreadFn func = 0, void* hand = 0, UPInt ssize = 128 * 1024,
720  int proc = -1, ThreadState state = NotRunning, ThreadPriority prior = NormalPriority)
721  : threadFunction(func), userHandle(hand), stackSize(ssize),
722  processor(proc), initialState(state), priority(prior) {}
723  ThreadFn threadFunction; // Thread function
724  void* userHandle; // User handle passes to a thread
725  UPInt stackSize; // Thread stack size
726  int processor; // Thread hardware processor
727  ThreadState initialState; //
728  ThreadPriority priority; // Thread priority
729  };
730 
731  // *** Constructors
732 
733  // A default constructor always creates a thread in NotRunning state, because
734  // the derived class has not yet been initialized. The derived class can call Start explicitly.
735  // "processor" parameter specifies which hardware processor this thread will be run on.
736  // -1 means OS decides this. Implemented only from Win32 and XBox360
737  KY_EXPORT Thread(UPInt stackSize = 128 * 1024, int processor = -1);
738  // Constructors that initialize the thread with a pointer to function.
739  // An option to start a thread is available, but it should not be used if classes are derived from Thread.
740  // "processor" parameter specifies which hardware processor this thread will be run on.
741  // -1 means OS decides this. Implemented only from Win32 and XBox360
742  KY_EXPORT Thread(ThreadFn threadFunction, void* userHandle = 0, UPInt stackSize = 128 * 1024,
743  int processor = -1, ThreadState initialState = NotRunning);
744  // Constructors that initialize the thread with a create parameters structure.
745  explicit KY_EXPORT Thread(const CreateParams& params);
746 
747  // Destructor.
748  KY_EXPORT virtual ~Thread();
749 
750  // Waits for all Threads to finish; should be called only from the root
751  // application thread. Once this function returns, we know that all other
752  // thread's references to Thread object have been released.
753  KY_EXPORT static void KY_CDECL FinishAllThreads();
754 
755 
756  // *** Overridable Run function for thread processing
757 
758  // - returning from this method will end the execution of the thread
759  // - return value is usually 0 for success
760  KY_EXPORT virtual int Run();
761  // Called after return/exit function
762  KY_EXPORT virtual void OnExit();
763 
764 
765  // *** Thread management
766 
767  // Starts the thread if its not already running
768  // - internally sets up the threading and calls Run()
769  // - initial state can either be Running or Suspended, NotRunning will just fail and do nothing
770  // - returns the exit code
771  KY_EXPORT virtual bool Start(ThreadState initialState = Running);
772 
773  // Quits with an exit code
774  KY_EXPORT virtual void Exit(int exitCode=0);
775 
776  // Suspend the thread until resumed
777  // Returns 1 for success, 0 for failure.
778  KY_EXPORT bool Suspend();
779  // Resumes currently suspended thread
780  // Returns 1 for success, 0 for failure.
781  KY_EXPORT bool Resume();
782 
783  // Static function to return a pointer to the current thread
784  //SF_EXPORT static Thread* GetThread();
785 
786 
787  // *** Thread status query functions
788 
789  KY_EXPORT bool GetExitFlag() const;
790  KY_EXPORT void SetExitFlag(bool exitFlag);
791 
792  // Determines whether the thread was running and is now finished
793  KY_EXPORT bool IsFinished() const;
794  // Determines if the thread is currently suspended
795  KY_EXPORT bool IsSuspended() const;
796  // Returns current thread state
797  KY_EXPORT ThreadState GetThreadState() const;
798 
799  // Returns the number of available CPUs on the system
800  KY_EXPORT static int GetCPUCount();
801 
802  // Returns the thread exit code. Exit code is initialized to 0,
803  // and set to the return value if Run function after the thread is finished.
804  KY_INLINE int GetExitCode() const { return ExitCode; }
805  // Returns an OS handle
806 #if (defined(KY_OS_WIN32) || defined(KY_OS_XBOX) || defined(KY_OS_XBOX360)) && !defined(KY_OS_WINMETRO)
807  void* GetOSHandle() const { return ThreadHandle; }
808 #elif defined(KY_OS_WINMETRO)
809 #if defined(KY_USE_STD11_THREADS)
810  std::thread* GetOSHandle() const { return ThreadHandle; }
811 #else
812  ThreadId GetOSHandle() const { return &ThreadHandle; }
813 #endif
814 #elif defined(KY_OS_WII) || defined(KY_OS_WIIU)
815  OSThread * GetOSHandle() const { return ThreadData ? const_cast<OSThread*>(&ThreadData->ThreadHandle) : 0; }
816 #elif defined(KY_OS_PS3)
817  sys_ppu_thread_t GetOSHandle() const { return ThreadHandle; }
818 #elif defined(KY_OS_PSVITA)
819  SceUID GetOSHandle() const { return ThreadHandle; }
820 #elif defined(KY_OS_3DS)
821  nn::os::Thread* GetOSHandle() const { return ThreadHandle; }
822 #else
823  pthread_t GetOSHandle() const { return ThreadHandle; }
824 #endif
825 
826 #if (defined(KY_OS_WIN32) || defined(KY_OS_XBOX) || defined(KY_OS_XBOX360)) && !defined(KY_OS_WINMETRO)
827  ThreadId GetThreadId() const { return IdValue; }
828 #elif defined(KY_OS_WINMETRO)
829 #if defined(KY_USE_STD11_THREADS)
830  ThreadId GetThreadId() const { return IdValue != std::thread::id() ? IdValue.hash() : 0; }
831 #else
832  ThreadId GetThreadId() const { return (ThreadId)GetOSHandle(); }
833 #endif
834 #else
835  ThreadId GetThreadId() const { return (ThreadId)GetOSHandle(); }
836 #endif
837 
838  static int GetOSPriority(ThreadPriority);
839  // *** Sleep
840 
841  // Sleep secs seconds
842  KY_EXPORT static bool Sleep(unsigned secs);
843  // Sleep msecs milliseconds
844  KY_EXPORT static bool MSleep(unsigned msecs);
845 
846 
847  // *** Waitable interface implementation
848 
849  // A thread is signaled once it has finished. Waitable interface
850  // can be used to wait for a thread to finish.
851  virtual bool IsSignaled() const { return (ThreadFlags & KY_THREAD_FINISHED) != 0; }
852 
853  // A thread can be acquired if it has finished.
854  // However, the acquisition of a thread does not require any release logic.
855  virtual AcquireInterface* GetAcquireInterface() { return this; }
856 
857  // *** Acquire interface implementation
858  virtual bool CanAcquire() { return IsSignaled(); }
859  virtual bool TryAcquire() { return IsSignaled(); }
860  // Default implementation (that just succeeds) is fine here
861  //SF_EXPORT virtual bool TryAcquireCommit();
862  //SF_EXPORT virtual bool TryAcquireCancel();
863 
864  // *** Debugging functionality
865 #if (defined(KY_OS_WIN32) || defined(KY_OS_XBOX360)) && !defined(KY_OS_WINMETRO)
866  virtual void SetThreadName( const char* name );
867 #else
868  virtual void SetThreadName( const char* name ) { KY_UNUSED(name); }
869 #endif
870 
871 private:
872 #if (defined(KY_OS_WIN32) || defined(KY_OS_XBOX) || defined(KY_OS_XBOX360)) && ! defined(KY_OS_WINMETRO)
873  friend unsigned WINAPI Thread_Win32StartFn(void *pthread);
874 
875 #elif defined(KY_OS_WINMETRO)
876 #if defined(KY_USE_STD11_THREADS)
877  friend void Thread_Std11StartFunc(void *phandle);
878 #else
879  friend void WINAPIV Thread_WinRTStartFn(void *pthread);
880 #endif
881 #elif defined(KY_OS_WII)
882  friend void *Thread_PthreadStartFn(void * phandle);
883  friend class ThreadList;
884 
885 #elif defined(KY_OS_WIIU)
886  friend int Thread_PthreadStartFn(int, void * phandle);
887  friend class ThreadList;
888 
889 #elif defined(KY_OS_3DS)
890  friend void Thread_PthreadStartFn(void * phandle);
891 
892 #elif defined(KY_OS_PS3)
893  friend void Thread_PpuThreadStartFn(uint64_t phandle);
894 
895 #elif defined(KY_OS_PSVITA)
896  friend int Thread_Psp2ThreadStartFn(SceSize size, void* phandle);
897 
898 #else
899  friend void *Thread_PthreadStartFn(void * phandle);
900 
901  static int InitAttr;
902  static pthread_attr_t Attr;
903 #endif
904 
905 protected:
906  // Thread state flags
907  AtomicInt<UInt32> ThreadFlags;
908  AtomicInt<SInt32> SuspendCount;
909  UPInt StackSize;
910 
911  // Hardware processor which this thread is running on.
912  int Processor;
913  ThreadPriority Priority;
914 
915 #if (defined(KY_OS_WIN32) || defined(KY_OS_XBOX) || defined(KY_OS_XBOX360)) && !defined(KY_OS_WINMETRO)
916  void* ThreadHandle;
917  volatile ThreadId IdValue;
918 
919  // System-specific cleanup function called from destructor
920  void CleanupSystemThread();
921 
922 #elif defined(KY_OS_WINMETRO)
923 #if defined(KY_USE_STD11_THREADS)
924  std::thread* ThreadHandle;
925  std::thread::id IdValue;
926 #else
927  concurrency::task_group ThreadHandle;
928 #endif
929 
930 #elif defined(KY_OS_WII) || defined(KY_OS_WIIU)
931 public: // for Wii compiler 4.3 145
932  struct ThreadDataWii : public ListNode<ThreadDataWii>
933  {
934  OSThread ThreadHandle;
935  jmp_buf ExitJmp;
936  UByte Stack[32] __attribute__((aligned(32)));
937  };
938 protected:
939  ThreadDataWii* ThreadData;
940 #elif defined(KY_OS_3DS)
941  jmp_buf ExitJmp;
942  nn::os::Thread* ThreadHandle;
943 #elif defined(KY_OS_PS3)
944  sys_ppu_thread_t ThreadHandle;
945 #elif defined(KY_OS_PSVITA)
946  SceUID ThreadHandle;
947 #else
948  pthread_t ThreadHandle;
949 #endif
950 
951  // Exit code of the thread, as returned by Run.
952  int ExitCode;
953 
954  // Internal run function.
955  int PRun();
956  // Finishes the thread and releases internal reference to it.
957  void FinishAndRelease();
958 
959  void Init(const CreateParams& params);
960 
961  // Protected copy constructor
962  Thread(const Thread &source) : Waitable(1) { KY_UNUSED(source); }
963 
964 
965 };
966 
967 // Returns the unique Id of a thread it is called on, intended for
968 // comparison purposes.
969 ThreadId GetCurrentThreadId();
970 
971 
972 
973 #endif // KY_ENABLE_THREADS
974 
975 } // Scaleform
976 
977 #endif // INC_KY_Kernel_Threads_H
Definition: gamekitcrowddispersion.h:20