cpp-ipc/include/libipc/spin_lock.h
2022-10-15 18:39:36 +08:00

87 lines
1.5 KiB
C++

/**
* @file libipc/spin_lock.h
* @author mutouyun (orz@orzz.org)
* @brief Define spin locks
* @date 2022-02-27
*/
#pragma once
#include <atomic>
#include <thread>
#include <chrono>
#include <utility>
#include "libimp/export.h"
#include "libipc/def.h"
LIBIPC_NAMESPACE_BEG_
/**
* @brief Gives hint to processor that improves performance of spin-wait loops.
*/
LIBIMP_EXPORT void pause() noexcept;
/**
* @brief Yield to other threads
*/
template <typename K>
inline void yield(K &k) noexcept {
if (k < 4) { /* Do nothing */ }
else
if (k < 16) { pause(); }
else
if (k < 32) { std::this_thread::yield(); }
else {
std::this_thread::sleep_for(std::chrono::milliseconds(1));
return;
}
++k;
}
template <std::size_t N = 32, typename K, typename F>
inline void sleep(K &k, F &&f) {
if (k < static_cast<K>(N)) {
std::this_thread::yield();
}
else {
static_cast<void>(std::forward<F>(f)());
return;
}
++k;
}
template <std::size_t N = 32, typename K>
inline void sleep(K &k) {
sleep<N>(k, [] {
std::this_thread::sleep_for(std::chrono::microseconds(1));
});
}
/**
* @brief Basic spin lock
*/
class LIBIMP_EXPORT spin_lock {
std::atomic<unsigned> lc_ {0};
public:
void lock() noexcept;
void unlock() noexcept;
};
/**
* @brief Support for shared mode spin lock
*/
class LIBIMP_EXPORT rw_lock {
std::atomic<unsigned> lc_ {0};
public:
void lock() noexcept;
void unlock() noexcept;
void lock_shared() noexcept;
void unlock_shared() noexcept;
};
LIBIPC_NAMESPACE_END_