eathread.cpp 5.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254
  1. ///////////////////////////////////////////////////////////////////////////////
  2. // Copyright (c) Electronic Arts Inc. All rights reserved.
  3. ///////////////////////////////////////////////////////////////////////////////
  4. #include <eathread/internal/config.h>
  5. #include <eathread/eathread.h>
  6. #include <stdarg.h>
  7. #include <stdio.h>
  8. namespace EA
  9. {
  10. namespace Thread
  11. {
  12. EA::Thread::Allocator* gpAllocator = NULL;
  13. EATHREADLIB_API void SetAllocator(Allocator* pEAThreadAllocator)
  14. {
  15. gpAllocator = pEAThreadAllocator;
  16. }
  17. EATHREADLIB_API Allocator* GetAllocator()
  18. {
  19. return gpAllocator;
  20. }
  21. // Currently we take advantage of the fact that ICoreAllocator
  22. // is a binary mapping to EA::Thread::Allocator.
  23. // To do: We need to come up with a better solution that this,
  24. // as it is not future-safe and not even guaranteed to
  25. // be portable. The problem is that we can't make this
  26. // package dependent on the CoreAllocator package without
  27. // breaking users who aren't using it.
  28. EATHREADLIB_API void SetAllocator(EA::Allocator::ICoreAllocator* pCoreAllocator)
  29. {
  30. gpAllocator = (EA::Thread::Allocator*)(uintptr_t)pCoreAllocator;
  31. }
  32. EATHREADLIB_API void SetThreadAffinityMask(ThreadAffinityMask nAffinityMask)
  33. {
  34. EA::Thread::SetThreadAffinityMask(GetThreadId(), nAffinityMask);
  35. }
  36. EATHREADLIB_API ThreadAffinityMask GetThreadAffinityMask()
  37. {
  38. return GetThreadAffinityMask(GetThreadId());
  39. }
  40. }
  41. }
  42. #if !EA_THREADS_AVAILABLE
  43. // Do nothing
  44. #elif EA_USE_CPP11_CONCURRENCY
  45. #include "cpp11/eathread_cpp11.cpp"
  46. #elif defined(EA_PLATFORM_SONY)
  47. #include "kettle/eathread_kettle.cpp"
  48. #elif defined(EA_PLATFORM_UNIX) || EA_POSIX_THREADS_AVAILABLE
  49. #include "unix/eathread_unix.cpp"
  50. #elif defined(EA_PLATFORM_MICROSOFT)
  51. #include "pc/eathread_pc.cpp"
  52. #endif
  53. namespace EA
  54. {
  55. namespace Thread
  56. {
  57. namespace detail
  58. {
  59. #if !defined(EAThreadIdToString_CUSTOM_IMPLEMENTATION)
  60. ThreadIdToStringBuffer::ThreadIdToStringBuffer(EA::Thread::ThreadId threadId)
  61. {
  62. sprintf(mBuf, "%d", (int)(intptr_t)threadId);
  63. }
  64. SysThreadIdToStringBuffer::SysThreadIdToStringBuffer(EA::Thread::SysThreadId sysThreadId)
  65. {
  66. sprintf(mBuf, "%d", (int)(intptr_t)sysThreadId);
  67. }
  68. #endif
  69. }
  70. }
  71. }
  72. #if defined(EA_PLATFORM_ANDROID)
  73. #if EATHREAD_C11_ATOMICS_AVAILABLE == 0
  74. #include "android/eathread_fake_atomic_64.cpp"
  75. #endif
  76. #endif
  77. #if !defined(EAT_ASSERT_SNPRINTF)
  78. #if defined(EA_PLATFORM_MICROSOFT)
  79. #define EAT_ASSERT_SNPRINTF _vsnprintf
  80. #else
  81. #define EAT_ASSERT_SNPRINTF snprintf
  82. #endif
  83. #endif
  84. void EA::Thread::AssertionFailureV(const char* pFormat, ...)
  85. {
  86. const size_t kBufferSize = 512;
  87. char buffer[kBufferSize];
  88. va_list arguments;
  89. va_start(arguments, pFormat);
  90. const int nReturnValue = EAT_ASSERT_SNPRINTF(buffer, kBufferSize, pFormat, arguments);
  91. va_end(arguments);
  92. if(nReturnValue > 0)
  93. {
  94. buffer[kBufferSize - 1] = 0;
  95. AssertionFailure(buffer);
  96. }
  97. }
  98. ///////////////////////////////////////////////////////////////////////////////
  99. // non-threaded implementation
  100. ///////////////////////////////////////////////////////////////////////////////
  101. #if !EA_THREADS_AVAILABLE
  102. #include <stdio.h>
  103. #if defined(EA_PLATFORM_UNIX) || EA_POSIX_THREADS_AVAILABLE
  104. #include <sched.h>
  105. #include <sys/time.h>
  106. #elif defined(EA_PLATFORM_WINDOWS)
  107. extern "C" __declspec(dllimport) void __stdcall Sleep(unsigned long dwMilliseconds);
  108. #endif
  109. namespace EA
  110. {
  111. namespace Thread
  112. {
  113. // Assertion variables.
  114. EA::Thread::AssertionFailureFunction gpAssertionFailureFunction = NULL;
  115. void* gpAssertionFailureContext = NULL;
  116. }
  117. }
  118. EA::Thread::ThreadId EA::Thread::GetThreadId()
  119. {
  120. return 1;
  121. }
  122. int EA::Thread::GetThreadPriority()
  123. {
  124. return kThreadPriorityDefault;
  125. }
  126. bool EA::Thread::SetThreadPriority(int nPriority)
  127. {
  128. return true;
  129. }
  130. void* EA::Thread::GetThreadStackBase()
  131. {
  132. return NULL;
  133. }
  134. void EA::Thread::SetThreadProcessor(int /*nProcessor*/)
  135. {
  136. }
  137. int EA::Thread::GetThreadProcessor()
  138. {
  139. return 0;
  140. }
  141. int EA::Thread::GetProcessorCount()
  142. {
  143. return 1;
  144. }
  145. void EA::Thread::ThreadSleep(const ThreadTime& timeRelative)
  146. {
  147. #if defined(EA_PLATFORM_WINDOWS)
  148. // There is no nanosleep on Windows, but there is Sleep.
  149. if(timeRelative == kTimeoutImmediate)
  150. Sleep(0);
  151. else
  152. Sleep((unsigned)((timeRelative.tv_sec * 1000) + (((timeRelative.tv_nsec % 1000) * 1000000))));
  153. #elif defined(EA_PLATFORM_UNIX) || EA_POSIX_THREADS_AVAILABLE
  154. if(timeRelative == kTimeoutImmediate)
  155. sched_yield();
  156. else
  157. nanosleep(&timeRelative, 0);
  158. #endif
  159. }
  160. void EA::Thread::ThreadEnd(intptr_t /*threadReturnValue*/)
  161. {
  162. // We could possibly call exit here.
  163. }
  164. EA::Thread::ThreadTime EA::Thread::GetThreadTime()
  165. {
  166. #if defined(EA_PLATFORM_WINDOWS)
  167. return (ThreadTime)GetTickCount();
  168. #elif defined(EA_PLATFORM_UNIX) || EA_POSIX_THREADS_AVAILABLE
  169. #if defined(EA_PLATFORM_LINUX) || defined(__CYGWIN__) || (_POSIX_TIMERS > 0)
  170. ThreadTime threadTime;
  171. clock_gettime(CLOCK_REALTIME, &threadTime); // If you get a linker error about clock_getttime, you need to link librt.a (specify -lrt to the linker).
  172. return threadTime;
  173. #else
  174. timeval temp;
  175. gettimeofday(&temp, NULL);
  176. return ThreadTime(temp.tv_sec, temp.tv_usec * 1000);
  177. #endif
  178. #endif
  179. }
  180. void EA::Thread::SetAssertionFailureFunction(EA::Thread::AssertionFailureFunction pAssertionFailureFunction, void* pContext)
  181. {
  182. gpAssertionFailureFunction = pAssertionFailureFunction;
  183. gpAssertionFailureContext = pContext;
  184. }
  185. void EA::Thread::AssertionFailure(const char* pExpression)
  186. {
  187. if(gpAssertionFailureFunction)
  188. gpAssertionFailureFunction(pExpression, gpAssertionFailureContext);
  189. else
  190. {
  191. #if EAT_ASSERT_ENABLED
  192. printf("EA::Thread::AssertionFailure: %s\n", pExpression);
  193. #endif
  194. }
  195. }
  196. #endif // EA_THREADS_AVAILABLE