nf7/common/life.hh
2022-10-10 11:18:34 +09:00

77 lines
1.4 KiB
C++

#pragma once
#include <atomic>
#include <cassert>
#include <memory>
#include "nf7.hh"
namespace nf7 {
template <typename T>
class Life final {
public:
struct Data final {
std::atomic<T*> ptr;
};
class Ref final {
public:
Ref() = default;
Ref(const Life& life) noexcept {
if (!life.data_) {
auto& l = const_cast<Life&>(life);
l.data_ = std::make_shared<Data>();
l.data_->ptr = l.ptr_;
}
data_ = life.data_;
}
Ref(const Ref&) = default;
Ref(Ref&&) = default;
Ref& operator=(const Ref&) = default;
Ref& operator=(Ref&&) = default;
void EnforceAlive() const {
if (!data_->ptr) {
throw nf7::ExpiredException {"target expired"};
}
}
operator bool() const noexcept {
return !!data_->ptr;
}
T& operator*() const noexcept {
assert(data_->ptr);
return *data_->ptr;
}
T* operator->() const noexcept {
return &**this;
}
private:
std::shared_ptr<Data> data_;
};
Life() = delete;
Life(T& target) noexcept : ptr_(&target) {
}
~Life() noexcept {
if (data_) data_->ptr = nullptr;
}
Life(const Life&) = delete;
Life(Life&&) = delete;
Life& operator=(const Life&) = delete;
Life& operator=(Life&&) = delete;
Ref ref() const noexcept { return *this; }
private:
T* const ptr_;
std::shared_ptr<Data> data_;
};
} // namespace nf7