105 lines
2.1 KiB
C++
105 lines
2.1 KiB
C++
// Copyright 2009-2021 Intel Corporation
|
|
// SPDX-License-Identifier: Apache-2.0
|
|
|
|
#pragma once
|
|
|
|
#include "platform.h"
|
|
#include "intrinsics.h"
|
|
#include "atomic.h"
|
|
|
|
#define CPU_CACHELINE_SIZE 64
|
|
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())
|
|
{
|
|
_mm_pause();
|
|
_mm_pause();
|
|
}
|
|
|
|
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())
|
|
{
|
|
_mm_pause();
|
|
_mm_pause();
|
|
}
|
|
}
|
|
|
|
public:
|
|
atomic<bool> flag;
|
|
};
|
|
|
|
class PaddedSpinLock : public SpinLock
|
|
{
|
|
private:
|
|
MAYBE_UNUSED char padding[CPU_CACHELINE_SIZE - sizeof(SpinLock)];
|
|
};
|
|
/*! safe mutex lock and unlock helper */
|
|
template<typename Mutex> 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;
|
|
};
|
|
}
|