util/DisposablePointer: new class
This commit is contained in:
parent
48d3bd1cca
commit
f5092cb73d
127
src/util/DisposablePointer.hxx
Normal file
127
src/util/DisposablePointer.hxx
Normal file
@ -0,0 +1,127 @@
|
|||||||
|
// SPDX-License-Identifier: BSD-2-Clause
|
||||||
|
// Copyright CM4all GmbH
|
||||||
|
// author: Max Kellermann <mk@cm4all.com>
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <utility>
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A generic object which is owned by somebody who doesn't know how to
|
||||||
|
* dispose of it; to do this, a function pointer for disposing it is
|
||||||
|
* provided. Some implementations may do "delete this", but others
|
||||||
|
* may be allocated from a custom allocator and may need different
|
||||||
|
* ways to dispose of it.
|
||||||
|
*
|
||||||
|
* Unlike std::any, this class does not require the contained object
|
||||||
|
* to be copyable; quite contrary, it is designed to adopt ownership
|
||||||
|
* of the contained value.
|
||||||
|
*/
|
||||||
|
class DisposablePointer {
|
||||||
|
public:
|
||||||
|
using DisposeFunction = void(*)(void *ptr) noexcept;
|
||||||
|
|
||||||
|
private:
|
||||||
|
void *ptr = nullptr;
|
||||||
|
|
||||||
|
DisposeFunction dispose;
|
||||||
|
|
||||||
|
public:
|
||||||
|
DisposablePointer() = default;
|
||||||
|
DisposablePointer(std::nullptr_t) noexcept {}
|
||||||
|
|
||||||
|
DisposablePointer(void *_ptr, DisposeFunction _dispose) noexcept
|
||||||
|
:ptr(_ptr), dispose(_dispose) {}
|
||||||
|
|
||||||
|
DisposablePointer(DisposablePointer &&src) noexcept
|
||||||
|
:ptr(std::exchange(src.ptr, nullptr)), dispose(src.dispose) {}
|
||||||
|
|
||||||
|
~DisposablePointer() noexcept {
|
||||||
|
if (ptr != nullptr)
|
||||||
|
dispose(ptr);
|
||||||
|
}
|
||||||
|
|
||||||
|
DisposablePointer &operator=(DisposablePointer &&other) noexcept {
|
||||||
|
using std::swap;
|
||||||
|
swap(ptr, other.ptr);
|
||||||
|
swap(dispose, other.dispose);
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
operator bool() const noexcept {
|
||||||
|
return ptr != nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
void *get() const noexcept {
|
||||||
|
return ptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
void reset() noexcept {
|
||||||
|
if (ptr != nullptr)
|
||||||
|
dispose(std::exchange(ptr, nullptr));
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
class TypedDisposablePointer : public DisposablePointer {
|
||||||
|
public:
|
||||||
|
template<typename... Args>
|
||||||
|
TypedDisposablePointer(Args&&... args) noexcept
|
||||||
|
:DisposablePointer(std::forward<Args>(args)...) {}
|
||||||
|
|
||||||
|
TypedDisposablePointer(void *_ptr, DisposeFunction _dispose) noexcept;
|
||||||
|
|
||||||
|
TypedDisposablePointer(T *_ptr, DisposeFunction _dispose) noexcept
|
||||||
|
:DisposablePointer(_ptr, _dispose) {}
|
||||||
|
|
||||||
|
T *get() const noexcept {
|
||||||
|
return (T *)DisposablePointer::get();
|
||||||
|
}
|
||||||
|
|
||||||
|
T *operator->() const noexcept {
|
||||||
|
return get();
|
||||||
|
}
|
||||||
|
|
||||||
|
T &operator*() const noexcept {
|
||||||
|
return *get();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
inline DisposablePointer
|
||||||
|
ToNopPointer(const void *ptr) noexcept
|
||||||
|
{
|
||||||
|
/* since the disposer is a no-op, we allow passing a const
|
||||||
|
pointer here; the const_cast is necessary because
|
||||||
|
DisposablePointer wants a non-const pointer */
|
||||||
|
return {const_cast<void *>(ptr), [](void *) noexcept {}};
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
TypedDisposablePointer<T>
|
||||||
|
ToDeletePointer(T *ptr) noexcept
|
||||||
|
{
|
||||||
|
return {ptr, [](void *p) noexcept {
|
||||||
|
T *t = (T *)p;
|
||||||
|
delete t;
|
||||||
|
}};
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
TypedDisposablePointer<T>
|
||||||
|
ToDeleteArray(T *ptr) noexcept
|
||||||
|
{
|
||||||
|
return {ptr, [](void *p) noexcept {
|
||||||
|
T *t = (T *)p;
|
||||||
|
delete[] t;
|
||||||
|
}};
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
TypedDisposablePointer<T>
|
||||||
|
ToDestructPointer(T *ptr) noexcept
|
||||||
|
{
|
||||||
|
return {ptr, [](void *p) noexcept {
|
||||||
|
T *t = (T *)p;
|
||||||
|
t->~T();
|
||||||
|
}};
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user