89 lines
2.0 KiB
C++
89 lines
2.0 KiB
C++
#ifndef THWEAVER_ATOMIC_H
|
|
#define THWEAVER_ATOMIC_H
|
|
|
|
#include <cstdint>
|
|
#include <concepts>
|
|
#include <limits>
|
|
#include <type_traits>
|
|
|
|
template <typename T>
|
|
concept Additive = std::is_integral_v<T> && !std::is_same_v<T, bool>;
|
|
|
|
template <typename A, typename T>
|
|
concept AtomicAdditive =
|
|
requires(A a, T v) {
|
|
{
|
|
a.load()
|
|
}
|
|
-> std::same_as<T>;
|
|
{
|
|
a.store(v)
|
|
};
|
|
{
|
|
a.fetch_add(v)
|
|
}
|
|
-> std::same_as<T>;
|
|
{
|
|
a.fetch_sub(v)
|
|
}
|
|
-> std::same_as<T>;
|
|
};
|
|
|
|
template <typename T>
|
|
concept Bitwise =
|
|
(std::is_integral_v<T> || std::is_enum_v<T>) &&
|
|
!std::is_same_v<T, bool>;
|
|
|
|
template <typename A, typename T>
|
|
concept AtomicBitwise =
|
|
requires(A a, T v) {
|
|
{
|
|
a.load()
|
|
}
|
|
-> std::same_as<T>;
|
|
{
|
|
a.store(v)
|
|
};
|
|
{
|
|
a.fetch_or(v)
|
|
}
|
|
-> std::same_as<T>;
|
|
{
|
|
a.fetch_and(v)
|
|
}
|
|
-> std::same_as<T>;
|
|
{
|
|
a.fetch_xor(v)
|
|
}
|
|
-> std::same_as<T>;
|
|
};
|
|
|
|
// Uses the full bitmap
|
|
template<typename Atomic, typename T, uint32_t NumBits, typename Index = uint32_t>
|
|
requires Bitwise<T> && AtomicBitwise<Atomic, T> &&
|
|
Additive<Index> && std::is_unsigned_v<Index>
|
|
class AtomicBitmap {
|
|
public:
|
|
static_assert(NumBits <= std::numeric_limits<T>::digits);
|
|
|
|
AtomicBitmap() noexcept
|
|
: bits(T {}), rotation(0) {}
|
|
|
|
void reset(const T &bits, const Index rotation) noexcept;
|
|
|
|
bool get_bit(const Index n) const noexcept;
|
|
void set_bit(const Index n) noexcept;
|
|
void clear_bit(const Index n) noexcept;
|
|
|
|
void rotate(const Index n) noexcept;
|
|
Index get_rotation() const noexcept;
|
|
|
|
Index get_low_bit() const noexcept;
|
|
Index rotate_to_low_bit(const Index offset = 0) noexcept;
|
|
private:
|
|
Atomic bits;
|
|
Index rotation;
|
|
};
|
|
|
|
#endif
|