Seastar
High performance C++ framework for concurrent servers
deleter.hh
1/*
2 * This file is open source software, licensed to you under the terms
3 * of the Apache License, Version 2.0 (the "License"). See the NOTICE file
4 * distributed with this work for additional information regarding copyright
5 * ownership. You may not use this file except in compliance with the License.
6 *
7 * You may obtain a copy of the License at
8 *
9 * http://www.apache.org/licenses/LICENSE-2.0
10 *
11 * Unless required by applicable law or agreed to in writing,
12 * software distributed under the License is distributed on an
13 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
14 * KIND, either express or implied. See the License for the
15 * specific language governing permissions and limitations
16 * under the License.
17 */
18/*
19 * Copyright (C) 2014 Cloudius Systems, Ltd.
20 */
21
22#pragma once
23
24#ifndef SEASTAR_MODULE
25#include <cassert>
26#include <cstdint>
27#include <cstdlib>
28#include <new>
29#include <utility>
30#include <seastar/util/modules.hh>
31#endif
32
33namespace seastar {
34
37
51SEASTAR_MODULE_EXPORT
52class deleter final {
53public:
55 struct impl;
56 struct raw_object_tag {};
58private:
59 // if bit 0 set, point to object to be freed directly.
60 impl* _impl = nullptr;
61public:
63 deleter() noexcept = default;
64 deleter(const deleter&) = delete;
66 deleter(deleter&& x) noexcept : _impl(x._impl) { x._impl = nullptr; }
68 explicit deleter(impl* i) noexcept : _impl(i) {}
69 deleter(raw_object_tag, void* object) noexcept
70 : _impl(from_raw_object(object)) {}
73 ~deleter();
74 deleter& operator=(deleter&& x) noexcept;
75 deleter& operator=(deleter&) = delete;
81 deleter share();
83 explicit operator bool() const noexcept { return bool(_impl); }
85 void reset(impl* i) {
86 this->~deleter();
87 new (this) deleter(i);
88 }
92 void append(deleter d);
93private:
94 static bool is_raw_object(impl* i) noexcept {
95 auto x = reinterpret_cast<uintptr_t>(i);
96 return x & 1;
97 }
98 bool is_raw_object() const noexcept {
99 return is_raw_object(_impl);
100 }
101 static void* to_raw_object(impl* i) noexcept {
102 auto x = reinterpret_cast<uintptr_t>(i);
103 return reinterpret_cast<void*>(x & ~uintptr_t(1));
104 }
105 void* to_raw_object() const noexcept {
106 return to_raw_object(_impl);
107 }
108 impl* from_raw_object(void* object) noexcept {
109 auto x = reinterpret_cast<uintptr_t>(object);
110 return reinterpret_cast<impl*>(x | 1);
111 }
112};
113
115struct deleter::impl {
116 unsigned refs = 1;
117 deleter next;
118 impl(deleter next) : next(std::move(next)) {}
119 virtual ~impl() {}
120};
122
123inline
125 if (is_raw_object()) {
126 std::free(to_raw_object());
127 return;
128 }
129 if (_impl && --_impl->refs == 0) {
130 delete _impl;
131 }
132}
133
134inline
135deleter& deleter::operator=(deleter&& x) noexcept {
136 if (this != &x) {
137 this->~deleter();
138 new (this) deleter(std::move(x));
139 }
140 return *this;
141}
142
144template <typename Deleter>
145struct lambda_deleter_impl final : deleter::impl {
146 Deleter del;
147 lambda_deleter_impl(deleter next, Deleter&& del)
148 : impl(std::move(next)), del(std::move(del)) {}
149 virtual ~lambda_deleter_impl() override { del(); }
150};
151
152template <typename Object>
153struct object_deleter_impl final : deleter::impl {
154 Object obj;
155 object_deleter_impl(deleter next, Object&& obj)
156 : impl(std::move(next)), obj(std::move(obj)) {}
157};
158
159template <typename Object>
160inline
161object_deleter_impl<Object>* make_object_deleter_impl(deleter next, Object obj) {
162 return new object_deleter_impl<Object>(std::move(next), std::move(obj));
163}
165
166
167SEASTAR_MODULE_EXPORT_BEGIN
175template <typename Object>
176deleter
177make_deleter(deleter next, Object o) {
178 return deleter(new lambda_deleter_impl<Object>(std::move(next), std::move(o)));
179}
180
186template <typename Object>
188make_deleter(Object o) {
189 return make_deleter(deleter(), std::move(o));
190}
191SEASTAR_MODULE_EXPORT_END
192
194struct free_deleter_impl final : deleter::impl {
195 void* obj;
196 free_deleter_impl(void* obj) : impl(deleter()), obj(obj) {}
197 free_deleter_impl(const free_deleter_impl&) = delete;
198 free_deleter_impl(free_deleter_impl&&) = delete;
199 virtual ~free_deleter_impl() override { std::free(obj); }
200};
202
203inline
204deleter
206 if (!_impl) {
207 return deleter();
208 }
209 if (is_raw_object()) {
210 _impl = new free_deleter_impl(to_raw_object());
211 }
212 ++_impl->refs;
213 return deleter(_impl);
214}
215
216// Appends 'd' to the chain of deleters. Avoids allocation if possible. For
217// performance reasons the current chain should be shorter and 'd' should be
218// longer.
219inline
221 if (!d._impl) {
222 return;
223 }
224 impl* next_impl = _impl;
225 deleter* next_d = this;
226 while (next_impl) {
227 if (next_impl == d._impl) {
228 return; // Already appended
229 }
230 if (is_raw_object(next_impl)) {
231 next_d->_impl = next_impl = new free_deleter_impl(to_raw_object(next_impl));
232 }
233
234 if (next_impl->refs != 1) {
235 next_d->_impl = next_impl = make_object_deleter_impl(deleter(next_impl), std::move(d));
236 return;
237 }
238
239 next_d = &next_impl->next;
240 next_impl = next_d->_impl;
241 }
242 next_d->_impl = d._impl;
243 d._impl = nullptr;
244}
245
246SEASTAR_MODULE_EXPORT_BEGIN
251inline
254 if (!obj) {
255 return deleter();
256 }
257 return deleter(deleter::raw_object_tag(), obj);
258}
259
266inline
268make_free_deleter(deleter next, void* obj) {
269 return make_deleter(std::move(next), [obj] () mutable { std::free(obj); });
270}
271
274template <typename T>
275inline
278 return deleter{make_object_deleter_impl(deleter(), std::move(obj))};
279}
280
283template <typename T>
284inline
287 return deleter{make_object_deleter_impl(std::move(d), std::move(obj))};
288}
289SEASTAR_MODULE_EXPORT_END
290
292
293}
Definition: deleter.hh:52
deleter() noexcept=default
Constructs an empty deleter that does nothing in its destructor.
deleter make_free_deleter(deleter next, void *obj)
Definition: deleter.hh:268
deleter make_object_deleter(T &&obj)
Definition: deleter.hh:277
void append(deleter d)
Definition: deleter.hh:220
deleter make_object_deleter(deleter d, T &&obj)
Definition: deleter.hh:286
deleter make_deleter(Object o)
Definition: deleter.hh:188
~deleter()
Destroys the deleter and carries out the encapsulated action.
Definition: deleter.hh:124
deleter share()
Definition: deleter.hh:205
deleter make_free_deleter(void *obj)
Definition: deleter.hh:253
deleter make_deleter(deleter next, Object o)
Definition: deleter.hh:177
holds the implementation parts of the metrics layer, do not use directly.
Seastar API namespace.
Definition: abort_on_ebadf.hh:26
STL namespace.