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::reclamation::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  [[nodiscard]] T* get() const noexcept { return ptr.get(); }
20 
21  // Get mark bits
22  [[nodiscard]] uintptr_t mark() const noexcept { return ptr.mark(); }
23 
24  operator MarkedPtr() const noexcept { return ptr; } // NOLINT (explicit)
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  std::swap(ptr, g.ptr);
38  self().do_swap(g);
39  }
40 
41 protected:
42  // NOLINTNEXTLINE (explicit-constructor)
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 } // namespace xenium::reclamation::detail
52 
53 #endif