DUNE PDELab (git)

polymorphicsmallobject.hh
1// -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*-
2// vi: set et ts=4 sw=2 sts=2:
3#ifndef DUNE_FUNCTIONS_COMMON_POLYMORPHICSMALLOBJECT_HH
4#define DUNE_FUNCTIONS_COMMON_POLYMORPHICSMALLOBJECT_HH
5
6#include <cstddef>
7#include <utility>
8#include <type_traits>
9#include <algorithm>
10
11namespace Dune {
12namespace Functions {
13
14
45template<class Base, size_t bufferSize>
47{
48 // Actual buffer size must be > 0
49 static constexpr std::size_t actualBufferSize = std::max(sizeof(std::byte), bufferSize);
50
51 // Alignment requirement for the buffer. The `Derived` type must have
52 // an alignment requirement that is a divisor of `bufferAlignment`
53 static constexpr std::size_t bufferAlignment = alignof(std::max_align_t);
54
55public:
56
59 p_(nullptr)
60 {}
61
68 template<class Derived,
69 std::enable_if_t<std::is_base_of_v<Base, std::remove_cv_t<
70 std::remove_reference_t<Derived>>>, int> = 0>
71 PolymorphicSmallObject(Derived&& derived)
72 {
73 constexpr bool useBuffer = (sizeof(Derived) <= bufferSize)
74 && (bufferAlignment % alignof(Derived) == 0);
75
76 if constexpr (useBuffer) {
77 p_ = new (&buffer_) Derived(std::forward<Derived>(derived));
78 } else {
79 p_ = new Derived(std::forward<Derived>(derived));
80 }
81 }
82
85 {
86 moveToWrappedObject(std::move(other));
87 }
88
91 {
92 copyToWrappedObject(other);
93 }
94
97 {
98 destroyWrappedObject();
99 }
100
103 {
104 if (&other!=this)
105 {
106 destroyWrappedObject();
107 copyToWrappedObject(other);
108 }
109 return *this;
110 }
111
114 {
115 destroyWrappedObject();
116 moveToWrappedObject(std::move(other));
117 return *this;
118 }
119
121 explicit operator bool() const
122 {
123 return p_;
124 }
125
127 bool bufferUsed() const
128 {
129 return ((void*) (p_) == (void*)(&buffer_));
130 }
131
133 const Base& get() const
134 {
135 return *p_;
136 }
137
139 Base& get()
140 {
141 return *p_;
142 }
143
144private:
145
146 void destroyWrappedObject() noexcept
147 {
148 if (operator bool())
149 {
150 if (bufferUsed())
151 p_->~Base();
152 else
153 delete p_;
154 }
155 }
156
157 void moveToWrappedObject(PolymorphicSmallObject&& other) noexcept
158 {
159 if (other.bufferUsed())
160 p_ = other.p_->move(&buffer_);
161 else
162 {
163 // We don't need to check for &other_!=this, because you can't
164 // have an rvalue to *this and call it's assignment/constructor
165 // at the same time. (Despite trying to shoot yourself in the foot
166 // with std::move explicitly.)
167
168 // Take ownership of allocated object
169 p_ = other.p_;
170
171 // Leave pointer in a clean state to avoid double freeing it.
172 other.p_ = 0;
173 }
174 }
175
176 void copyToWrappedObject(const PolymorphicSmallObject& other)
177 {
178 if (other.bufferUsed())
179 p_ = other.p_->clone(&buffer_);
180 else
181 p_ = other.p_->clone();
182 }
183
184 alignas(bufferAlignment) std::byte buffer_[actualBufferSize];
185 Base* p_;
186};
187
188
189} // namespace Functions
190} // namespace Dune
191
192#endif // DUNE_FUNCTIONS_COMMON_POLYMORPHICSMALLOBJECT_HH
A wrapper providing small object optimization with polymorphic types.
Definition: polymorphicsmallobject.hh:47
const Base & get() const
Obtain reference to stored object.
Definition: polymorphicsmallobject.hh:133
bool bufferUsed() const
Check if object is stored in internal stack buffer.
Definition: polymorphicsmallobject.hh:127
PolymorphicSmallObject(Derived &&derived)
Construct from object.
Definition: polymorphicsmallobject.hh:71
PolymorphicSmallObject(PolymorphicSmallObject &&other) noexcept
Move constructor from other PolymorphicSmallObject.
Definition: polymorphicsmallobject.hh:84
PolymorphicSmallObject & operator=(const PolymorphicSmallObject &other)
Copy assignment from other PolymorphicSmallObject.
Definition: polymorphicsmallobject.hh:102
PolymorphicSmallObject & operator=(PolymorphicSmallObject &&other) noexcept
Move assignment from other PolymorphicSmallObject.
Definition: polymorphicsmallobject.hh:113
PolymorphicSmallObject(const PolymorphicSmallObject &other)
Copy constructor from other PolymorphicSmallObject.
Definition: polymorphicsmallobject.hh:90
~PolymorphicSmallObject()
Destructor.
Definition: polymorphicsmallobject.hh:96
PolymorphicSmallObject()
Default constructor.
Definition: polymorphicsmallobject.hh:58
Base & get()
Obtain mutable reference to stored object.
Definition: polymorphicsmallobject.hh:139
constexpr auto max
Function object that returns the greater of the given values.
Definition: hybridutilities.hh:484
Dune namespace.
Definition: alignedallocator.hh:13
Creative Commons License   |  Legal Statements / Impressum  |  Hosted by TU Dresden  |  generated with Hugo v0.111.3 (Jul 15, 22:36, 2024)