fish-shell/src/global_safety.h

67 lines
2 KiB
C++
Raw Normal View History

// Support for enforcing correct access to globals.
#ifndef FISH_GLOBAL_SAFETY_H
#define FISH_GLOBAL_SAFETY_H
#include "config.h" // IWYU pragma: keep
#include <atomic>
#include "common.h"
/// A latch variable may only be set once.
/// The value is immortal.
template <typename T>
class latch_t : noncopyable_t, nonmovable_t {
T *value_{};
public:
operator T *() { return value_; }
operator const T *() const { return value_; }
T *operator->() { return value_; }
const T *operator->() const { return value_; }
bool is_set() const { return value_ != nullptr; }
2019-04-29 02:16:55 +00:00
void operator=(std::unique_ptr<T> value) {
assert(value_ == nullptr && "Latch variable initialized multiple times");
assert(value != nullptr && "Latch variable initialized with null");
2019-04-29 02:16:55 +00:00
// Note: deliberate leak.
value_ = value.release();
}
2019-04-29 02:16:55 +00:00
void operator=(T &&value) { *this = make_unique<T>(std::move(value)); }
};
/// An atomic type that always use relaxed reads.
template <typename T>
class relaxed_atomic_t {
std::atomic<T> value_{};
public:
relaxed_atomic_t() = default;
relaxed_atomic_t(T value) : value_(value) {}
operator T() const volatile { return value_.load(std::memory_order_relaxed); }
void operator=(T v) { return value_.store(v, std::memory_order_relaxed); }
void operator=(T v) volatile { return value_.store(v, std::memory_order_relaxed); }
// Perform a CAS operation, returning whether it succeeded.
bool compare_exchange(T expected, T desired) {
return value_.compare_exchange_strong(expected, desired, std::memory_order_relaxed);
}
// postincrement
T operator++(int) { return value_.fetch_add(1, std::memory_order_relaxed); }
T operator--(int) { return value_.fetch_sub(1, std::memory_order_relaxed); }
// preincrement
T operator++() { return value_.fetch_add(1, std::memory_order_relaxed) + 1; }
T operator--() { return value_.fetch_sub(1, std::memory_order_relaxed) - 1; }
};
using relaxed_atomic_bool_t = relaxed_atomic_t<bool>;
#endif