eathread.h 41 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826
  1. ///////////////////////////////////////////////////////////////////////////////
  2. // Copyright (c) Electronic Arts Inc. All rights reserved.
  3. ///////////////////////////////////////////////////////////////////////////////
  4. /////////////////////////////////////////////////////////////////////////////
  5. // eathread.h
  6. //
  7. // Created by Paul Pedriana, Maxis
  8. //
  9. // Provides some base global definitions for the EA::Thread library.
  10. //
  11. // Design
  12. // Many of the design criteria for EA::Thread is based on the design of the
  13. // Posix threading standard. The Posix threading standard is designed to
  14. // work portably on a wide range of operating systems and hardware, including
  15. // embedded systems and realtime environments. As such, Posix threads generally
  16. // represent a competent model to follow where possible. Windows and various
  17. // other platforms have independent multi-threading systems which are taken
  18. // into account here as well. If something exists in Windows but doesn't
  19. // exist here (e.g. Thread suspend/resume), there is a decent chance that it
  20. // is by design and for some good reason.
  21. //
  22. // C++
  23. // There are a number of C++ libraries devoted to multithreading. Usually the
  24. // goal of these libraries is provide a platform independent interface which
  25. // simplifies the most common usage patterns and helps prevent common errors.
  26. // Some of these libraries are basic wrappers around existing C APIs while
  27. // others provide a new and different paradigm. We take the former approach
  28. // here, as it is provides more or less the same functionality but provides
  29. // it in a straightforward way that is easily approached by those familiar
  30. // with platform-specific APIs. This approach has been referred to as the
  31. // "Wrapper Facade Pattern".
  32. //
  33. // Condition Variables
  34. // Posix condition variables are implemented via the Condition class. Condition
  35. // is essentially the Java and C# name for Posix' condition variables. For some
  36. // people, a condition variable may seem similar to a Win32 Signal. In actuality
  37. // they are similar but there is one critical difference: a Signal does not
  38. // atomically unlock a mutex as part of the signaling process. This results in
  39. // problematic race conditions that make reliable producer/consumer systems
  40. // impossible to implement.
  41. //
  42. // Signals
  43. // As of this writing, there isn't a Win32-like Signal class. The reason for this
  44. // is that Semaphore does most or all the duty that Signal does and is a little
  45. // more portable, given that Signals exist only on Win32 and not elsewhere.
  46. //
  47. // Timeouts
  48. // Timeouts are specified as absolute times and not relative times. This may
  49. // not be how Win32 threading works but it is what's proper and is how Posix
  50. // threading works. From the OpenGroup online pthread documentation on this:
  51. // An absolute time measure was chosen for specifying the
  52. // timeout parameter for two reasons. First, a relative time
  53. // measure can be easily implemented on top of a function
  54. // that specifies absolute time, but there is a race
  55. // condition associated with specifying an absolute timeout
  56. // on top of a function that specifies relative timeouts.
  57. // For example, assume that clock_gettime() returns the
  58. // current time and cond_relative_timed_wait() uses relative
  59. // timeouts:
  60. // clock_gettime(CLOCK_REALTIME, &now);
  61. // reltime = sleep_til_this_absolute_time - now;
  62. // cond_relative_timed_wait(c, m, &reltime);
  63. // If the thread is preempted between the first statement and
  64. // the last statement, the thread blocks for too long. Blocking,
  65. // however, is irrelevant if an absolute timeout is used.
  66. // An absolute timeout also need not be recomputed if it is used
  67. // multiple times in a loop, such as that enclosing a condition wait.
  68. // For cases when the system clock is advanced discontinuously by
  69. // an operator, it is expected that implementations process any
  70. // timed wait expiring at an intervening time as if that time had
  71. // actually occurred.
  72. //
  73. // General Threads
  74. // For detailed information about threads, it is recommended that you read
  75. // various competent sources of information about multithreading and
  76. // multiprocessing.
  77. // Programming with POSIX(R) Threads, by David R. Butenhof
  78. // http://www.opengroup.org/onlinepubs/007904975/basedefs/pthread.h.html
  79. // usenet: comp.programming.threads
  80. // http://www.openmp.org/index.cgi?faq
  81. // http://www.lambdacs.com/cpt/MFAQ.html
  82. // http://www.lambdacs.com/cpt/FAQ.html
  83. // http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dllproc/base/processes_and_threads.asp
  84. //
  85. /////////////////////////////////////////////////////////////////////////////
  86. #ifndef EATHREAD_EATHREAD_H
  87. #define EATHREAD_EATHREAD_H
  88. #include <eathread/internal/config.h>
  89. #if !EA_THREADS_AVAILABLE
  90. // Do nothing
  91. #elif EA_USE_CPP11_CONCURRENCY
  92. EA_DISABLE_VC_WARNING(4265 4365 4836 4571 4625 4626 4628 4193 4127 4548 4574 4946 4350)
  93. #include <chrono>
  94. #include <thread>
  95. EA_RESTORE_VC_WARNING()
  96. #elif defined(EA_PLATFORM_UNIX) || EA_POSIX_THREADS_AVAILABLE
  97. #include <pthread.h>
  98. #if defined(EA_HAVE_DINKUMWARE_CPP_LIBRARY) // Dinkumware doesn't usually provide gettimeofday or <sys/types.h>
  99. #include <time.h> // clock_gettime
  100. #elif defined(EA_PLATFORM_UNIX)
  101. #include <sys/time.h> // gettimeofday
  102. #endif
  103. #endif
  104. #if defined(EA_PLATFORM_APPLE)
  105. #include <mach/mach_types.h>
  106. #endif
  107. #if defined(EA_PLATFORM_SONY)
  108. #include "sdk_version.h"
  109. #include <kernel.h>
  110. #endif
  111. #include <limits.h>
  112. #include <float.h>
  113. #if defined(EA_PRAGMA_ONCE_SUPPORTED)
  114. #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.
  115. #endif
  116. ///////////////////////////////////////////////////////////////////////////////
  117. // EA_THREAD_PREEMPTIVE / EA_THREAD_COOPERATIVE
  118. //
  119. // Defined or not defined.
  120. //
  121. // EA_THREAD_COOPERATIVE means that threads are not time-sliced by the
  122. // operating system. If there exist multiple threads of the same priority
  123. // then they will need to wait, sleep, or yield in order for the others
  124. // to get time. See enum Scheduling and EATHREAD_SCHED for more info.
  125. //
  126. // EA_THREAD_PREEMPTIVE means that threads are time-sliced by the operating
  127. // system at runtime. If there exist multiple threads of the same priority
  128. // then the operating system will split execution time between them.
  129. // See enum Scheduling and EATHREAD_SCHED for more info.
  130. //
  131. #if !EA_THREADS_AVAILABLE
  132. #define EA_THREAD_COOPERATIVE
  133. #else
  134. #define EA_THREAD_PREEMPTIVE
  135. #endif
  136. /// namespace EA
  137. ///
  138. /// This is the standard Electronic Arts C++ namespace.
  139. ///
  140. namespace EA
  141. {
  142. namespace Allocator
  143. {
  144. class ICoreAllocator;
  145. }
  146. /// namespace Thread
  147. ///
  148. /// This is the standard Electronic Arts Thread C++ namespace.
  149. ///
  150. namespace Thread
  151. {
  152. /// Scheduling
  153. /// Defines scheduling types supported by the given platform.
  154. /// These are defined in detail by the Posix standard, with the
  155. /// exception of Coop, which is added here. FIFO scheduling
  156. /// is the most classic for game development, as it allows for
  157. /// thread priorities and well-behaved synchronization primitives,
  158. /// but it doesn't do time-slicing. The problem with time slicing
  159. /// is that threads are pre-empted in the middle of work and this
  160. /// hurts execution performance and cache performance.
  161. ///
  162. enum Scheduling
  163. {
  164. kSchedulingFIFO = 1, /// There is no automatic time-slicing; thread priorities control execution and context switches.
  165. kSchedulingRR = 2, /// Same as FIFO but is periodic time-slicing.
  166. kSchedulingSporadic = 4, /// Complex scheduling control. See the Posix standard.
  167. kSchedulingTS = 8, /// a.k.a. SCHED_OTHER. Usually same as FIFO or RR except that thread priorities and execution can be temporarily modified.
  168. kSchedulingCoop = 16 /// The user must control thread scheduling beyond the use of synchronization primitives.
  169. };
  170. #if defined(EA_PLATFORM_UNIX)
  171. #define EATHREAD_SCHED kSchedulingFIFO
  172. #elif defined(EA_PLATFORM_MICROSOFT)
  173. #define EATHREAD_SCHED kSchedulingRR
  174. #else
  175. #define EATHREAD_SCHED kSchedulingFIFO
  176. #endif
  177. // EATHREAD_MULTIPROCESSING_OS
  178. //
  179. // Defined as 0 or 1.
  180. // Indicates whether the OS supports multiple concurrent processes, which may be in
  181. // addition to supporting multiple threads within a process.
  182. // Some platforms support multiple concurrently loaded processes but don't support
  183. // running these processes concurrently. We don't currently count this as a
  184. // multiprocessing OS.
  185. #ifndef EATHREAD_MULTIPROCESSING_OS
  186. #if defined(EA_PLATFORM_WINDOWS) || defined(EA_PLATFORM_UNIX)
  187. #define EATHREAD_MULTIPROCESSING_OS 1
  188. #else
  189. #define EATHREAD_MULTIPROCESSING_OS 0
  190. #endif
  191. #endif
  192. // EATHREAD_OTHER_THREAD_NAMING_SUPPORTED
  193. //
  194. // Defined as 0 or 1.
  195. // Indicates whether the OS supports setting the thread name from a different
  196. // thread (set to 1) or if the name can be set only from the curren thread (set to 0)
  197. #ifndef EATHREAD_OTHER_THREAD_NAMING_SUPPORTED
  198. #if defined(EA_PLATFORM_LINUX) || defined(EA_PLATFORM_APPLE)
  199. #define EATHREAD_OTHER_THREAD_NAMING_SUPPORTED 0
  200. #else
  201. #define EATHREAD_OTHER_THREAD_NAMING_SUPPORTED 1
  202. #endif
  203. #endif
  204. // Uint / Int
  205. // Defines a machine-word sized integer, useful for operations that are as efficient
  206. // as possible on the given machine. Note that the C99 intfastNN_t types aren't sufficient,
  207. // as they are defined by compilers in an undesirable way for the processors we work with.
  208. #if !defined(EA_PLATFORM_WORD_SIZE) || (EA_PLATFORM_WORD_SIZE == 4)
  209. typedef uint32_t Uint;
  210. typedef int32_t Int;
  211. #else
  212. typedef uint64_t Uint;
  213. typedef int64_t Int;
  214. #endif
  215. /// ThreadId
  216. /// Uniquely identifies a thread throughout the system and is used by the EAThread API
  217. /// to identify threads in a way equal to system provided thread ids. A ThreadId is the
  218. /// same as a system thread id and can be used in direct system threading API calls.
  219. #if !EA_THREADS_AVAILABLE
  220. typedef int ThreadId;
  221. #elif EA_USE_CPP11_CONCURRENCY
  222. typedef std::thread::id ThreadId;
  223. #elif defined(EA_PLATFORM_SONY)
  224. typedef uint64_t ThreadId;
  225. #elif defined(EA_PLATFORM_UNIX) || EA_POSIX_THREADS_AVAILABLE
  226. typedef pthread_t ThreadId;
  227. #elif defined(EA_PLATFORM_MICROSOFT) && !EA_POSIX_THREADS_AVAILABLE
  228. typedef void* ThreadId; // This is really HANDLE, but HANDLE is the same as void* and we can avoid an expensive #include here.
  229. #else
  230. typedef int ThreadId;
  231. #endif
  232. // ThreadId constants
  233. #if EA_USE_CPP11_CONCURRENCY
  234. const ThreadId kThreadIdInvalid = ThreadId(); /// Special ThreadId indicating an invalid thread identifier.
  235. #else
  236. const ThreadId kThreadIdInvalid = ThreadId(0); /// Special ThreadId indicating an invalid thread identifier.
  237. const ThreadId kThreadIdCurrent = ThreadId(INT_MAX); /// Special ThreadId indicating the current thread.
  238. const ThreadId kThreadIdAny = ThreadId(INT_MAX - 1); /// Special ThreadId indicating no thread in particular.
  239. #endif
  240. /// SysThreadId
  241. /// It turns out that Microsoft operating systems (Windows, XBox, XBox 360)
  242. /// have two different ways to identify a thread: HANDLE and DWORD. Some API
  243. /// functions take thread HANDLES, while others take what Microsoft calls
  244. /// thread ids (DWORDs). EAThread ThreadId is a HANDLE, as that is used for
  245. /// more of the core threading APIs. However, some OS-level APIs accept instead
  246. /// the DWORD thread id.
  247. #if defined(EA_PLATFORM_MICROSOFT) && !EA_POSIX_THREADS_AVAILABLE && !EA_USE_CPP11_CONCURRENCY
  248. typedef uint32_t SysThreadId;
  249. const SysThreadId kSysThreadIdInvalid = SysThreadId(0); /// Special SysThreadId indicating an invalid thread identifier.
  250. #elif defined(EA_PLATFORM_SONY)
  251. typedef ScePthread SysThreadId;
  252. const SysThreadId kSysThreadIdInvalid = { 0 }; /// Special SysThreadId indicating an invalid thread identifier.
  253. #elif defined(EA_PLATFORM_APPLE)
  254. typedef thread_act_t SysThreadId; // thread_act_t is useful for calling mach APIs such as thread_policy_set() with.
  255. const SysThreadId kSysThreadIdInvalid = SysThreadId(0); /// Special SysThreadId indicating an invalid thread identifier.
  256. #elif EA_USE_CPP11_CONCURRENCY
  257. typedef std::thread::native_handle_type SysThreadId;
  258. const SysThreadId kSysThreadIdInvalid = { 0 }; /// Special SysThreadId indicating an invalid thread identifier.
  259. // For MSVC, native_handle_type is not a primitive type so we define operator== and operator!= for convenience.
  260. // We use an auto converting proxy type for comparisons to avoid errors when native_handle_type is a built in type.
  261. bool Equals(const SysThreadId& a, const SysThreadId& b);
  262. struct SysThreadIdProxy
  263. {
  264. SysThreadIdProxy(const SysThreadId& id_) : id(id_) {}
  265. SysThreadId id;
  266. };
  267. inline bool operator==(const SysThreadId& lhs, const SysThreadIdProxy& rhs) { return Equals(lhs, rhs.id); }
  268. inline bool operator!=(const SysThreadId& lhs, const SysThreadIdProxy& rhs) { return !Equals(lhs, rhs.id); }
  269. #else
  270. typedef ThreadId SysThreadId;
  271. const SysThreadId kSysThreadIdInvalid = SysThreadId(0); /// Special SysThreadId indicating an invalid thread identifier.
  272. #endif
  273. /// ThreadUniqueId
  274. /// Uniquely identifies a thread throughout the system, but in a way that is not
  275. /// necessarily compatible with system thread id identification. Sometimes it is
  276. /// costly to work with system thread ids whereas all you want is some integer
  277. /// that is unique between threads and you don't need to use it for system calls.
  278. /// See the EAThreadGetUniqueId macro/function for usage.
  279. typedef Uint ThreadUniqueId;
  280. // ThreadUniqueId constants
  281. const ThreadUniqueId kThreadUniqueIdInvalid = 0; /// Special ThreadUniqueId indicating an invalid thread identifier.
  282. // Time constants
  283. // Milliseconds are the units of time in EAThread. While every generation of computers
  284. // results in faster computers and thus milliseconds become an increasingly large number
  285. // compared to the computer speed, computer multithreading is still largely done at the
  286. // millisecond level, due to it still being a small value relative to human perception.
  287. // We may reconsider this some time in the future and provide an option to have ThreadTime
  288. // be specified in finer units, such as microseconds.
  289. #if EA_USE_CPP11_CONCURRENCY
  290. typedef std::chrono::milliseconds::rep ThreadTime; /// Current storage mechanism for time used by thread timeout functions. Units are milliseconds.
  291. const ThreadTime kTimeoutImmediate = std::chrono::milliseconds::zero().count();/// Used to specify to functions to return immediately if the operation could not be done.
  292. const ThreadTime kTimeoutNone = std::chrono::milliseconds::max().count(); /// Used to specify to functions to block without a timeout (i.e. block forever).
  293. const ThreadTime kTimeoutYield = std::chrono::milliseconds::zero().count(); /// This is used with ThreadSleep to minimally yield to threads of equivalent priority.
  294. #define EA_THREADTIME_AS_INT64(t) ((int64_t)(t))
  295. #define EA_THREADTIME_AS_DOUBLE(t) ((double)(t))
  296. #elif defined(EA_PLATFORM_SONY) && EA_THREADS_AVAILABLE
  297. typedef double ThreadTime; // SceKernelUseconds maps to unsigned int
  298. static_assert(sizeof(ThreadTime) >= sizeof(unsigned int), "ThreadTime not large enough for uint32_t representation of milliseconds for platform portablity");
  299. const ThreadTime kTimeoutImmediate = 0;
  300. const ThreadTime kTimeoutNone = DBL_MAX;
  301. const ThreadTime kTimeoutYield = 0.000001; // 1 nanosecond in terms of a millisecond
  302. #define EA_THREADTIME_AS_UINT_MICROSECONDS(t) ((unsigned int)((t) * 1000.0)) /// Returns the milliseconds time as uint in microseconds.
  303. #define EA_THREADTIME_AS_INT64(t) ((int64_t)(t)) /// Returns the unconverted milliseconds time as a int64_t.
  304. #define EA_THREADTIME_AS_DOUBLE(t) (t) /// Returns the time as double milliseconds. May include a fraction component.
  305. #define EA_TIMESPEC_AS_UINT(t) ((unsigned int)(((t).tv_sec * 1000) + ((t).tv_nsec / 1000000))) /// Returns the time as uint in milliseconds.
  306. #define EA_TIMESPEC_AS_DOUBLE_IN_MS(t) ( (((t).tv_sec * 1000000000ull) + ((t).tv_nsec))/1000000.0) /// Returns the time as uint in milliseconds.
  307. #elif (defined(EA_PLATFORM_UNIX) || EA_POSIX_THREADS_AVAILABLE) && EA_THREADS_AVAILABLE
  308. struct ThreadTime : public timespec
  309. {
  310. typedef int seconds_t; // To consider: change to uint64_t or maybe long.
  311. typedef int nseconds_t;
  312. ThreadTime() { tv_sec = 0; tv_nsec = 0; }
  313. ThreadTime(const timespec& ts) { tv_sec = ts.tv_sec; tv_nsec = ts.tv_nsec; }
  314. ThreadTime(seconds_t nSeconds, nseconds_t nNanoseconds) { tv_sec = (long)nSeconds; tv_nsec = (long)nNanoseconds; }
  315. ThreadTime(const int64_t& nMilliseconds) { tv_sec = (long)(nMilliseconds / 1000); tv_nsec = (long)((nMilliseconds - (tv_sec * 1000)) * 1000000); }
  316. ThreadTime& operator+=(const int64_t& nMilliseconds) { long lTemp((long)nMilliseconds / 1000); tv_sec += lTemp; tv_nsec += (long)((nMilliseconds - (lTemp * 1000)) * 1000000); if(tv_nsec >= 1000000000){ tv_sec++; tv_nsec -= 1000000000; } return *this; }
  317. ThreadTime& operator-=(const int64_t& nMilliseconds) { long lTemp((long)nMilliseconds / 1000); tv_sec -= lTemp; tv_nsec -= (long)((nMilliseconds - (lTemp * 1000)) * 1000000); if(tv_nsec < 0) { tv_sec--; tv_nsec += 1000000000; } return *this; }
  318. ThreadTime& operator+=(const ThreadTime& tt) { tv_sec += tt.tv_sec; tv_nsec += tt.tv_nsec; if(tv_nsec >= 1000000000){ tv_sec++; tv_nsec -= 1000000000; } return *this; }
  319. ThreadTime& operator-=(const ThreadTime& tt) { tv_sec -= tt.tv_sec; tv_nsec -= tt.tv_nsec; if(tv_nsec < 0) { tv_sec--; tv_nsec += 1000000000; } return *this; }
  320. };
  321. inline ThreadTime operator+ (const ThreadTime& tt1, const ThreadTime& tt2) { ThreadTime ttR(tt1); ttR += tt2; return ttR; }
  322. inline ThreadTime operator+ (const ThreadTime& tt, const int64_t& nMilliseconds){ ThreadTime ttR(tt); ttR += nMilliseconds; return ttR; }
  323. inline ThreadTime operator- (const ThreadTime& tt1, const ThreadTime& tt2) { ThreadTime ttR(tt1); ttR -= tt2; return ttR; }
  324. inline ThreadTime operator- (const ThreadTime& tt, const int64_t& nMilliseconds){ ThreadTime ttR(tt); ttR -= nMilliseconds; return ttR; }
  325. inline bool operator==(const ThreadTime& tt1, const ThreadTime& tt2) { return (tt1.tv_nsec == tt2.tv_nsec) && (tt1.tv_sec == tt2.tv_sec); } // These comparisons assume that the nsec value is normalized (always between 0 && 1000000000).
  326. inline bool operator!=(const ThreadTime& tt1, const ThreadTime& tt2) { return (tt1.tv_nsec != tt2.tv_nsec) || (tt1.tv_sec != tt2.tv_sec); }
  327. inline bool operator< (const ThreadTime& tt1, const ThreadTime& tt2) { return (tt1.tv_sec == tt2.tv_sec) ? (tt1.tv_nsec < tt2.tv_nsec) : (tt1.tv_sec < tt2.tv_sec); }
  328. inline bool operator> (const ThreadTime& tt1, const ThreadTime& tt2) { return (tt1.tv_sec == tt2.tv_sec) ? (tt1.tv_nsec > tt2.tv_nsec) : (tt1.tv_sec > tt2.tv_sec); }
  329. inline bool operator<=(const ThreadTime& tt1, const ThreadTime& tt2) { return (tt1.tv_sec == tt2.tv_sec) ? (tt1.tv_nsec <= tt2.tv_nsec) : (tt1.tv_sec <= tt2.tv_sec); }
  330. inline bool operator>=(const ThreadTime& tt1, const ThreadTime& tt2) { return (tt1.tv_sec == tt2.tv_sec) ? (tt1.tv_nsec >= tt2.tv_nsec) : (tt1.tv_sec >= tt2.tv_sec); }
  331. const ThreadTime kTimeoutImmediate(0, 0); /// Used to specify to functions to return immediately if the operation could not be done.
  332. const ThreadTime kTimeoutNone(INT_MAX, INT_MAX); /// Used to specify to functions to block without a timeout (i.e. block forever).
  333. const ThreadTime kTimeoutYield(0, 0); /// Used to specify to ThreadSleep to yield to threads of equivalent priority.
  334. #define EA_THREADTIME_AS_INT64(t) ((int64_t)(((t).tv_sec * 1000) + ((t).tv_nsec / 1000000))) /// Returns the time as int64_t milliseconds.
  335. #define EA_THREADTIME_AS_INT64_MICROSECONDS(t) ((int64_t)(((t).tv_sec * 1000000) + (((t).tv_nsec / 1000)))) /// Returns the time as int64_t microseconds.
  336. #define EA_THREADTIME_AS_DOUBLE(t) (((t).tv_sec * 1000.0) + ((t).tv_nsec / 1000000.0)) /// Returns the time as double milliseconds.
  337. #elif defined(EA_PLATFORM_MICROSOFT) && defined(EA_PROCESSOR_X86_64)
  338. typedef uint64_t ThreadTime; /// Current storage mechanism for time used by thread timeout functions. Units are milliseconds.
  339. const ThreadTime kTimeoutImmediate = 0; /// Used to specify to functions to return immediately if the operation could not be done.
  340. const ThreadTime kTimeoutNone = UINT64_MAX; /// Used to specify to functions to block without a timeout (i.e. block forever).
  341. const ThreadTime kTimeoutYield = 0; /// This is used with ThreadSleep to minimally yield to threads of equivalent priority.
  342. #define EA_THREADTIME_AS_INT64(t) ((int64_t)(t))
  343. #define EA_THREADTIME_AS_DOUBLE(t) ((double)(t))
  344. #else
  345. typedef unsigned ThreadTime; /// Current storage mechanism for time used by thread timeout functions. Units are milliseconds.
  346. const ThreadTime kTimeoutImmediate = 0; /// Used to specify to functions to return immediately if the operation could not be done.
  347. const ThreadTime kTimeoutNone = UINT_MAX; /// Used to specify to functions to block without a timeout (i.e. block forever).
  348. const ThreadTime kTimeoutYield = 0; /// This is used with ThreadSleep to minimally yield to threads of equivalent priority.
  349. #define EA_THREADTIME_AS_INT64(t) ((int64_t)(t))
  350. #define EA_THREADTIME_AS_DOUBLE(t) ((double)(t))
  351. #endif
  352. #if defined(EA_PLATFORM_MICROSOFT) /// Can be removed from C++11 Concurrency builds once full C++11 implementation is completed
  353. uint32_t RelativeTimeoutFromAbsoluteTimeout(ThreadTime absoluteTimeout);
  354. #endif
  355. // Thread priority constants
  356. // There is a standardized mechanism to convert system-specific thread
  357. // priorities to these platform-independent priorities and back without
  358. // loss of precision or behaviour. The convention is that kThreadPriorityDefault
  359. // equates to the system-specific normal thread priority. Thus for Microsoft
  360. // APIs a thread with priority kThreadPriorityDefault will be of Microsoft
  361. // priority THREAD_PRIORITY_NORMAL. A thread with an EAThread priority
  362. // of kThreadPriorityDefault + 1 will have a Microsoft priority of THREAD_PRIORITY_NORMAL + 1.
  363. // The only difference is that with EAThread all platforms are standardized on
  364. // kThreadPriorityDefault as the normal value and that higher EAThread priority
  365. // integral values mean higher thread priorities for running threads. This last
  366. // item is of significance because Sony platforms natively define lower integers
  367. // to mean higher thread priorities. With EAThread you get consistent behaviour
  368. // across platforms and thus kThreadPriorityDefault + 1 always results in a
  369. // thread that runs at priority of one level higher. On Sony platforms, this + 1
  370. // gets translated to a - 1 when calling the Sony native thread priority API.
  371. // EAThread priorities have no mandated integral bounds, though
  372. // kThreadPriorityMin and kThreadPriorityMax are defined as convenient practical
  373. // endpoints for users. Users should not generally use hard-coded constants to
  374. // refer to EAThread priorities much like it's best not to use hard-coded
  375. // constants to refer to platform-specific native thread priorities. Also, users
  376. // generally want to avoid manipulating thread priorities to the extent possible
  377. // and use conventional synchronization primitives to control execution.
  378. // Similarly, wildly varying thread priorities such as +100 are not likely to
  379. // achieve much and are not likely to be very portable.
  380. //
  381. const int kThreadPriorityUnknown = INT_MIN; /// Invalid or unknown priority.
  382. const int kThreadPriorityMin = -128; /// Minimum thread priority enumerated by EAThread. In practice, a valid thread priority can be anything other than kThreadPriorityUnknown.
  383. const int kThreadPriorityDefault = 0; /// Default (a.k.a. normal) thread priority.
  384. const int kThreadPriorityMax = 127; /// Maximum thread priority enumerated by EAThread. In practice, a valid thread priority can be anything other than kThreadPriorityUnknown.
  385. /// kSysThreadPriorityDefault
  386. /// Defines the platform-specific default thread priority.
  387. #if defined(EA_PLATFORM_SONY)
  388. const int kSysThreadPriorityDefault = 700;
  389. #elif defined(EA_PLATFORM_UNIX) || EA_POSIX_THREADS_AVAILABLE
  390. const int kSysThreadPriorityDefault = 0; // Some Unix variants use values other than zero, but these are not relevant.
  391. #elif defined(EA_PLATFORM_MICROSOFT)
  392. const int kSysThreadPriorityDefault = 0; // Same as THREAD_PRIORITY_NORMAL
  393. #else
  394. const int kSysThreadPriorityDefault = 0;
  395. #endif
  396. // The following functions are standalone and not static members of the thread class
  397. // because they are potentially used by multiple threading primitives and we don't
  398. // want to create a dependency of threading primitives on class Thread.
  399. /// GetThreadId
  400. /// Gets the thread ID for the current thread. This thread ID should
  401. /// be unique throughout the system.
  402. EATHREADLIB_API ThreadId GetThreadId();
  403. /// GetSysThreadId
  404. /// Gets the operating system thread id associated with the given ThreadId.
  405. /// It turns out that Microsoft operating systems (Windows, XBox, XBox 360)
  406. /// have two different ways to identify a thread: HANDLE and DWORD. Some API
  407. /// functions take thread HANDLES, while others take what Microsoft calls
  408. /// thread ids (DWORDs). EAThread ThreadId is a HANDLE, as that is used for
  409. /// more of the core threading APIs. However, some OS-level APIs accept instead
  410. /// the DWORD thread id. This function returns the OS thread id for a given
  411. /// EAThread ThreadId. In the case of Microsoft OSs, this returns a DWORD from
  412. /// a HANDLE and with other OSs this function simply returns the ThreadId.
  413. /// Returns a valid SysThreadId or kSysThreadIdInvalid if the input id is invalid.
  414. EATHREADLIB_API SysThreadId GetSysThreadId(ThreadId id);
  415. /// GetThreadId
  416. ///
  417. /// This is a portable function to convert between ThreadId's and SysThreadId's.
  418. /// For platforms that do not differentiate between these two types no conversion is attempted.
  419. EATHREADLIB_API ThreadId GetThreadId(SysThreadId id);
  420. /// GetSysThreadId
  421. /// Gets the SysThreadId for the current thread. This thread ID should
  422. /// be unique throughout the system.
  423. EATHREADLIB_API SysThreadId GetSysThreadId();
  424. /// GetThreadPriority
  425. /// Gets the priority of the current thread.
  426. /// This function can return any int except for kThreadPriorityUnknown, as the
  427. /// current thread's priority will always be knowable. A return value of kThreadPriorityDefault
  428. /// means that this thread is of normal (a.k.a. default) priority.
  429. /// See the documentation for thread priority constants (e.g. kThreadPriorityDefault)
  430. /// for more information about thread priority values and behaviour.
  431. EATHREADLIB_API int GetThreadPriority();
  432. /// SetThreadPriority
  433. /// Sets the priority of the current thread.
  434. /// Accepts any integer priority value except kThreadPriorityUnknown.
  435. /// On some platforms, this function will automatically convert any invalid
  436. /// priority for that particular platform to a valid one. A normal (a.k.a. default) thread
  437. /// priority is identified by kThreadPriorityDefault.
  438. /// See the documentation for thread priority constants (e.g. kThreadPriorityDefault)
  439. /// for more information about thread priority values and behaviour.
  440. EATHREADLIB_API bool SetThreadPriority(int nPriority);
  441. /// GetThreadStackBase
  442. /// Returns the base address of the current thread's stack.
  443. /// Recall that on all supported platforms that the stack grows downward
  444. /// and thus that the stack base address is of a higher value than the
  445. /// stack's contents.
  446. EATHREADLIB_API void* GetThreadStackBase();
  447. // Thread processor constants
  448. const int kProcessorDefault = -1; /// Use the default processor for the platform. On many platforms, the default is to not be tied to any specific processor, but other threads can only ever be bound to a single processor.
  449. const int kProcessorAny = -2; /// Run the thread on any processor. Many platforms will switch threads between processors dynamically.
  450. /// SetThreadProcessor
  451. /// Sets the processor the current thread should run on. Valid values
  452. /// are kThreadProcessorDefault, kThreadProcessorAny, or a processor
  453. /// index in the range of [0, processor count). If the input value
  454. /// is >= the processor count, it will be reduced to be a modulo of
  455. /// the processor count. Any other invalid value will cause the processor
  456. /// to be set to zero.
  457. /// This function isn't guaranteed to restrict the thread from executing
  458. /// on the given processor for all platforms. Some platforms don't support
  459. /// assigning thread processor affinity, while with others (e.g. Windows using
  460. /// SetThreadIdealProcessor) the OS tries to comply but will use a different
  461. /// processor when the assigned one is unavailable.
  462. EATHREADLIB_API void SetThreadProcessor(int nProcessor);
  463. /// GetThreadProcessor
  464. /// Returns the (possibly virtual) CPU index that the thread is currently
  465. /// running on. Different systems may have differing definitions of what
  466. /// a unique processor is. Some CPUs have multiple sub-CPUs (e.g. "cores")
  467. /// which are treated as unique processors by the system.
  468. /// Many systems switch threads between processors dynamically; thus it's
  469. /// possible that the thread may be on a different CPU by the time this
  470. /// function returns.
  471. /// Lastly, some systems don't provide the ability to detect what processor
  472. /// the current thread is running on; in these cases this function returns 0.
  473. EATHREADLIB_API int GetThreadProcessor();
  474. /// GetProcessorCount
  475. /// Returns the (possibly virtual) CPU count that the current system has.
  476. /// Some systems (e.g. Posix, Unix) don't expose an ability to tell how
  477. /// many processors there are; in these cases this function returns 1.
  478. /// This function returns the number of currently active processors.
  479. /// Some systems can modify the number of active processors dynamically.
  480. EATHREADLIB_API int GetProcessorCount();
  481. /// kThreadAffinityMaskAny
  482. /// Defines the thread affinity mask that enables the thread
  483. /// to float on all available processors.
  484. typedef uint64_t ThreadAffinityMask;
  485. const ThreadAffinityMask kThreadAffinityMaskAny = ~0U;
  486. /// SetThreadAffinityMask
  487. ///
  488. /// The nAffinityMask is a bit field where each bit designates a processor.
  489. ///
  490. /// This function isn't guaranteed to restrict the thread from executing
  491. /// on the given processor for all platforms. Some platforms don't support
  492. /// assigning thread processor affinity, while with others (e.g. Windows using
  493. /// SetThreadIdealProcessor) the OS tries to comply but will use a different
  494. /// processor when the assigned one is unavailable.
  495. EATHREADLIB_API void SetThreadAffinityMask(ThreadAffinityMask nAffinityMask);
  496. EATHREADLIB_API void SetThreadAffinityMask(const EA::Thread::ThreadId& id, ThreadAffinityMask nAffinityMask);
  497. /// GetThreadAffinityMask
  498. ///
  499. /// Returns the current thread affinity mask specified by the user.
  500. EATHREADLIB_API ThreadAffinityMask GetThreadAffinityMask();
  501. EATHREADLIB_API ThreadAffinityMask GetThreadAffinityMask(const EA::Thread::ThreadId& id);
  502. /// GetName
  503. /// Returns the name of the thread assigned by the SetName function.
  504. /// If the thread was not named by the SetName function, then the name is empty ("").
  505. EATHREADLIB_API const char* GetThreadName();
  506. EATHREADLIB_API const char* GetThreadName(const EA::Thread::ThreadId& id);
  507. /// SetThreadName
  508. ///
  509. /// Sets a descriptive name or the thread. On some platforms this name is passed on
  510. /// to the debugging tools so they can see this name. The name length, including a
  511. /// terminating 0 char, is limited to EATHREAD_NAME_SIZE characters. Any characters
  512. /// beyond that are ignored.
  513. ///
  514. /// You can set the name of a Thread object only if it has already begun. You can
  515. /// also set the name with the Begin function via the ThreadParameters argument to
  516. /// Begin. This design is in order to simplify the implementation, but being able
  517. /// to set ThreadParameters before Begin is something that can be considered in the
  518. /// future.
  519. ///
  520. /// Some platforms (e.g. Linux) have the restriction that this function works
  521. /// properly only when called by the same thread that you want to name. Given this
  522. /// situation, the most portable way to use this SetName function is to either
  523. /// always call it from the thread to be named or to use the ThreadParameters to
  524. /// give the thread a name before it is started and let the started thread name
  525. /// itself.
  526. //
  527. //
  528. //
  529. EATHREADLIB_API void SetThreadName(const char* pName);
  530. EATHREADLIB_API void SetThreadName(const EA::Thread::ThreadId& id, const char* pName);
  531. /// ThreadSleep
  532. /// Puts the current thread to sleep for an amount of time hinted at
  533. /// by the time argument. The timeout is merely a hint and the system
  534. /// thread scheduler might return well before the sleep time has elapsed.
  535. /// The input 'timeRelative' refers to a relative time and not an
  536. /// absolute time such as used by EAThread mutexes, semaphores, etc.
  537. /// This is for consistency with other threading systems such as Posix and Win32.
  538. /// A sleep time of zero has the same effect as simply yielding to other
  539. /// available threads.
  540. ///
  541. EATHREADLIB_API void ThreadSleep(const ThreadTime& timeRelative = kTimeoutImmediate);
  542. /// ThreadCooperativeYield
  543. /// On platforms that use cooperative multithreading instead of
  544. /// pre-emptive multithreading, this function maps to ThreadSleep(0).
  545. /// On pre-emptive platforms, this function is a no-op. The intention
  546. /// is to allow cooperative multithreaded systems to yield manually
  547. /// in order for other threads to run, but also not to penalize
  548. /// pre-emptive systems that don't need such manual yielding. If you
  549. /// want to forcefully yield on a pre-emptive system, call ThreadSleep(0).
  550. #ifdef EA_THREAD_COOPERATIVE
  551. #define ThreadCooperativeYield() EA::Thread::ThreadSleep(EA::Thread::kTimeoutYield)
  552. #else
  553. #define ThreadCooperativeYield()
  554. #endif
  555. /// End
  556. /// This function provides a way for a thread to end itself.
  557. EATHREADLIB_API void ThreadEnd(intptr_t threadReturnValue);
  558. /// GetThreadTime
  559. /// Gets the current absolute time in milliseconds.
  560. /// This is required for working with absolute timeouts, for example.
  561. /// To specify a timeout that is relative to the current time, simply
  562. /// add time (in milliseconds) to the return value of GetThreadTime.
  563. /// Alternatively, you can use ConvertRelativeTime to calculate an absolute time.
  564. EATHREADLIB_API ThreadTime GetThreadTime();
  565. /// ConvertRelativeTime
  566. /// Given a relative time (in milliseconds), this function returns an
  567. /// absolute time (in milliseconds).
  568. /// Example usage:
  569. /// mutex.Lock(ConvertRelativeTime(1000));
  570. EATHREADLIB_API inline ThreadTime ConvertRelativeTime(const ThreadTime& timeRelative)
  571. {
  572. return GetThreadTime() + timeRelative;
  573. }
  574. /// SetAssertionFailureFunction
  575. /// Allows the user to specify a callback function to trap assertion failures.
  576. /// You can use this to glue your own assertion system into this system.
  577. typedef void (*AssertionFailureFunction)(const char* pExpression, void* pContext);
  578. EATHREADLIB_API void SetAssertionFailureFunction(AssertionFailureFunction pAssertionFailureFunction, void* pContext);
  579. /// AssertionFailure
  580. /// Triggers an assertion failure. This function is generally intended for internal
  581. /// use but is available so that related code can use the same system.
  582. EATHREADLIB_API void AssertionFailure(const char* pExpression);
  583. EATHREADLIB_API void AssertionFailureV(const char* pFormat, ...);
  584. /// Allocator
  585. /// This is the same as (the first four functions of) ICoreAllocator.
  586. /// If the allocator is set via SetAllocator, then it must be done before
  587. /// any other thread operations which might allocate memory are done.
  588. /// Typically this includes creating objects via factory functions and
  589. /// creating threads whereby you specify that thread resources be allocated for you..
  590. class Allocator
  591. {
  592. public:
  593. virtual ~Allocator() {}
  594. virtual void* Alloc(size_t size, const char* name = 0, unsigned int flags = 0) = 0;
  595. virtual void* Alloc(size_t size, const char* name, unsigned int flags,
  596. unsigned int align, unsigned int alignOffset = 0) = 0;
  597. virtual void Free(void* block, size_t size=0) = 0;
  598. };
  599. EATHREADLIB_API void SetAllocator(Allocator* pAllocator);
  600. EATHREADLIB_API Allocator* GetAllocator();
  601. EATHREADLIB_API void SetAllocator(EA::Allocator::ICoreAllocator* pAllocator);
  602. } // namespace Thread
  603. } // namespace EA
  604. /// EAThreadGetUniqueId
  605. ///
  606. /// Gets a value that is unique per thread but isn't necessarily the system-recognized
  607. /// thread id. This function is at least as fast as GetThreadId, and on some platforms
  608. /// is potentially significantly faster due to being implemented in inline asm which
  609. /// avoids a system function call which may cause an instruction cache miss penalty.
  610. /// This function is useful for creating very fast implementations of some kinds of
  611. /// threading constructs. It's implemented as a macro instead of a function in order
  612. /// to optimizing inlining success across all platforms and compilers.
  613. ///
  614. /// This function is guaranteed to yield a valid value; there are no error conditions.
  615. ///
  616. /// This macro acts as if it were declared as a function like this:
  617. /// void EAThreadGetUniqueId(ThreadUniqueId& result);
  618. ///
  619. /// Example usage:
  620. /// ThreadUniqueId x;
  621. /// EAThreadGetUniqueId(x);
  622. ///
  623. #if EA_USE_CPP11_CONCURRENCY
  624. #define EAThreadGetUniqueId(dest) (dest = static_cast<uintptr_t>(std::hash<std::thread::id>()(std::this_thread::get_id())))
  625. #elif defined(EA_PLATFORM_WINDOWS) && defined(EA_COMPILER_MSVC) && !defined(EA_PLATFORM_WIN64)
  626. // Reference implementation:
  627. //extern "C" __declspec(dllimport) unsigned long __stdcall GetCurrentThreadId();
  628. //#define EAThreadGetUniqueId(dest) dest = (ThreadUniqueId)(uintptr_t)GetCurrentThreadId()
  629. // Fast implementation:
  630. extern "C" unsigned long __readfsdword(unsigned long offset);
  631. #pragma intrinsic(__readfsdword)
  632. #define EAThreadGetUniqueId(dest) dest = (EA::Thread::ThreadUniqueId)(uintptr_t)__readfsdword(0x18)
  633. #elif defined(EA_COMPILER_MSVC) && defined(EA_PROCESSOR_X86_64)
  634. EA_DISABLE_ALL_VC_WARNINGS()
  635. #include <intrin.h>
  636. EA_RESTORE_ALL_VC_WARNINGS()
  637. #define EAThreadGetUniqueId(dest) dest = (EA::Thread::ThreadUniqueId)(uintptr_t)__readgsqword(0x30)
  638. // Could also use dest = (EA::Thread::ThreadUniqueId)NtCurrentTeb(), but that would require #including <windows.h>, which is very heavy.
  639. #else
  640. // Reference implementation:
  641. #define EAThreadGetUniqueId(dest) dest = (EA::Thread::ThreadUniqueId)(uintptr_t)EA::Thread::GetThreadId()
  642. #endif
  643. // EAThreadIdToString
  644. // Convert a thread id to a string suitable for use with printf like functions, e.g.:
  645. // printf("%s", EAThreadIdToString(myThreadId));
  646. // This macro is intended for debugging purposes and makes no guarantees about performance
  647. // or how a thread id is mapped to a string.
  648. namespace EA
  649. {
  650. namespace Thread
  651. {
  652. namespace detail
  653. {
  654. struct EATHREADLIB_API ThreadIdToStringBuffer
  655. {
  656. public:
  657. enum { BufSize = 32 };
  658. explicit ThreadIdToStringBuffer(EA::Thread::ThreadId threadId);
  659. const char* c_str() const { return mBuf; }
  660. private:
  661. char mBuf[BufSize];
  662. };
  663. struct EATHREADLIB_API SysThreadIdToStringBuffer
  664. {
  665. public:
  666. enum { BufSize = 32 };
  667. explicit SysThreadIdToStringBuffer(EA::Thread::SysThreadId sysThreadId);
  668. const char* c_str() const { return mBuf; }
  669. private:
  670. char mBuf[BufSize];
  671. };
  672. }
  673. }
  674. }
  675. #if !defined(EAThreadThreadIdToString)
  676. #define EAThreadThreadIdToString(threadId) (EA::Thread::detail::ThreadIdToStringBuffer(threadId).c_str())
  677. #endif
  678. #if !defined(EAThreadSysThreadIdToString)
  679. #define EAThreadSysThreadIdToString(sysThreadId) (EA::Thread::detail::SysThreadIdToStringBuffer(sysThreadId).c_str())
  680. #endif
  681. ///////////////////////////////////////////////////////////////////////////////
  682. // Inline functions
  683. ///////////////////////////////////////////////////////////////////////////////
  684. #if defined(EA_PLATFORM_MICROSOFT) && !EA_POSIX_THREADS_AVAILABLE
  685. // We implement GetSysThreadId in our associated .cpp file.
  686. #elif defined(EA_PLATFORM_SONY)
  687. // We implement GetSysThreadId in our associated .cpp file.
  688. #elif defined(EA_PLATFORM_APPLE)
  689. // We implement GetSysThreadId in our associated .cpp file.
  690. #elif EA_USE_CPP11_CONCURRENCY
  691. // We implement GetSysThreadId in our associated .cpp file.
  692. #else
  693. inline EA::Thread::SysThreadId EA::Thread::GetSysThreadId(ThreadId id)
  694. {
  695. return id;
  696. }
  697. inline EA::Thread::SysThreadId EA::Thread::GetSysThreadId()
  698. {
  699. return GetThreadId(); // ThreadId == SysThreadId in this case
  700. }
  701. #endif
  702. #endif // EATHREAD_EATHREAD_H