// Copyright 2009-2020 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once #include "platform.h" #include "intrinsics.h" #include "atomic.h" namespace embree { /*! system mutex */ class MutexSys { friend struct ConditionImplementation; public: MutexSys(); ~MutexSys(); private: MutexSys (const MutexSys& other) DELETED; // do not implement MutexSys& operator= (const MutexSys& other) DELETED; // do not implement public: void lock(); bool try_lock(); void unlock(); protected: void* mutex; }; /*! spinning mutex */ class SpinLock { public: SpinLock () : flag(false) {} __forceinline bool isLocked() { return flag.load(); } __forceinline void lock() { while (true) { while (flag.load()) { // -- GODOT start -- #if !(defined (__WIN32__) && defined (__MINGW32__)) // -- GODOT end -- _mm_pause(); _mm_pause(); // -- GODOT start -- #else usleep(1); #endif // -- GODOT end -- } bool expected = false; if (flag.compare_exchange_strong(expected,true,std::memory_order_acquire)) break; } } __forceinline bool try_lock() { bool expected = false; if (flag.load() != expected) { return false; } return flag.compare_exchange_strong(expected,true,std::memory_order_acquire); } __forceinline void unlock() { flag.store(false,std::memory_order_release); } __forceinline void wait_until_unlocked() { while(flag.load()) { // -- GODOT start -- #if !(defined (__WIN32__) && defined(__MINGW32__)) // -- GODOT end -- _mm_pause(); _mm_pause(); // -- GODOT start -- #else usleep(1); #endif // -- GODOT end -- } } public: atomic flag; }; /*! safe mutex lock and unlock helper */ template class Lock { public: Lock (Mutex& mutex) : mutex(mutex), locked(true) { mutex.lock(); } Lock (Mutex& mutex, bool locked) : mutex(mutex), locked(locked) {} ~Lock() { if (locked) mutex.unlock(); } __forceinline void lock() { assert(!locked); locked = true; mutex.lock(); } __forceinline bool isLocked() const { return locked; } protected: Mutex& mutex; bool locked; }; }