PosixWaitObject.h 2.8 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697
  1. #pragma once
  2. #if IL2CPP_TARGET_POSIX && !RUNTIME_TINY
  3. #include <pthread.h>
  4. #include <stdint.h>
  5. #include <limits.h>
  6. #include "utils/NonCopyable.h"
  7. #include "os/WaitStatus.h"
  8. #if (IL2CPP_USE_POSIX_COND_TIMEDWAIT_REL)
  9. int pthread_cond_timedwait_relative_np(pthread_cond_t *cond, pthread_mutex_t *mutex, const struct timespec *spec);
  10. #endif
  11. namespace il2cpp
  12. {
  13. namespace os
  14. {
  15. class ThreadImpl;
  16. namespace posix
  17. {
  18. const uint32_t kNoTimeout = UINT_MAX;
  19. ////TODO: generalize this so that it can be used with c++11 condition variables
  20. /// Base class for all synchronization primitives when running on POSIX.
  21. ///
  22. /// To support interruption and timeouts for all synchronization primitives (events, mutexes, and
  23. /// semaphores) we implement these primitives ourselves instead of using their standard POSIX/Mach
  24. /// system counterparts. See PosixWaitObject.cpp for an explanation why.
  25. class PosixWaitObject : public il2cpp::utils::NonCopyable
  26. {
  27. public:
  28. ~PosixWaitObject();
  29. WaitStatus Wait(bool interruptible = false);
  30. WaitStatus Wait(uint32_t ms, bool interruptible = false);
  31. /// Cause an ongoing blocking wait on this object to exit and check for pending APCs.
  32. /// If the object is not currently being waited on, will cause the next wait to exit
  33. /// right away and check for APCs. After APCs have been handled, the object will go
  34. /// back to waiting except if the wait timeout has expired.
  35. void InterruptWait();
  36. void* GetOSHandle();
  37. static void LockWaitObjectDeletion();
  38. static void UnlockWaitObjectDeletion();
  39. protected:
  40. enum Type
  41. {
  42. kMutex, /// All mutexes are recursive.
  43. kManualResetEvent,
  44. kAutoResetEvent,
  45. kSemaphore
  46. };
  47. PosixWaitObject(Type type);
  48. Type m_Type;
  49. /// Always have to acquire this mutex to touch m_Count.
  50. pthread_mutex_t m_Mutex;
  51. /// Signal other threads of changes to m_Count.
  52. pthread_cond_t m_Condition;
  53. /// "Release" count for the primitive. Means different things depending on the type of primitive
  54. /// but for all primitives, we wait until this is zero. Semaphores are the only primitive for which
  55. /// this can go past 1.
  56. uint32_t m_Count;
  57. /// Number of threads waiting on this object. This is used to prevent unnecessary signals
  58. /// on m_Condition.
  59. uint32_t m_WaitingThreadCount;
  60. bool HaveWaitingThreads() const { return (m_WaitingThreadCount != 0); }
  61. };
  62. struct AutoLockWaitObjectDeletion
  63. {
  64. AutoLockWaitObjectDeletion() { PosixWaitObject::LockWaitObjectDeletion(); }
  65. ~AutoLockWaitObjectDeletion() { PosixWaitObject::UnlockWaitObjectDeletion(); }
  66. };
  67. }
  68. }
  69. }
  70. #endif // IL2CPP_TARGET_POSIX