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
11namespace 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