#ifndef __TBB_malloc_Synchronize_H_
#define __TBB_malloc_Synchronize_H_
#include "oneapi/tbb/detail/_utils.h"
#include <atomic>
class MallocMutex : tbb::detail::no_copy {
std::atomic_flag m_flag = ATOMIC_FLAG_INIT;
void lock() {
tbb::detail::atomic_backoff backoff;
while (m_flag.test_and_set()) backoff.pause();
}
bool try_lock() {
return !m_flag.test_and_set();
}
void unlock() {
m_flag.clear(std::memory_order_release);
}
public:
class scoped_lock : tbb::detail::no_copy {
MallocMutex& m_mutex;
bool m_taken;
public:
scoped_lock(MallocMutex& m) : m_mutex(m), m_taken(true) {
m.lock();
}
scoped_lock(MallocMutex& m, bool block, bool *locked) : m_mutex(m), m_taken(false) {
if (block) {
m.lock();
m_taken = true;
} else {
m_taken = m.try_lock();
}
if (locked) *locked = m_taken;
}
~scoped_lock() {
if (m_taken) {
m_mutex.unlock();
}
}
};
friend class scoped_lock;
};
inline void SpinWaitWhileEq(const std::atomic<intptr_t>& location, const intptr_t value) {
tbb::detail::spin_wait_while_eq(location, value);
}
#if USE_PTHREAD && __TBB_SOURCE_DIRECTLY_INCLUDED
inline void SpinWaitUntilEq(const std::atomic<intptr_t>& location, const intptr_t value) {
tbb::detail::spin_wait_until_eq(location, value);
}
#endif
class AtomicBackoff {
tbb::detail::atomic_backoff backoff;
public:
AtomicBackoff() {}
void pause() { backoff.pause(); }
};
#endif