diff options
Diffstat (limited to 'ovr_sdk_win_23.0.0/LibOVRKernel/Src/Kernel/OVR_ThreadsPthread.cpp')
-rw-r--r-- | ovr_sdk_win_23.0.0/LibOVRKernel/Src/Kernel/OVR_ThreadsPthread.cpp | 234 |
1 files changed, 234 insertions, 0 deletions
diff --git a/ovr_sdk_win_23.0.0/LibOVRKernel/Src/Kernel/OVR_ThreadsPthread.cpp b/ovr_sdk_win_23.0.0/LibOVRKernel/Src/Kernel/OVR_ThreadsPthread.cpp new file mode 100644 index 0000000..56fd27c --- /dev/null +++ b/ovr_sdk_win_23.0.0/LibOVRKernel/Src/Kernel/OVR_ThreadsPthread.cpp @@ -0,0 +1,234 @@ +/************************************************************************************ + +Filename : OVR_ThreadsPthread.cpp +Content : +Created : +Notes : + +Copyright : Copyright (c) Facebook Technologies, LLC and its affiliates. All rights reserved. + +Licensed under the Oculus Master SDK License Version 1.0 (the "License"); +you may not use the Oculus VR Rift SDK except in compliance with the License, +which is provided at the time of installation or download, or which +otherwise accompanies this software in either electronic or hard copy form. + +You may obtain a copy of the License at + +https://developer.oculus.com/licenses/oculusmastersdk-1.0 + +Unless required by applicable law or agreed to in writing, the Oculus VR SDK +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. + +************************************************************************************/ + +#if !defined(_WIN32) // Skip the entire file under Windows + +#include "OVR_Threads.h" + +#ifdef OVR_ENABLE_THREADS + +#include <errno.h> +#include <pthread.h> +#include <sched.h> +#include <sys/time.h> +#include <time.h> +#include <unistd.h> +#include "OVR_Timer.h" + +#if defined(OVR_OS_MAC) || defined(OVR_OS_BSD) +#include <sys/param.h> +#include <sys/sysctl.h> +#if !defined(OVR_OS_MAC) +#include <pthread_np.h> +#endif +#endif + +namespace OVR { + +// ***** Mutex implementation + +// *** Internal Mutex implementation structure + +class MutexImpl : public NewOverrideBase { + // System mutex or semaphore + pthread_mutex_t SMutex; + bool Recursive; + unsigned LockCount; + pthread_t LockedBy; + + public: + // Constructor/destructor + MutexImpl(Mutex* pmutex, bool recursive = 1); + ~MutexImpl(); + + // Locking functions + void DoLock(); + bool TryLock(); + void Unlock(Mutex* pmutex); + // Returns 1 if the mutes is currently locked + bool IsLockedByAnotherThread(Mutex* pmutex); + bool IsSignaled() const; +}; + +pthread_mutexattr_t Lock::RecursiveAttr; +bool Lock::RecursiveAttrInit = 0; + +// *** Constructor/destructor +MutexImpl::MutexImpl(Mutex* pmutex, bool recursive) { + OVR_UNUSED(pmutex); + Recursive = recursive; + LockCount = 0; + + if (Recursive) { + if (!Lock::RecursiveAttrInit) { + pthread_mutexattr_init(&Lock::RecursiveAttr); + pthread_mutexattr_settype(&Lock::RecursiveAttr, PTHREAD_MUTEX_RECURSIVE); + Lock::RecursiveAttrInit = 1; + } + + pthread_mutex_init(&SMutex, &Lock::RecursiveAttr); + } else + pthread_mutex_init(&SMutex, 0); +} + +MutexImpl::~MutexImpl() { + pthread_mutex_destroy(&SMutex); +} + +// Lock and try lock +void MutexImpl::DoLock() { + while (pthread_mutex_lock(&SMutex)) + ; + LockCount++; + LockedBy = pthread_self(); +} + +bool MutexImpl::TryLock() { + if (!pthread_mutex_trylock(&SMutex)) { + LockCount++; + LockedBy = pthread_self(); + return 1; + } + + return 0; +} + +void MutexImpl::Unlock(Mutex* pmutex) { + OVR_UNUSED(pmutex); + OVR_ASSERT(pthread_self() == LockedBy && LockCount > 0); + + // unsigned lockCount; + LockCount--; + // lockCount = LockCount; + + pthread_mutex_unlock(&SMutex); +} + +bool MutexImpl::IsLockedByAnotherThread(Mutex* pmutex) { + OVR_UNUSED(pmutex); + // There could be multiple interpretations of IsLocked with respect to current thread + if (LockCount == 0) + return 0; + if (pthread_self() != LockedBy) + return 1; + return 0; +} + +bool MutexImpl::IsSignaled() const { + // An mutex is signaled if it is not locked ANYWHERE + // Note that this is different from IsLockedByAnotherThread function, + // that takes current thread into account + return LockCount == 0; +} + +// *** Actual Mutex class implementation + +// NOTE: RefCount mode already thread-safe for all waitables. +Mutex::Mutex(bool recursive) : pImpl(new MutexImpl(this, recursive)) {} + +Mutex::~Mutex() {} + +// Lock and try lock +void Mutex::DoLock() { + pImpl->DoLock(); +} +bool Mutex::TryLock() { + return pImpl->TryLock(); +} +void Mutex::Unlock() { + pImpl->Unlock(this); +} +bool Mutex::IsLockedByAnotherThread() { + return pImpl->IsLockedByAnotherThread(this); +} + +//----------------------------------------------------------------------------------- +// ***** Event + +bool Event::Wait(unsigned delay) { + std::unique_lock<std::mutex> locker(StateMutex); + + // Do the correct amount of waiting + if (delay == OVR_WAIT_INFINITE) { + while (!State) + StateWaitCondition.wait(locker); + } else if (delay) { + if (!State) + StateWaitCondition.wait_for(locker, std::chrono::milliseconds(delay)); + } + + bool state = State; + // Take care of temporary 'pulsing' of a state + if (Temporary) { + Temporary = false; + State = false; + } + return state; +} + +void Event::updateState(bool newState, bool newTemp, bool mustNotify) { + std::unique_lock<std::mutex> lock(StateMutex); + State = newState; + Temporary = newTemp; + if (mustNotify) { + lock.unlock(); + StateWaitCondition.notify_all(); + } +} + +ThreadId GetCurrentThreadId() { + return (void*)pthread_self(); +} + +// *** Sleep functions + +/* static */ +bool Thread::MSleep(unsigned msecs) { + usleep(msecs * 1000); + return 1; +} + +void Thread::SetCurrentThreadName(const char* name) { +#if defined(OVR_OS_APPLE) + pthread_setname_np(name); +#else + pthread_setname_np(pthread_self(), name); +#endif +} + +void Thread::GetCurrentThreadName(char* name, size_t nameCapacity) { + name[0] = 0; +#if !defined(OVR_OS_ANDROID) + // Android does not have pthread_getname_np (or an equivalent) + pthread_getname_np(pthread_self(), name, nameCapacity); +#endif +} + +} // namespace OVR + +#endif // OVR_ENABLE_THREADS + +#endif // _WIN32 |