mijin2/source/mijin/util/bitarray.hpp

76 lines
1.6 KiB
C++

#pragma once
#if !defined(MIJIN_UTIL_BITARRAY_HPP_INCLUDED)
#define MIJIN_UTIL_BITARRAY_HPP_INCLUDED 1
#include <array>
#include <atomic>
#include <cstddef>
namespace mijin
{
//
// public defines
//
//
// public constants
//
//
// public types
//
template<std::size_t numBits, bool threadSafe = false>
struct BitArray
{
private:
using byte_type = std::conditional_t<threadSafe, std::atomic_uint8_t, std::uint8_t>;
std::array<byte_type, (numBits + 7) / 8> bytes;
public:
[[nodiscard]] bool get(std::size_t index) const
{
MIJIN_ASSERT(index < numBits, "BitArray: index out of range.");
return (bytes[index / 8] & (1 << (index % 8)));
}
void set(std::size_t index, bool value)
{
byte_type& byte = bytes[index / 8];
const std::uint8_t mask = (1 << (index % 8));
if constexpr (threadSafe)
{
std::uint8_t oldByte = byte.load(std::memory_order_relaxed);
std::uint8_t newByte = 0;
do
{
if (value) {
newByte = oldByte | mask;
}
else {
newByte = oldByte & ~mask;
}
} while (!byte.compare_exchange_weak(oldByte, newByte, std::memory_order_release, std::memory_order_relaxed));
}
else
{
if (value) {
byte |= mask;
}
else {
byte &= ~mask;
}
}
}
};
//
// public functions
//
} // namespace mijin
#endif // !defined(MIJIN_UTIL_BITARRAY_HPP_INCLUDED)