6 #ifndef XENIUM_HAZARD_POINTER_HPP 
    7 #define XENIUM_HAZARD_POINTER_HPP 
    9 #include <xenium/reclamation/detail/allocation_tracker.hpp> 
   10 #include <xenium/reclamation/detail/concurrent_ptr.hpp> 
   11 #include <xenium/reclamation/detail/deletable_object.hpp> 
   12 #include <xenium/reclamation/detail/guard_ptr.hpp> 
   13 #include <xenium/reclamation/detail/thread_block_list.hpp> 
   15 #include <xenium/acquire_guard.hpp> 
   16 #include <xenium/parameter.hpp> 
   17 #include <xenium/policy.hpp> 
   22 namespace xenium::reclamation {
 
   30   using std::runtime_error::runtime_error;
 
   34   template <
class Strategy, 
class Derived>
 
   35   struct basic_hp_thread_control_block;
 
   37   template <
size_t K_, 
size_t A, 
size_t B, 
template <
class> 
class ThreadControlBlock>
 
   38   struct generic_hp_allocation_strategy {
 
   39     static constexpr 
size_t K = K_;
 
   41     static size_t retired_nodes_threshold() { 
return A * number_of_active_hazard_pointers() + B; }
 
   43     static size_t number_of_active_hazard_pointers() { 
return number_of_active_hps.load(std::memory_order_relaxed); }
 
   45     using thread_control_block = ThreadControlBlock<generic_hp_allocation_strategy>;
 
   48     friend thread_control_block;
 
   49     friend basic_hp_thread_control_block<generic_hp_allocation_strategy, thread_control_block>;
 
   51     inline static std::atomic<size_t> number_of_active_hps{0};
 
   54   template <
class Strategy>
 
   55   struct static_hp_thread_control_block;
 
   57   template <
class Strategy>
 
   58   struct dynamic_hp_thread_control_block;
 
   61 namespace hp_allocation {
 
   72   template <
size_t K = 2, 
size_t A = 2, 
size_t B = 100>
 
   73   struct static_strategy : detail::generic_hp_allocation_strategy<K, A, B, detail::static_hp_thread_control_block> {};
 
   96   template <
size_t K = 2, 
size_t A = 2, 
size_t B = 100>
 
   97   struct dynamic_strategy : detail::generic_hp_allocation_strategy<K, A, B, detail::dynamic_hp_thread_control_block> {};
 
  100 template <
class AllocationStrategy = hp_allocation::static_strategy<3>>
 
  101 struct hazard_pointer_traits {
 
  102   using allocation_strategy = AllocationStrategy;
 
  104   template <
class... Policies>
 
  127 template <
typename Traits = hazard_po
inter_traits<>>
 
  129   using allocation_strategy = 
typename Traits::allocation_strategy;
 
  130   using thread_control_block = 
typename allocation_strategy::thread_control_block;
 
  131   friend detail::basic_hp_thread_control_block<allocation_strategy, thread_control_block>;
 
  133   template <
class T, 
class MarkedPtr>
 
  147   template <
class... Policies>
 
  150   template <
class T, std::
size_t N = 0, 
class Deleter = std::default_delete<T>>
 
  151   class enable_concurrent_ptr;
 
  153   class region_guard {};
 
  155   template <
class T, std::
size_t N = T::number_of_mark_bits>
 
  163   inline static detail::thread_block_list<thread_control_block> global_thread_block_list;
 
  164   inline static thread_local thread_data local_thread_data;
 
  166   ALLOCATION_TRACKING_FUNCTIONS;
 
  169 template <
typename Traits>
 
  170 template <
class T, std::
size_t N, 
class Deleter>
 
  171 class hazard_pointer<Traits>::enable_concurrent_ptr :
 
  172     private detail::deletable_object_impl<T, Deleter>,
 
  173     private detail::tracked_object<hazard_pointer> {
 
  175   static constexpr std::size_t number_of_mark_bits = N;
 
  178   enable_concurrent_ptr() noexcept = default;
 
  179   enable_concurrent_ptr(const enable_concurrent_ptr&) noexcept = default;
 
  180   enable_concurrent_ptr(enable_concurrent_ptr&&) noexcept = default;
 
  181   enable_concurrent_ptr& operator=(const enable_concurrent_ptr&) noexcept = default;
 
  182   enable_concurrent_ptr& operator=(enable_concurrent_ptr&&) noexcept = default;
 
  183   ~enable_concurrent_ptr() noexcept override = default;
 
  186   friend detail::deletable_object_impl<T, Deleter>;
 
  188   template <class, class>
 
  189   friend class guard_ptr;
 
  192 template <typename Traits>
 
  193 template <class T, class MarkedPtr>
 
  194 class hazard_pointer<Traits>::guard_ptr : public detail::guard_ptr<T, MarkedPtr, guard_ptr<T, MarkedPtr>> {
 
  195   using base = detail::guard_ptr<T, MarkedPtr, guard_ptr>;
 
  196   using Deleter = 
typename T::Deleter;
 
  199   guard_ptr() noexcept = default;
 
  202   explicit guard_ptr(const MarkedPtr& p);
 
  203   guard_ptr(const guard_ptr& p);
 
  204   guard_ptr(guard_ptr&& p) noexcept;
 
  206   guard_ptr& operator=(const guard_ptr& p);
 
  207   guard_ptr& operator=(guard_ptr&& p) noexcept;
 
  210   void acquire(const concurrent_ptr<T>& p, std::memory_order order = std::memory_order_seq_cst);
 
  213   bool acquire_if_equal(const concurrent_ptr<T>& p,
 
  214                         const MarkedPtr& expected,
 
  215                         std::memory_order order = std::memory_order_seq_cst);
 
  218   void reset() noexcept;
 
  221   void reclaim(Deleter d = Deleter()) noexcept;
 
  224   using enable_concurrent_ptr = hazard_pointer::enable_concurrent_ptr<T, MarkedPtr::number_of_mark_bits, Deleter>;
 
  227   void do_swap(guard_ptr& g) noexcept;
 
  229   typename thread_control_block::hazard_pointer* hp = 
nullptr;
 
  233 #define HAZARD_POINTER_IMPL 
  234 #include <xenium/reclamation/impl/hazard_pointer.hpp> 
  235 #undef HAZARD_POINTER_IMPL