22#include <system_error>
25#if defined(__has_feature)
26#if __has_feature(thread_sanitizer)
27#include <sanitizer/tsan_interface.h>
28#define tsan_acquire(addr) __tsan_acquire(addr)
29#define tsan_release(addr) __tsan_release(addr)
31#define tsan_acquire(addr) static_cast<void>(0)
32#define tsan_release(addr) static_cast<void>(0)
35#define tsan_acquire(addr) static_cast<void>(0)
36#define tsan_release(addr) static_cast<void>(0)
41class [[nodiscard]] Defer {
43 template <
typename Func>
44 Defer(Func &&func) : func_(std::forward<Func>(func)) {}
47 Defer(
const Defer &) =
delete;
48 Defer &operator=(
const Defer &) =
delete;
49 Defer(Defer &&) =
delete;
50 Defer &operator=(Defer &&) =
delete;
53 std::function<void()> func_;
62template <
typename Func> Defer
defer(Func &&func) {
63 return Defer(std::forward<Func>(func));
66template <
typename BaseMutex>
class MaybeMutex :
public BaseMutex {
68 using Base = BaseMutex;
71 void lock() noexcept {
77 void unlock() noexcept {
83 bool try_lock() noexcept {
85 return Base::try_lock();
90 void set_use_mutex(
bool use_mutex)
noexcept { use_mutex_ = use_mutex; }
93 bool use_mutex_ =
false;
96[[noreturn]]
inline void panic_on(std::string_view msg)
noexcept {
97 std::cerr << std::format(
"Panic: {}\n", msg);
102 std::exit(EXIT_FAILURE);
106template <
typename T>
class RawStorage {
108 template <
typename... Args>
void construct(Args &&...args) {
109 new (&storage_) T(std::forward<Args>(args)...);
112 T &get() {
return *
reinterpret_cast<T *
>(&storage_); }
114 const T &get()
const {
return *
reinterpret_cast<const T *
>(&storage_); }
116 void destroy() { get().~T(); }
119 alignas(T)
unsigned char storage_[
sizeof(T)];
122template <
typename T,
size_t N>
class SmallArray {
124 SmallArray(
size_t capacity) : capacity_(capacity) {
126 large_ =
new T[capacity];
136 T &operator[](
size_t index) {
137 return is_small_() ? small_[index] : large_[index];
140 const T &operator[](
size_t index)
const {
141 return is_small_() ? small_[index] : large_[index];
144 size_t capacity()
const {
return capacity_; }
147 bool is_small_()
const {
return capacity_ <= N; }
157inline auto make_system_error(std::string_view msg,
int ec) {
158 return std::system_error(ec, std::generic_category(), std::string(msg));
161template <
typename M,
typename T>
constexpr ptrdiff_t offset_of(M T::*member) {
162 constexpr T *dummy =
nullptr;
163 return reinterpret_cast<ptrdiff_t
>(&(dummy->*member));
166template <
typename M,
typename T> T *container_of(M T::*member, M *ptr) {
167 auto offset = offset_of(member);
169 return reinterpret_cast<T *
>(
reinterpret_cast<intptr_t
>(ptr) - offset);
172template <typename T, T From = 0, T To = std::numeric_limits<T>::max()>
175 static_assert(From < To,
"Invalid ID range");
178 if (!recycled_ids_.empty()) {
179 T
id = recycled_ids_.top();
186 throw std::runtime_error(
"ID pool exhausted");
190 assert(From <=
id &&
id < next_id_ &&
id < To);
191 recycled_ids_.push(
id);
196 while (!recycled_ids_.empty()) {
203 std::stack<T> recycled_ids_;
208 void lock() noexcept {
209 bool expected =
false;
210 while (!lock_.compare_exchange_weak(expected,
true,
211 std::memory_order_acquire,
212 std::memory_order_relaxed)) {
214 lock_.wait(
true, std::memory_order_relaxed);
218 void unlock() noexcept {
219 lock_.store(
false, std::memory_order_release);
224 std::atomic_bool lock_ =
false;
The main namespace for the Condy library.
Defer defer(Func &&func)
Defer the execution of a function until the current scope ends.