eathread_thread.h 33 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795
  1. ///////////////////////////////////////////////////////////////////////////////
  2. // Copyright (c) Electronic Arts Inc. All rights reserved.
  3. ///////////////////////////////////////////////////////////////////////////////
  4. #ifndef EATHREAD_EATHREAD_THREAD_H
  5. #define EATHREAD_EATHREAD_THREAD_H
  6. #include <eathread/eathread.h>
  7. #include <eathread/eathread_semaphore.h>
  8. #include <eathread/eathread_atomic.h>
  9. EA_DISABLE_ALL_VC_WARNINGS()
  10. #include <stddef.h>
  11. #include <stdlib.h>
  12. #include <type_traits>
  13. EA_RESTORE_ALL_VC_WARNINGS()
  14. #if defined(EA_PRAGMA_ONCE_SUPPORTED)
  15. #pragma once // Some compilers (e.g. VC++) benefit significantly from using this. We've measured 3-4% build speed improvements in apps as a result.
  16. #endif
  17. #if defined(EA_DLL) && defined(EA_COMPILER_MSVC)
  18. // Suppress warning about class 'AtomicInt32' needs to have a
  19. // dll-interface to be used by clients of class which have a templated member.
  20. //
  21. // These templates cannot be instantiated outside of the DLL. If you try, a
  22. // link error will result. This compiler warning is intended to notify users
  23. // of this.
  24. EA_DISABLE_VC_WARNING(4251)
  25. #endif
  26. /////////////////////////////////////////////////////////////////////////
  27. /// ThreadData
  28. ///
  29. /// This is used internally by class Thread.
  30. /// To consider: Move this declaration into a platform-specific
  31. /// header file.
  32. /////////////////////////////////////////////////////////////////////////
  33. #if !EA_THREADS_AVAILABLE
  34. struct EAThreadDynamicData
  35. {
  36. };
  37. struct EAThreadData
  38. {
  39. EAThreadDynamicData* mpData;
  40. };
  41. #elif EA_USE_CPP11_CONCURRENCY
  42. #include <eathread/eathread_mutex.h>
  43. #include <eathread/eathread_semaphore.h>
  44. EA_DISABLE_VC_WARNING(4062 4265 4365 4836 4571 4625 4626 4628 4193 4127 4548 4350)
  45. #if EA_PLATFORM_WINDOWS
  46. #include <ctxtcall.h> // workaround for compile errors in winrt. see http://connect.microsoft.com/VisualStudio/feedback/details/730564/ppl-in-winrt-projects-fail-to-compile
  47. #endif
  48. #include <future>
  49. #include <mutex>
  50. struct EAThreadDynamicData
  51. {
  52. typedef void (*ThreadFunc)(EAThreadDynamicData* tdd, void* userFunc, void* userContext, void* userWrapperFunc);
  53. EAThreadDynamicData(EA::Thread::ThreadUniqueId uniqueThreadId, const char* pThreadName);
  54. EAThreadDynamicData(void* userFunc, void* userContext, void* userWrapperFunc, ThreadFunc threadFunc);
  55. ~EAThreadDynamicData();
  56. void AddRef();
  57. void Release();
  58. EA::Thread::AtomicInt32 mnRefCount;
  59. EA::Thread::AtomicInt32 mStatus;
  60. intptr_t mReturnValue;
  61. char mName[EATHREAD_NAME_SIZE];
  62. void* mpStackBase;
  63. EA::Thread::ThreadAffinityMask mnThreadAffinityMask;
  64. EA::Thread::ThreadUniqueId mUniqueThreadId;
  65. struct EAThreadComposite
  66. {
  67. EAThreadComposite()
  68. : mReturnPromise()
  69. , mReturnFuture(mReturnPromise.get_future())
  70. , mGetStatusFuture(mReturnFuture)
  71. {
  72. }
  73. std::promise<intptr_t> mReturnPromise;
  74. std::shared_future<intptr_t> mReturnFuture;
  75. std::shared_future<intptr_t> mGetStatusFuture;
  76. std::thread mThread;
  77. } *mpComp;
  78. private:
  79. // Disable copy and assignment
  80. EAThreadDynamicData(const EAThreadDynamicData&);
  81. EAThreadDynamicData operator=(const EAThreadDynamicData&);
  82. };
  83. struct EAThreadData
  84. {
  85. EAThreadDynamicData* mpData;
  86. };
  87. EA_RESTORE_VC_WARNING()
  88. // TODO: collapse the defines.
  89. #elif defined(EA_PLATFORM_SONY)
  90. #include <eathread/eathread_mutex.h>
  91. #include <eathread/eathread_semaphore.h>
  92. #include <kernel.h>
  93. #include <scebase.h>
  94. // Internal queue wrapper which is used to allow for a higher resolution sleep than what is provided by Sony's sleep functions
  95. // as despite the names, sceKernelSleep, sceKernelUSleep and sceKernelNanosleep are all 1 ms resolution whereas this timer is 100 microseconds
  96. struct EAThreadTimerQueue
  97. {
  98. EAThreadTimerQueue()
  99. {
  100. int result = sceKernelCreateEqueue(&mTimerEventQueue, "EAThread Timer Queue");
  101. mbEnabled = result == SCE_OK;
  102. // A timer queue will fail to be created when there are too many kernel objects open. It is a valid
  103. // use-case for the Event Queue to fail being created as the ThreadSleep function implements a fallback.
  104. //
  105. // EAT_ASSERT_FORMATTED(mbEnabled, "Failed to initialize the EAThread Timer Queue (0x%x)", result);
  106. }
  107. ~EAThreadTimerQueue()
  108. {
  109. if(mbEnabled) // only destroy the queue if it was created.
  110. sceKernelDeleteEqueue(mTimerEventQueue);
  111. mbEnabled = false;
  112. }
  113. SceKernelEqueue mTimerEventQueue;
  114. EA::Thread::AtomicUint32 mCurrentId = 0;
  115. bool mbEnabled = false;
  116. };
  117. struct EAThreadDynamicData
  118. {
  119. EAThreadDynamicData();
  120. ~EAThreadDynamicData();
  121. void AddRef();
  122. void Release();
  123. EA::Thread::ThreadId mThreadId;
  124. EA::Thread::SysThreadId mSysThreadId;
  125. pid_t mThreadPid; // For Linux this is the thread ID from gettid(). Otherwise it's the getpid() value.
  126. volatile int mnStatus;
  127. intptr_t mnReturnValue;
  128. void* mpStartContext[2];
  129. void* mpBeginThreadUserWrapper; // User-specified BeginThread function wrapper or class wrapper
  130. void* mpStackBase;
  131. EA::Thread::AtomicInt32 mnRefCount;
  132. char mName[EATHREAD_NAME_SIZE];
  133. int mStartupProcessor; // The thread affinity for the thread to set itself to after it starts. We need to do this because we currently have no way to set the affinity of another thread until after it has started.
  134. EA::Thread::Mutex mRunMutex; // Locked while the thread is running. The reason for this mutex is that it allows timeouts to be specified in the WaitForEnd function.
  135. EA::Thread::Semaphore mStartedSemaphore; // Signaled when the thread starts. This allows us to know in a thread-safe way when the thread has actually started executing.
  136. EA::Thread::ThreadAffinityMask mnThreadAffinityMask;
  137. EAThreadTimerQueue mThreadTimerQueue; // This queue allows for high resolution timer events to be submitted per thread allowing for better sleep resolution than Sony's provided sleep functions
  138. };
  139. struct EAThreadData{
  140. EAThreadDynamicData* mpData;
  141. };
  142. #elif defined(EA_PLATFORM_UNIX) || EA_POSIX_THREADS_AVAILABLE
  143. #include <pthread.h>
  144. #include <eathread/eathread_mutex.h>
  145. #include <eathread/eathread_semaphore.h>
  146. struct EAThreadDynamicData
  147. {
  148. EAThreadDynamicData();
  149. ~EAThreadDynamicData();
  150. void AddRef();
  151. void Release();
  152. EA::Thread::ThreadId mThreadId;
  153. EA::Thread::SysThreadId mSysThreadId;
  154. pid_t mThreadPid; // For Linux this is the thread ID from gettid(). Otherwise it's the getpid() value.
  155. volatile int mnStatus;
  156. intptr_t mnReturnValue;
  157. void* mpStartContext[2];
  158. void* mpBeginThreadUserWrapper; // User-specified BeginThread function wrapper or class wrapper
  159. void* mpStackBase;
  160. EA::Thread::AtomicInt32 mnRefCount;
  161. char mName[EATHREAD_NAME_SIZE];
  162. int mStartupProcessor; // DEPRECATED: The thread affinity for the thread to set itself to after it starts. We need to do this because we currently have no way to set the affinity of another thread until after it has started.
  163. EA::Thread::ThreadAffinityMask mnThreadAffinityMask; // mStartupProcessor is deprecated in favor of using the the mnThreadAffinityMask and doesn't suffer from the limitations of only specifying the value at thread startup time.
  164. EA::Thread::Mutex mRunMutex; // Locked while the thread is running. The reason for this mutex is that it allows timeouts to be specified in the WaitForEnd function.
  165. EA::Thread::Semaphore mStartedSemaphore; // Signaled when the thread starts. This allows us to know in a thread-safe way when the thread has actually started executing.
  166. };
  167. struct EAThreadData
  168. {
  169. EAThreadDynamicData* mpData;
  170. };
  171. #elif defined(EA_PLATFORM_MICROSOFT) && !EA_POSIX_THREADS_AVAILABLE
  172. struct EAThreadDynamicData
  173. {
  174. EAThreadDynamicData();
  175. ~EAThreadDynamicData();
  176. void AddRef();
  177. void Release();
  178. EA::Thread::ThreadId mhThread;
  179. unsigned int mnThreadId; // EA::Thread::SysThreadId
  180. int mnStatus;
  181. EA::Thread::ThreadAffinityMask mnThreadAffinityMask;
  182. intptr_t mnReturnValue;
  183. void* mpStartContext[3];
  184. void* mpBeginThreadUserWrapper; // User-specified BeginThread function wrapper or class wrapper
  185. void* mpStackBase;
  186. EA::Thread::AtomicInt32 mnRefCount;
  187. char mName[EATHREAD_NAME_SIZE];
  188. };
  189. struct EAThreadData
  190. {
  191. EAThreadDynamicData* mpData;
  192. };
  193. #endif
  194. namespace EA
  195. {
  196. namespace Thread
  197. {
  198. struct EATHREADLIB_API ThreadEnumData
  199. {
  200. ThreadEnumData();
  201. ~ThreadEnumData();
  202. EAThreadDynamicData* mpThreadDynamicData;
  203. void Release();
  204. };
  205. }
  206. }
  207. /////////////////////////////////////////////////////////////////////////
  208. namespace EA
  209. {
  210. namespace Thread
  211. {
  212. /// FindThreadDynamicData
  213. /// Utility functionality, not needed for most uses.
  214. EATHREADLIB_API EAThreadDynamicData* FindThreadDynamicData(ThreadId threadId);
  215. EATHREADLIB_API EAThreadDynamicData* FindThreadDynamicData(SysThreadId threadId);
  216. /// EnumerateThreads
  217. /// Enumerates known threads. For some platforms the returned thread list is limited
  218. /// to the main thread and threads created by EAThread.
  219. /// Returns the required count to enumerate all threads.
  220. /// Fills in thread data up till the supplied capacity.
  221. ///
  222. /// Example usage:
  223. /// ThreadEnumData enumData[32];
  224. /// size_t count = EA::Thread::EnumerateThreads(enumData, EAArrayCount(enumData));
  225. ///
  226. /// for(size_t i = 0; i < count; i++)
  227. /// {
  228. /// printf("Thread id: %s\n", EAThreadIdToString(enumData[i].mpThreadDynamicData->mThreadId));
  229. /// enumData[i].Release();
  230. /// }
  231. size_t EATHREADLIB_API EnumerateThreads(ThreadEnumData* pDataArray, size_t dataArrayCapacity);
  232. /// RunnableFunction
  233. /// Defines the prototype of a standalone thread function.
  234. /// The return value is of type intptr_t, which is a standard integral
  235. /// data type that is large enough to hold an int or void*.
  236. typedef intptr_t (*RunnableFunction)(void* pContext);
  237. /// IRunnable
  238. /// Defines a class whose Run function executes in a separate thread.
  239. /// An implementation of this interface can be run using a Thread class instance.
  240. struct EATHREADLIB_API IRunnable
  241. {
  242. virtual ~IRunnable() { }
  243. /// \brief Task run entry point
  244. /// The thread terminates when this method returns.
  245. /// The return value is of type intptr_t, which is a standard integral
  246. /// data type that is large enough to hold an int or void*.
  247. virtual intptr_t Run(void* pContext = NULL) = 0;
  248. };
  249. /// RunnableFunctionUserWrapper
  250. /// Defines the prototype of a user callback function when thread function is started.
  251. /// \param pContext: thread start context void* passed in from thread Thread::Begin()
  252. /// \param defaultRunnableFunction: default function Thread::Begin() normally would
  253. /// call, user must call this function with passed in pContext.
  254. ///
  255. /// Here's an example:
  256. /// \code
  257. /// int ThreadFunction(void*)
  258. /// {
  259. /// printf("Throw NULL pointer Exception.\n");
  260. /// char* pTest = NULL;
  261. /// *pTest = 1;
  262. /// return 0;
  263. /// }
  264. ///
  265. /// intptr_t MyThreadBeginWrapper(RunnableFunction defaultRunnableFunction, void* pContext)
  266. /// {
  267. /// // Do pre-start thread function stuff
  268. /// try {
  269. /// // must call defaultRunnableFunction to execute thread function, if don't then
  270. /// // thread function will never gets executed.
  271. /// intptr_t retValue = defaultRunnableFunction(pContext);
  272. /// }
  273. /// catch(...) {
  274. /// printf("Exception detected.\n");
  275. /// }
  276. ///
  277. /// // do post-start thread function stuff
  278. /// return retValue;
  279. /// }
  280. /// \endcode
  281. ///
  282. /// In your thread begin() function:
  283. /// \code
  284. /// ...
  285. /// threadIds = threads.Begin(ThreadFunction, NULL, NULL, MyThreadBeginWrapper);
  286. /// ...
  287. /// \endcode
  288. typedef intptr_t (*RunnableFunctionUserWrapper)(RunnableFunction defaultRunnableFunction, void* pContext);
  289. /// RunnableClassUserWrapper
  290. /// Defines the prototype of a user callback function when thread function is started.
  291. /// \param pContext: thread start context void* passed in from thread Thread::Begin()
  292. /// \param defaultRunnableFunction: default function Thread::Begin() normally would
  293. /// call, user must call this function with passed in pContext.
  294. ///
  295. /// Here's an example:
  296. /// \code
  297. /// class MyThreadClass
  298. /// {
  299. /// virtual intptr_t Run(void* pContext = NULL)
  300. /// {
  301. /// printf("Throw NULL pointer Exception.\n");
  302. /// char* pTest = NULL;
  303. /// *pTest = 1;
  304. /// return 0;
  305. /// }
  306. /// }
  307. ///
  308. /// intptr_t MyThreadBeginWrapper(IRunnable defaultRunnableFunction, void* pContext)
  309. /// {
  310. /// // do pre-start thread function stuff
  311. ///
  312. /// // a good example is try catch block
  313. /// try
  314. /// {
  315. /// // must call defaultRunnableFunction to execute thread function, if don't then
  316. /// // thread function will never gets executed.
  317. /// intptr_t retValue = defaultRunnableFunction->Run(pContext);
  318. /// }
  319. /// catch(...)
  320. /// {
  321. /// printf("Exception detected.\n");
  322. /// }
  323. ///
  324. /// // do post-start thread function stuff
  325. /// return retValue;
  326. /// }
  327. /// \endcode
  328. ///
  329. /// In your thread begin() function:
  330. ///
  331. /// \code
  332. /// ...
  333. /// MyThreadClass myThreadClass = new MyThreadClass();
  334. /// threadIds = threads.Begin(&myThreadClass, NULL, NULL, MyThreadBeginWrapper);
  335. /// ...
  336. /// \endcode
  337. typedef intptr_t (*RunnableClassUserWrapper)(IRunnable* defaultRunnableClass, void* pContext);
  338. /// ThreadParameters
  339. /// Used for specifying thread starting parameters. Note that we do not
  340. /// include a 'start paused' parameter. The reason for this is that such
  341. /// a thing is not portable and other mechanisms can achieve the same
  342. /// effect. Thread pause/resume in general is considered bad practice.
  343. struct EATHREADLIB_API ThreadParameters
  344. {
  345. void* mpStack; /// Pointer to stack memory. This would be the low address of the memory. A NULL value means to create a default stack. Default is NULL. Note that some platforms (such as Windows) don't support a user-supplied stack.
  346. size_t mnStackSize; /// Size of the stack memory. Default is variable, depending on the platform.
  347. int mnPriority; /// Value in the range of [kThreadPriorityMin, kThreadPriorityMax]. Default is kThreadPriorityDefault.
  348. int mnProcessor; /// 0-based index of which processor to run the thread on. A value of -1 means to use default. Default is -1. See SetThreadProcessor for caveats regarding this value.
  349. const char* mpName; /// A name to give to the thread. Useful for identifying threads in a descriptive way.
  350. EA::Thread::ThreadAffinityMask mnAffinityMask; /// A bitmask representing the cores that the thread is allowed to run on. NOTE: This affinity mask is only applied when mnProcessor is set to kProcessorAny.
  351. bool mbDisablePriorityBoost; /// Whether the system should override the default behavior of boosting the thread priority as they come out of a wait state (currently only supported on Windows).
  352. ThreadParameters();
  353. };
  354. /// Thread
  355. ///
  356. /// Note that we do not provide thread suspend and resume functions.
  357. /// The reason for this is that such things are inherently unsafe as
  358. /// you usually cannot know where the thread is executing when the
  359. /// suspension occurs. The safe alternative is to use signal or
  360. /// semaphore primitives to achieve the same thing in a safe way.
  361. ///
  362. /// For performance reasons, the thread creation functions of this
  363. /// class are themselves not thread-safe. Thus if you want to call
  364. /// the Begin functions for an instance of this class from multiple
  365. /// threads, you will need to synchronize access to the begin
  366. /// functions yourself.
  367. class EATHREADLIB_API Thread
  368. {
  369. public:
  370. enum Status
  371. {
  372. kStatusNone, /// The thread has neither started nor ended.
  373. kStatusRunning, /// The thread has started but not ended.
  374. kStatusEnded /// The thread has both started and ended.
  375. };
  376. /// Thread
  377. /// \brief Thread constructor.
  378. Thread();
  379. /// Thread
  380. /// \brief Thread copy constructor.
  381. Thread(const Thread& t);
  382. /// Thread
  383. /// \brief Thread destructor. The destructor does not take any
  384. /// action on the thread associated with it. Any threads created
  385. /// by this class will continue to run and exit normally after
  386. /// this destructor has executed.
  387. ~Thread();
  388. /// operator=
  389. /// \brief Thread assignment operator.
  390. Thread& operator=(const Thread& t);
  391. /// \brief Return global RunnableFunctionUserWrapper set by user.
  392. /// \return function pointer to RunnableFunctionUserWrapper function user
  393. /// set, if NULL, nothing is set.
  394. /// \sa RunnableFunctionUserWrapper
  395. static RunnableFunctionUserWrapper GetGlobalRunnableFunctionUserWrapper();
  396. /// \brief Set global RunnableFunctionUserWrapper. This can only be
  397. /// set once in the application life time.
  398. /// \param pUserWrapper user specified wrapper function pointer.
  399. /// \sa RunnableFunctionUserWrapper
  400. static void SetGlobalRunnableFunctionUserWrapper(RunnableFunctionUserWrapper pUserWrapper);
  401. /// \brief Return global RunnableClassUserWrapper set by user.
  402. /// \return function pointer to RunnableClassUserWrapper function user
  403. /// set, if NULL, nothing is set.
  404. /// \sa RunnableClassUserWrapper
  405. static RunnableClassUserWrapper GetGlobalRunnableClassUserWrapper();
  406. /// \brief Set global RunnableClassUserWrapper. This can only be
  407. /// set once in the application life time.
  408. /// \sa RunnableClassUserWrapper
  409. static void SetGlobalRunnableClassUserWrapper(RunnableClassUserWrapper pUserWrapper);
  410. /// Begin
  411. /// \brief Starts a thread via a RunnableFunction.
  412. /// Returns the thread id of the newly running thread.
  413. /// The pContext argument is passed to the RunnableFunction and serves
  414. /// to allow the caller to pass information to the thread.
  415. /// The pThreadParameters argument allows the caller to specify additional
  416. /// information about how to start the thread. If this parameter is NULL,
  417. /// then default settings will be chosen.
  418. /// The Begin function itself is not thread-safe. While this Thread class
  419. /// can be used to Begin multiple threads, the Begin function itself cannot
  420. /// safely be executed by multiple threads at a time. This is by design and
  421. /// allows for a simpler more efficient library.
  422. /// User can have their own RunnableFunction wrapper by specifying one in
  423. /// pUserWrapper. When pUserWrapper is used, pUserWrapper will get called
  424. /// first, then pUserWrapper function can do whatever is desired before the
  425. /// just-created thread's entry point is called.
  426. /// \sa RunnableFunctionUserWrapper
  427. ThreadId Begin(RunnableFunction pFunction, void* pContext = NULL, const ThreadParameters* pThreadParameters = NULL, RunnableFunctionUserWrapper pUserWrapper = GetGlobalRunnableFunctionUserWrapper());
  428. /// Begin
  429. /// Starts a thread via an object of the IRunnable interface.
  430. /// Returns the thread id of the newly running thread.
  431. /// The pContext argument is passed to the RunnableFunction and serves
  432. /// to allow the caller to pass information to the thread.
  433. /// The pThreadParameters argument allows the caller to specify additional
  434. /// information about how to start the thread. If this parameter is NULL,
  435. /// then default settings will be chosen.
  436. /// The Begin function itself is not thread-safe. While this Thread class
  437. /// can be used to Begin multiple threads, the Begin function itself cannot
  438. /// safely be executed by multiple threads at a time. This is by design and
  439. /// allows for a simpler more efficient library.
  440. /// User can have their own RunnableClass wrapper by specifying one pUserWrapper.
  441. /// When pUserWrapper is used, pUserWrapper will get called first, then
  442. /// pUserWrapper function can do whatever is desired before the just-created
  443. /// thread's entry point is called.
  444. /// \sa RunnableClassUserWrapper
  445. ThreadId Begin(IRunnable* pRunnable, void* pContext = NULL, const ThreadParameters* pThreadParameters = NULL, RunnableClassUserWrapper pUserWrapper = GetGlobalRunnableClassUserWrapper());
  446. /// WaitForEnd
  447. /// Waits for the thread associated with an object of this class
  448. /// to end. Returns one of enum Status to indicate the status upon
  449. /// return of this call.
  450. /// This function is similar to the Posix pthread_join function and
  451. /// the Windows WaitForSingleObject function.
  452. /// If input pThreadReturnValue is non-NULL, it will be filled in with
  453. /// the return value of the thread.
  454. /// This function must be called only by a single thread at a time.
  455. /// The resulting behaviour is undefined if multiple threads call this function.
  456. ///
  457. /// Note that the timeout is specified in absolute time and not relative time.
  458. ///
  459. /// Note also that due to the way thread scheduling works -- particularly in a
  460. /// time-sliced threading environment -- that the timeout value is a hint and
  461. /// the actual amount of time passed before the timeout occurs may be significantly
  462. /// more or less than the specified timeout time.
  463. ///
  464. Status WaitForEnd(const ThreadTime& timeoutAbsolute = kTimeoutNone, intptr_t* pThreadReturnValue = NULL);
  465. /// GetStatus
  466. /// Returns one of enum GetStatus. Note that in the most general sense
  467. /// the running status may change if the thread quit right after
  468. /// this call was made. But this function is useful if you know that
  469. /// a function was running and you want to poll for its status while
  470. /// waiting for it to exit.
  471. /// If input pThreadReturnValue is non-NULL, it will be filled in with
  472. /// the return value of the thread if the Status is kStatusEnded.
  473. /// If the Status is not kStatusEnded, pThreadReturnValue will be ignored.
  474. Status GetStatus(intptr_t* pThreadReturnValue = NULL) const;
  475. /// GetId
  476. /// Gets the Id of the thread associated with an object of this class.
  477. /// This Id is unique throughout the system. This function returns a
  478. /// value that under Posix threads would be synonymous with pthread_t
  479. /// and under Windows would be synonymous with a thread HANDLE (and not
  480. /// a Windows thread id).
  481. ThreadId GetId() const;
  482. /// GetPriority
  483. /// Gets the priority of the thread. Return kThreadPriorityUnknown if
  484. /// the thread associated with this class isn't running. If a thread
  485. /// wants to get its own priority, it can use this class member or it
  486. /// can simply use the global SetThreadPriority function and not need
  487. /// an instance of this class. If you want to manipulate the thread
  488. /// priority via the native platform interface, you can use GetId to
  489. /// get the platform-specific identifier and use that value with native APIs.
  490. ///
  491. /// This function can return any int except for kThreadPriorityUnknown, as the
  492. /// current thread's priority will always be knowable. A return value of kThreadPriorityDefault
  493. /// means that this thread is of normal (a.k.a. default) priority.
  494. /// See the documentation for thread priority constants (e.g. kThreadPriorityDefault)
  495. /// for more information about thread priority values and behaviour.
  496. int GetPriority() const;
  497. /// SetPriority
  498. /// Sets the priority of the thread. Returns false if the thread associated
  499. /// with this class isn't running. If a thread wants to set its own priority,
  500. /// it can use this class member or it can simply use the global SetThreadPriority
  501. /// function and not need an instance of this class. If you want to manipulate
  502. /// the thread priority via the native platform interface, you can use GetId to
  503. /// get the platform-specific identifier and use that value with native APIs.
  504. ///
  505. /// Accepts any integer priority value except kThreadPriorityUnknown.
  506. /// On some platforms, this function will automatically convert any invalid
  507. /// priority for that particular platform to a valid one. A normal (a.k.a. default) thread
  508. /// priority is identified by kThreadPriorityDefault.
  509. ///
  510. /// You can set the priority of a Thread object only if it has already begun.
  511. /// You can also set the priority with the Begin function via the ThreadParameters
  512. /// argument to Begin. This design is so in order to simply the implementation,
  513. /// but being able to set ThreadParameters before Begin is something that can
  514. /// be considered in the future.
  515. bool SetPriority(int priority);
  516. /// SetProcessor
  517. /// Sets the processor the given thread should run on. Valid values
  518. /// are kThreadProcessorDefault, kThreadProcessorAny, or a processor
  519. /// index in the range of [0, processor count). If the input value
  520. /// is >= the processor count, it will be reduced to be a modulo of
  521. /// the processor count. Any other invalid value will cause the processor
  522. /// to be set to zero.
  523. ///
  524. /// For some platforms you can set the processor of a Thread object only if it
  525. /// has already begun.
  526. ///
  527. /// You can also set the processor with the Begin function via the ThreadParameters
  528. /// argument to Begin. This design is so in order to simply the implementation,
  529. /// but being able to set ThreadParameters before Begin is something that can
  530. /// be considered in the future. This is the most reliable way to set the thread
  531. /// processor, as it works on all platforms.
  532. void SetProcessor(int nProcessor);
  533. /// Wake
  534. /// Wakes up a sleeping thread if it is sleeping. This necessarily can only
  535. /// be called from a thread other than the sleeping thread. You must be careful
  536. /// to not rely on this function as a synchronization primitive. For example,
  537. /// in the general case you cannot be sure that after calling Wake that the
  538. /// thread will be awake, as it is possible that right after you called Wake
  539. /// the thread immediately went back to sleep before you could do anything.
  540. /// Nevertheless, this function is useful in waking up a thread from a
  541. /// (potentially long) sleep so that it can examine data, lock a synchronization
  542. /// primitive, or simply exit.
  543. ///
  544. /// Note that this class has no member Sleep function. The reason is that a
  545. /// thread can only put itself to sleep and cannot put other threads to sleep.
  546. /// The thread should use the static Sleep function to put itself to sleep.
  547. void Wake();
  548. /// GetName
  549. /// Returns the name of the thread assigned by the SetName function.
  550. /// If the thread was not named by the SetName function, then the name is empty ("").
  551. const char* GetName() const;
  552. /// SetName
  553. /// Sets a descriptive name or the thread. On some platforms this name is passed
  554. /// on to the debugging tools so they can see this name. The name length, including
  555. /// a terminating 0 char, is limited to EATHREAD_NAME_SIZE characters. Any characters
  556. /// beyond that are ignored.
  557. ///
  558. /// You can set the name of a Thread object only if it has already begun.
  559. /// You can also set the name with the Begin function via the ThreadParameters
  560. /// argument to Begin. This design is so in order to simply the implementation,
  561. /// but being able to set ThreadParameters before Begin is something that can
  562. /// be considered in the future.
  563. ///
  564. /// Some platforms (e.g. Linux) have the restriction this function works propertly only
  565. /// when called by the same thread that you want to name. Given this situation,
  566. /// the most portable way to use this SetName function is to either always call
  567. /// it from the thread to be named or to use the ThreadParameters to give the
  568. /// thread a name before it is started and let the started thread name itself.
  569. void SetName(const char* pName);
  570. /// SetAffinityMask
  571. /// Sets an affinity mask for the thread. On some platforms, this OS feature is
  572. /// not supported. In this situation, you are at the mercy of the OS thread scheduler.
  573. ///
  574. /// Example(s):
  575. /// "00000100" -> thread is pinned to processor 2
  576. /// "01010100" -> thread is pinned to processor 2, 4, and 6.
  577. void SetAffinityMask(ThreadAffinityMask mnAffinityMask);
  578. /// GetAffinityMask
  579. /// Returns the affinity mask for this specific thread.
  580. ThreadAffinityMask GetAffinityMask();
  581. /// SetDefaultProcessor
  582. /// Sets the default processor to create threads with. To specify the processor
  583. /// for a running thread, use SetProcessor() or specify the processor in the
  584. /// thread creation ThreadParameters.
  585. ///
  586. /// If nProcessor is set to kProcessorAny, EAThread will automatically determine
  587. /// which processor to launch threads to.
  588. ///
  589. /// Please refer to SetProcessor for valid values for the nProcessor argument.
  590. static void SetDefaultProcessor(int nProcessor)
  591. { sDefaultProcessor = nProcessor; }
  592. /// GetDefaultProcessor
  593. /// Gets the default processor to create threads with.
  594. static int GetDefaultProcessor()
  595. { return sDefaultProcessor; }
  596. /// SetDefaultProcessorMask
  597. /// Sets which processors created threads should be explicitly run on.
  598. /// The default value is 0xffffffffffffffff.
  599. /// Each bit refers to the associated processor. A mask of 0xffffffffffffffff
  600. /// means to allow running on any processor, and on desktop platforms such
  601. /// as Windows it means that the OS decides what processor to use on its own.
  602. /// Not all platforms support this functionality, even if multiple processors are present.
  603. static void SetDefaultProcessorMask(uint64_t mask)
  604. { sDefaultProcessorMask.SetValue(mask); }
  605. /// GetDefaultProcessorMask
  606. /// Returns the mask set by SetDefaultProcessorMask.
  607. static uint64_t GetDefaultProcessorMask()
  608. { return sDefaultProcessorMask.GetValue(); }
  609. /// GetPlatformData
  610. /// Returns platform-specific data for this thread for debugging uses or
  611. /// other cases whereby special (and non-portable) uses are required.
  612. /// The value returned is a struct of type EAThreadData.
  613. void* GetPlatformData()
  614. { return &mThreadData; }
  615. protected:
  616. static RunnableFunctionUserWrapper sGlobalRunnableFunctionUserWrapper;
  617. static RunnableClassUserWrapper sGlobalRunnableClassUserWrapper;
  618. static EA::Thread::AtomicInt32 sDefaultProcessor;
  619. static EA::Thread::AtomicUint64 sDefaultProcessorMask;
  620. EAThreadData mThreadData;
  621. };
  622. /// ThreadFactory
  623. ///
  624. /// Implements a factory-based creation and destruction mechanism for class Thread.
  625. /// A primary use of this would be to allow the Thread implementation to reside in
  626. /// a private library while users of the class interact only with the interface
  627. /// header and the factory. The factory provides conventional create/destroy
  628. /// semantics which use global operator new, but also provides manual construction/
  629. /// destruction semantics so that the user can provide for memory allocation
  630. /// and deallocation.
  631. class EATHREADLIB_API ThreadFactory
  632. {
  633. public:
  634. static Thread* CreateThread(); // Internally implemented as: return new Thread;
  635. static void DestroyThread(Thread* pThread); // Internally implemented as: delete pThread;
  636. static size_t GetThreadSize(); // Internally implemented as: return sizeof(Thread);
  637. static Thread* ConstructThread(void* pMemory); // Internally implemented as: return new(pMemory) Thread;
  638. static void DestructThread(Thread* pThread); // Internally implemented as: pThread->~Thread();
  639. };
  640. /// MakeThread
  641. ///
  642. /// Simplify creating threads with lambdas
  643. ///
  644. template <typename F>
  645. auto MakeThread(F&& f, const EA::Thread::ThreadParameters& params = EA::Thread::ThreadParameters())
  646. {
  647. typedef std::decay_t<F> decayed_f_t;
  648. auto get_memory = []
  649. {
  650. const auto sz = sizeof(decayed_f_t);
  651. auto* pAllocator = EA::Thread::GetAllocator();
  652. if(pAllocator)
  653. return pAllocator->Alloc(sz);
  654. else
  655. return malloc(sz);
  656. };
  657. auto thread_enty = [](void* pMemory) -> intptr_t
  658. {
  659. auto free_memory = [](void* p)
  660. {
  661. auto* pAllocator = EA::Thread::GetAllocator();
  662. if(pAllocator)
  663. return pAllocator->Free(p);
  664. else
  665. return free(p);
  666. };
  667. auto* pF = reinterpret_cast<decayed_f_t*>(pMemory);
  668. (*pF)();
  669. pF->~decayed_f_t();
  670. free_memory(pF);
  671. return 0;
  672. };
  673. EA::Thread::Thread thread;
  674. thread.Begin(thread_enty, new(get_memory()) decayed_f_t(std::forward<F>(f)), &params); // deleted in the thread entry function
  675. return thread;
  676. }
  677. } // namespace Thread
  678. } // namespace EA
  679. #if defined(EA_DLL) && defined(EA_COMPILER_MSVC)
  680. // re-enable warning 4251 (it's a level-1 warning and should not be suppressed globally)
  681. EA_RESTORE_VC_WARNING()
  682. #endif
  683. #endif // EATHREAD_EATHREAD_THREAD_H