123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105 |
- #pragma once
- #if (IL2CPP_THREADS_PTHREAD || IL2CPP_THREADS_WIN32) && !RUNTIME_TINY
- #include <stdint.h>
- #include <limits.h>
- #include "utils/NonCopyable.h"
- #include "os/WaitStatus.h"
- #include "Baselib.h"
- #include "Cpp/Lock.h"
- #include "utils/dynamic_array.h"
- #if IL2CPP_THREADS_WIN32
- //#include "os/Win32/ThreadImpl.h"
- #else
- //#include "os/Posix/ThreadImpl.h"
- #endif
- namespace il2cpp
- {
- namespace os
- {
- class ThreadImpl;
- ////TODO: generalize this so that it can be used with c++11 condition variables
- class WaitObject : public il2cpp::utils::NonCopyable
- {
- public:
- const uint32_t kNoTimeout = UINT_MAX;
- class ReleaseOnDestroy
- {
- public:
- FORCE_INLINE ReleaseOnDestroy(baselib::Lock& lockReference) : m_LockReference(lockReference) {m_LockReference.Acquire();}
- FORCE_INLINE ~ReleaseOnDestroy() { m_LockReference.Release(); }
- private:
- baselib::Lock& m_LockReference;
- };
- ~WaitObject();
- WaitStatus Wait(bool interruptible = false);
- WaitStatus Wait(uint32_t ms, bool interruptible = false);
- void* GetOSHandle();
- static void LockWaitObjectDeletion();
- static void UnlockWaitObjectDeletion();
- protected:
- enum Type
- {
- kMutex, /// All mutexes are recursive.
- kManualResetEvent,
- kAutoResetEvent,
- kSemaphore
- };
- struct SThreadPairPosix
- {
- SThreadPairPosix(ThreadImpl* _thread, WaitObject* _owner)
- {
- thread = _thread;
- owner = _owner;
- }
- ThreadImpl* thread;
- WaitObject* owner;
- };
- WaitObject(Type type);
- Type m_Type;
- /// Always have to acquire this mutex to touch m_Count.
- baselib::Lock m_Mutex;
- /// Array of threads waiting for this sync primitive
- il2cpp::utils::dynamic_array<SThreadPairPosix> m_WaitingThreads;
- /// "Release" count for the primitive. Means different things depending on the type of primitive
- /// but for all primitives, we wait until this is zero. Semaphores are the only primitive for which
- /// this can go past 1.
- uint32_t m_Count;
- /// Number of threads waiting on this object. This is used to prevent unnecessary signals
- /// on m_Condition.
- uint32_t m_WaitingThreadCount;
- bool HaveWaitingThreads() const { return (m_WaitingThreadCount != 0); }
- void WakeupOneThread() { WakeupThreads(true); }
- void WakeupAllThreads() { WakeupThreads(false); }
- void WakeupThreads(bool wakeupOneThread);
- void ConditionWait(ThreadImpl* thread);
- bool ConditionTimedWait(ThreadImpl* thread, uint32_t timeout);
- void PushThreadToWaitersList(WaitObject* owner, ThreadImpl* thread);
- void PopThreadFromWaitersList(ThreadImpl* thread);
- };
- }
- }
- #endif // (IL2CPP_THREADS_PTHREAD || IL2CPP_THREADS_WIN32) && !RUNTIME_TINY
|