1 #ifndef CYCLE_PTR_DETAIL_BASE_CONTROL_H 2 #define CYCLE_PTR_DETAIL_BASE_CONTROL_H 10 #include <shared_mutex> 12 #include <cycle_ptr/detail/color.h> 13 #include <cycle_ptr/detail/hazard.h> 14 #include <cycle_ptr/detail/llist.h> 15 #include <cycle_ptr/detail/vertex.h> 16 #include <cycle_ptr/detail/intrusive_ptr.h> 19 template<
typename>
class cycle_allocator;
22 namespace cycle_ptr::detail {
31 :
public link<base_control>
42 assert(bc !=
nullptr);
45 std::uintptr_t old = bc->control_refs_.fetch_add(1u, std::memory_order_acquire);
46 assert(old > 0u && old < UINTPTR_MAX);
55 assert(bc !=
nullptr);
57 std::uintptr_t old = bc->control_refs_.fetch_sub(1u, std::memory_order_release);
60 if (old == 1u) std::invoke(bc->get_deleter_(), bc);
83 return get_color(store_refs_.load(std::memory_order_relaxed)) == color::black;
106 std::uintptr_t old = store_refs_.fetch_add(1u << color_shift, std::memory_order_relaxed);
107 assert(get_color(old) != color::black && get_color(old) != color::red);
117 auto acquire() noexcept ->
void;
132 const std::uintptr_t old = store_refs_.fetch_sub(
134 std::memory_order_release);
135 assert(get_refs(old) > 0u);
137 if (!skip_gc && get_refs(old) == 1u)
gc();
143 auto gc() noexcept ->
void;
149 std::lock_guard<std::mutex> lck{ mtx_ };
157 std::lock_guard<std::mutex> lck{ mtx_ };
158 edges_.erase(edges_.iterator_to(v));
162 virtual auto is_unowned() const noexcept ->
bool;
166 virtual auto clear_data_() noexcept ->
void = 0;
173 virtual auto get_deleter_() const noexcept ->
void (*)(
base_control*) noexcept = 0;
177 std::atomic<std::uintptr_t> store_refs_{ make_refcounter(1u, color::white) };
180 std::atomic<std::uintptr_t> control_refs_{ std::uintptr_t(1) };
182 hazard_ptr<generation> generation_;
186 llist<vertex, vertex> edges_;
218 struct address_range {
225 auto operator==(
const address_range& other)
const 228 return std::tie(addr, len) == std::tie(other.addr, other.len);
232 auto operator!=(
const address_range& other)
const 235 return !(*
this == other);
239 auto operator<(
const address_range& other)
const 242 return addr < other.addr;
264 using map_type = std::map<address_range, base_control*>;
296 static auto singleton_map_() noexcept
297 -> std::tuple<std::shared_mutex&, map_type&>;
300 map_type::const_iterator iter_;
306 return publisher::lookup(addr, len);
Definition: generation.h:19
Internally used datastructure for llist.
Definition: llist.h:15
auto gc() noexcept -> void
Run GC.
friend auto intrusive_ptr_add_ref(base_control *bc) noexcept -> void
Increment reference counter.
Definition: base_control.h:39
static auto lookup(void *addr, std::size_t len) -> intrusive_ptr< base_control >
Perform a lookup, to figure out which control manages the given address range.
Adaptor for collections with member types.
Definition: allocator.h:19
auto release(bool skip_gc=false) noexcept -> void
Release reference counter.
Definition: base_control.h:129
auto push_back(vertex &v) noexcept -> void
Register a vertex.
Definition: base_control.h:146
auto acquire() noexcept -> void
Acquire reference.
bool under_construction
This variable indicates the managed object is under construction.
Definition: base_control.h:204
Address range publisher.
Definition: base_control.h:215
Intrusive pointer.
Definition: intrusive_ptr.h:21
base_control()
Default constructor allocates a new generation.
~base_control() noexcept
Destructor.
~publisher() noexcept
Destructor, unpublishes the range.
static auto publisher_lookup(void *addr, std::size_t len) -> intrusive_ptr< base_control >
Implements publisher lookup based on address range.
Definition: base_control.h:304
static auto unowned_control() -> intrusive_ptr< base_control >
Create a control block that represents no ownership.
friend auto intrusive_ptr_release(base_control *bc) noexcept -> void
Decrement reference counter.
Definition: base_control.h:52
auto acquire_no_red() noexcept -> void
Acquire reference.
Definition: base_control.h:102
Base class for all control blocks.
Definition: base_control.h:30
auto weak_acquire() noexcept -> bool
Used by weak to strong reference promotion.
auto erase(vertex &v) noexcept -> void
Deregister a vertex.
Definition: base_control.h:154
auto expired() const noexcept -> bool
Test if the object managed by this control is expired.
Definition: base_control.h:80
virtual auto is_unowned() const noexcept -> bool
Test if this control block represents an unowned object.