xenium
Loading...
Searching...
No Matches
deletable_object.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_DETAIL_DELETABLE_OBJECT_HPP
7#define XENIUM_DETAIL_DELETABLE_OBJECT_HPP
8
9#include <memory>
10#include <type_traits>
11
12#ifdef _MSC_VER
13#pragma warning(push)
14#pragma warning(disable: 26495) // uninitialized member variable
15#endif
16
17namespace xenium { namespace reclamation { namespace detail {
18
19 struct deletable_object
20 {
21 virtual void delete_self() = 0;
22 deletable_object* next = nullptr;
23 protected:
24 virtual ~deletable_object() = default;
25 };
26
27 inline void delete_objects(deletable_object*& list)
28 {
29 auto cur = list;
30 for (deletable_object* next = nullptr; cur != nullptr; cur = next)
31 {
32 next = cur->next;
33 cur->delete_self();
34 }
35 list = nullptr;
36 }
37
38 template <class Derived, class DeleterT, class Base>
39 struct deletable_object_with_non_empty_deleter : Base
40 {
41 using Deleter = DeleterT;
42 virtual void delete_self() override
43 {
44 Deleter& my_deleter = reinterpret_cast<Deleter&>(deleter_buffer);
45 Deleter deleter(std::move(my_deleter));
46 my_deleter.~Deleter();
47
48 deleter(static_cast<Derived*>(this));
49 }
50
51 void set_deleter(Deleter deleter)
52 {
53 new (&deleter_buffer) Deleter(std::move(deleter));
54 }
55
56 private:
57 using buffer = typename std::aligned_storage<sizeof(Deleter), alignof(Deleter)>::type;
58 buffer deleter_buffer;
59 };
60
61 template <class Derived, class DeleterT, class Base>
62 struct deletable_object_with_empty_deleter : Base
63 {
64 using Deleter = DeleterT;
65 virtual void delete_self() override
66 {
67 static_assert(std::is_default_constructible<Deleter>::value, "empty deleters must be default constructible");
68 Deleter deleter{};
69 deleter(static_cast<Derived*>(this));
70 }
71
72 void set_deleter(Deleter /*deleter*/) {}
73 };
74
75 template <class Derived, class Deleter = std::default_delete<Derived>, class Base = deletable_object>
76 using deletable_object_impl = std::conditional_t<std::is_empty<Deleter>::value,
77 deletable_object_with_empty_deleter<Derived, Deleter, Base>,
78 deletable_object_with_non_empty_deleter<Derived, Deleter, Base>
79 >;
80}}}
81
82#ifdef _MSC_VER
83#pragma warning(pop)
84#endif
85
86#endif