cycle_ptr
control.h
1 #ifndef CYCLE_PTR_DETAIL_CONTROL_H
2 #define CYCLE_PTR_DETAIL_CONTROL_H
3 
4 #include <cassert>
5 #include <cstdint>
6 #include <memory>
7 #include <type_traits>
8 #include <utility>
9 #include <cycle_ptr/detail/base_control.h>
10 #include <cycle_ptr/detail/generation.h>
11 
12 namespace cycle_ptr::detail {
13 
14 
23 template<typename T, typename Alloc>
24 class control final
25 : public base_control,
26  private Alloc
27 {
28  using alloc_traits = std::allocator_traits<Alloc>;
29  using control_alloc_t = typename alloc_traits::template rebind_alloc<control>;
30  using control_alloc_traits_t = typename alloc_traits::template rebind_traits<control>;
31 
32  static_assert(std::is_same_v<typename alloc_traits::value_type, T>,
33  "Alloc must be allocator of T.");
34 
35  control(const control&) = delete;
36 
37  public:
40  control(Alloc alloc)
41  : Alloc(std::move(alloc))
42  {}
43 
51  template<typename... Args>
52  auto instantiate(Args&&... args)
53  -> T* {
54  assert(this->under_construction);
55 
56  publisher pub{ reinterpret_cast<void*>(&store_), sizeof(store_), *this };
57  new (reinterpret_cast<void*>(&store_)) T(std::forward<Args>(args)...); // May throw.
58 
59  // Clear construction flag after construction completes successfully.
60  this->under_construction = false;
61 
62  return reinterpret_cast<T*>(&store_);
63  }
64 
65  private:
69  auto clear_data_()
70  noexcept
71  -> void override {
72  assert(!this->under_construction);
73  reinterpret_cast<T*>(&store_)->~T();
74  }
75 
78  auto get_deleter_() const
79  noexcept
80  -> void (*)(base_control* bc) noexcept override {
81  return &deleter_impl_;
82  }
83 
86  static auto deleter_impl_(base_control* bc)
87  noexcept
88  -> void {
89  assert(bc != nullptr);
90 #ifdef NDEBUG
91  control* ptr = static_cast<control*>(bc);
92 #else
93  control* ptr = dynamic_cast<control*>(bc);
94  assert(ptr != nullptr);
95 #endif
96 
97  control_alloc_t alloc = std::move(*ptr);
98  control_alloc_traits_t::destroy(alloc, ptr);
99  control_alloc_traits_t::deallocate(alloc, ptr, 1);
100  }
101 
103  std::aligned_storage_t<sizeof(T), alignof(T)> store_;
104 };
105 
106 
107 } /* namespace cycle_ptr::detail */
108 
109 #endif /* CYCLE_PTR_DETAIL_CONTROL_H */
control(Alloc alloc)
Create control block.
Definition: control.h:40
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
base_control()
Default constructor allocates a new generation.
auto instantiate(Args &&... args) -> T *
Instantiate the object managed by this control block.
Definition: control.h:52
Control block implementation for given type and allocator combination.
Definition: control.h:24
Base class for all control blocks.
Definition: base_control.h:30