xenium
guard_ptr.hpp
1 //
2 // Copyright (c) 2018-2020 Manuel Pöter.
3 // Licensed under the MIT License. See LICENSE file in the project root for full license information.
4 //
5 
6 #ifndef XENIUM_DETAL_GUARD_PTR_HPP
7 #define XENIUM_DETAL_GUARD_PTR_HPP
8 
9 #include <utility>
10 
11 namespace xenium{ namespace reclamation { namespace detail {
12 
13  template <class T, class MarkedPtr, class Derived>
14  class guard_ptr {
15  public:
16  ~guard_ptr() { self().reset(); }
17 
18  // Get underlying pointer
19  T* get() const noexcept { return ptr.get(); }
20 
21  // Get mark bits
22  uintptr_t mark() const noexcept { return ptr.mark(); }
23 
24  operator MarkedPtr() const noexcept { return ptr; }
25 
26  // True if get() != nullptr || mark() != 0
27  explicit operator bool() const noexcept { return static_cast<bool>(ptr); }
28 
29  // Get pointer with mark bits stripped off. Undefined if target has been reclaimed.
30  T* operator->() const noexcept { return ptr.get(); }
31 
32  // Get reference to target of pointer. Undefined if target has been reclaimed.
33  T& operator*() const noexcept { return *ptr; }
34 
35  // Swap two guards
36  void swap(Derived& g) noexcept
37  {
38  std::swap(ptr, g.ptr);
39  self().do_swap(g);
40  }
41 
42  protected:
43  guard_ptr(const MarkedPtr& p = MarkedPtr{}) noexcept : ptr(p) {}
44  MarkedPtr ptr;
45 
46  void do_swap(Derived&) noexcept {} // empty dummy
47 
48  private:
49  Derived& self() { return static_cast<Derived&>(*this); }
50  };
51 }}}
52 
53 #endif