mirror of
https://github.com/RGBCube/serenity
synced 2025-05-14 05:14:59 +00:00
AK+Everywhere: Move custom deleter capability to OwnPtr
`OwnPtrWithCustomDeleter` was a decorator which provided the ability to add a custom deleter to `OwnPtr` by wrapping and taking the deleter as a run-time argument to the constructor. This solution means that no additional space is needed for the `OwnPtr` because it doesn't need to store a pointer to the deleter, but comes at the cost of having an extra type that stores a pointer for every instance. This logic is moved directly into `OwnPtr` by adding a template argument that is defaulted to the default deleter for the type. This means that the type itself stores the pointer to the deleter instead of every instance and adds some type safety by encoding the deleter in the type itself instead of taking a run-time argument.
This commit is contained in:
parent
53133b4359
commit
f2336d0144
12 changed files with 74 additions and 63 deletions
35
AK/DefaultDelete.h
Normal file
35
AK/DefaultDelete.h
Normal file
|
@ -0,0 +1,35 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2022, the SerenityOS developers.
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: BSD-2-Clause
|
||||||
|
*/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
namespace AK {
|
||||||
|
|
||||||
|
template<class T>
|
||||||
|
struct DefaultDelete {
|
||||||
|
constexpr DefaultDelete() = default;
|
||||||
|
|
||||||
|
constexpr void operator()(T* t)
|
||||||
|
{
|
||||||
|
delete t;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
template<class T>
|
||||||
|
struct DefaultDelete<T[]> {
|
||||||
|
constexpr DefaultDelete() = default;
|
||||||
|
|
||||||
|
constexpr void operator()(T* t)
|
||||||
|
{
|
||||||
|
delete[] t;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef USING_AK_GLOBALLY
|
||||||
|
using AK::DefaultDelete;
|
||||||
|
#endif
|
|
@ -6,6 +6,7 @@
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#include <AK/DefaultDelete.h>
|
||||||
#include <AK/Types.h>
|
#include <AK/Types.h>
|
||||||
|
|
||||||
namespace AK {
|
namespace AK {
|
||||||
|
@ -133,7 +134,7 @@ class LockRefPtr;
|
||||||
template<typename T>
|
template<typename T>
|
||||||
class RefPtr;
|
class RefPtr;
|
||||||
|
|
||||||
template<typename T>
|
template<typename T, typename TDeleter = DefaultDelete<T>>
|
||||||
class OwnPtr;
|
class OwnPtr;
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
|
|
|
@ -16,8 +16,6 @@
|
||||||
|
|
||||||
namespace AK {
|
namespace AK {
|
||||||
|
|
||||||
template<typename T>
|
|
||||||
class OwnPtr;
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
class RefPtr;
|
class RefPtr;
|
||||||
|
|
||||||
|
|
|
@ -7,6 +7,7 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <AK/Error.h>
|
#include <AK/Error.h>
|
||||||
|
#include <AK/Forward.h>
|
||||||
#include <AK/NonnullOwnPtr.h>
|
#include <AK/NonnullOwnPtr.h>
|
||||||
#include <AK/RefCounted.h>
|
#include <AK/RefCounted.h>
|
||||||
|
|
||||||
|
@ -14,7 +15,7 @@
|
||||||
|
|
||||||
namespace AK {
|
namespace AK {
|
||||||
|
|
||||||
template<typename T>
|
template<typename T, typename TDeleter>
|
||||||
class [[nodiscard]] OwnPtr {
|
class [[nodiscard]] OwnPtr {
|
||||||
public:
|
public:
|
||||||
OwnPtr() = default;
|
OwnPtr() = default;
|
||||||
|
@ -105,7 +106,7 @@ public:
|
||||||
|
|
||||||
void clear()
|
void clear()
|
||||||
{
|
{
|
||||||
delete m_ptr;
|
TDeleter {}(m_ptr);
|
||||||
m_ptr = nullptr;
|
m_ptr = nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,41 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright (c) 2022, Lucas Chollet <lucas.chollet@free.fr>
|
|
||||||
*
|
|
||||||
* SPDX-License-Identifier: BSD-2-Clause
|
|
||||||
*/
|
|
||||||
|
|
||||||
#pragma once
|
|
||||||
|
|
||||||
#include <AK/Function.h>
|
|
||||||
#include <AK/Noncopyable.h>
|
|
||||||
#include <AK/StdLibExtras.h>
|
|
||||||
|
|
||||||
template<typename T>
|
|
||||||
struct OwnPtrWithCustomDeleter {
|
|
||||||
AK_MAKE_NONCOPYABLE(OwnPtrWithCustomDeleter);
|
|
||||||
|
|
||||||
public:
|
|
||||||
OwnPtrWithCustomDeleter(T* ptr, Function<void(T*)> deleter)
|
|
||||||
: m_ptr(ptr)
|
|
||||||
, m_deleter(move(deleter))
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
OwnPtrWithCustomDeleter(OwnPtrWithCustomDeleter&& other)
|
|
||||||
{
|
|
||||||
swap(m_ptr, other.m_ptr);
|
|
||||||
swap(m_deleter, other.m_deleter);
|
|
||||||
};
|
|
||||||
|
|
||||||
~OwnPtrWithCustomDeleter()
|
|
||||||
{
|
|
||||||
if (m_ptr) {
|
|
||||||
VERIFY(m_deleter);
|
|
||||||
m_deleter(m_ptr);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
|
||||||
T* m_ptr { nullptr };
|
|
||||||
Function<void(T*)> m_deleter {};
|
|
||||||
};
|
|
|
@ -12,6 +12,7 @@
|
||||||
#include <AK/Atomic.h>
|
#include <AK/Atomic.h>
|
||||||
#include <AK/Error.h>
|
#include <AK/Error.h>
|
||||||
#include <AK/Format.h>
|
#include <AK/Format.h>
|
||||||
|
#include <AK/Forward.h>
|
||||||
#include <AK/NonnullRefPtr.h>
|
#include <AK/NonnullRefPtr.h>
|
||||||
#include <AK/StdLibExtras.h>
|
#include <AK/StdLibExtras.h>
|
||||||
#include <AK/Traits.h>
|
#include <AK/Traits.h>
|
||||||
|
@ -19,9 +20,6 @@
|
||||||
|
|
||||||
namespace AK {
|
namespace AK {
|
||||||
|
|
||||||
template<typename T>
|
|
||||||
class OwnPtr;
|
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
class [[nodiscard]] RefPtr {
|
class [[nodiscard]] RefPtr {
|
||||||
template<typename U>
|
template<typename U>
|
||||||
|
|
|
@ -23,9 +23,6 @@
|
||||||
|
|
||||||
namespace AK {
|
namespace AK {
|
||||||
|
|
||||||
template<typename T>
|
|
||||||
class OwnPtr;
|
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
struct LockRefPtrTraits {
|
struct LockRefPtrTraits {
|
||||||
ALWAYS_INLINE static T* as_ptr(FlatPtr bits)
|
ALWAYS_INLINE static T* as_ptr(FlatPtr bits)
|
||||||
|
|
|
@ -21,8 +21,6 @@
|
||||||
|
|
||||||
namespace AK {
|
namespace AK {
|
||||||
|
|
||||||
template<typename T>
|
|
||||||
class OwnPtr;
|
|
||||||
template<typename T, typename PtrTraits>
|
template<typename T, typename PtrTraits>
|
||||||
class LockRefPtr;
|
class LockRefPtr;
|
||||||
|
|
||||||
|
|
|
@ -52,6 +52,7 @@ set(AK_TEST_SOURCES
|
||||||
TestNonnullRefPtr.cpp
|
TestNonnullRefPtr.cpp
|
||||||
TestNumberFormat.cpp
|
TestNumberFormat.cpp
|
||||||
TestOptional.cpp
|
TestOptional.cpp
|
||||||
|
TestOwnPtr.cpp
|
||||||
TestPrint.cpp
|
TestPrint.cpp
|
||||||
TestQueue.cpp
|
TestQueue.cpp
|
||||||
TestQuickSort.cpp
|
TestQuickSort.cpp
|
||||||
|
|
23
Tests/AK/TestOwnPtr.cpp
Normal file
23
Tests/AK/TestOwnPtr.cpp
Normal file
|
@ -0,0 +1,23 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2022, the SerenityOS developers.
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: BSD-2-Clause
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <LibTest/TestCase.h>
|
||||||
|
|
||||||
|
#include <AK/OwnPtr.h>
|
||||||
|
|
||||||
|
static u64 deleter_call_count = 0;
|
||||||
|
|
||||||
|
TEST_CASE(should_call_custom_deleter)
|
||||||
|
{
|
||||||
|
auto deleter = [](auto* p) { if (p) ++deleter_call_count; };
|
||||||
|
auto ptr = OwnPtr<u64, decltype(deleter)> {};
|
||||||
|
ptr.clear();
|
||||||
|
EXPECT_EQ(0u, deleter_call_count);
|
||||||
|
ptr = adopt_own_if_nonnull(&deleter_call_count);
|
||||||
|
EXPECT_EQ(0u, deleter_call_count);
|
||||||
|
ptr.clear();
|
||||||
|
EXPECT_EQ(1u, deleter_call_count);
|
||||||
|
}
|
|
@ -1334,11 +1334,7 @@ ErrorOr<AddressInfoVector> getaddrinfo(char const* nodename, char const* servnam
|
||||||
for (auto* result = results; result != nullptr; result = result->ai_next)
|
for (auto* result = results; result != nullptr; result = result->ai_next)
|
||||||
TRY(addresses.try_append(*result));
|
TRY(addresses.try_append(*result));
|
||||||
|
|
||||||
return AddressInfoVector { move(addresses), results,
|
return AddressInfoVector { move(addresses), results };
|
||||||
[](struct addrinfo* ptr) {
|
|
||||||
if (ptr)
|
|
||||||
::freeaddrinfo(ptr);
|
|
||||||
} };
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ErrorOr<void> getsockopt(int sockfd, int level, int option, void* value, socklen_t* value_size)
|
ErrorOr<void> getsockopt(int sockfd, int level, int option, void* value, socklen_t* value_size)
|
||||||
|
|
|
@ -10,7 +10,7 @@
|
||||||
|
|
||||||
#include <AK/Error.h>
|
#include <AK/Error.h>
|
||||||
#include <AK/Noncopyable.h>
|
#include <AK/Noncopyable.h>
|
||||||
#include <AK/OwnPtrWithCustomDeleter.h>
|
#include <AK/OwnPtr.h>
|
||||||
#include <AK/StringView.h>
|
#include <AK/StringView.h>
|
||||||
#include <AK/Vector.h>
|
#include <AK/Vector.h>
|
||||||
#include <dirent.h>
|
#include <dirent.h>
|
||||||
|
@ -226,14 +226,18 @@ public:
|
||||||
private:
|
private:
|
||||||
friend ErrorOr<AddressInfoVector> getaddrinfo(char const* nodename, char const* servname, struct addrinfo const& hints);
|
friend ErrorOr<AddressInfoVector> getaddrinfo(char const* nodename, char const* servname, struct addrinfo const& hints);
|
||||||
|
|
||||||
AddressInfoVector(Vector<struct addrinfo>&& addresses, struct addrinfo* ptr, AK::Function<void(struct addrinfo*)> deleter)
|
AddressInfoVector(Vector<struct addrinfo>&& addresses, struct addrinfo* ptr)
|
||||||
: m_addresses(move(addresses))
|
: m_addresses(move(addresses))
|
||||||
, m_ptr(ptr, move(deleter))
|
, m_ptr(adopt_own_if_nonnull(ptr))
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct AddrInfoDeleter {
|
||||||
|
void operator()(struct addrinfo* ptr) { ::freeaddrinfo(ptr); }
|
||||||
|
};
|
||||||
|
|
||||||
Vector<struct addrinfo> m_addresses {};
|
Vector<struct addrinfo> m_addresses {};
|
||||||
OwnPtrWithCustomDeleter<struct addrinfo> m_ptr;
|
OwnPtr<struct addrinfo, AddrInfoDeleter> m_ptr {};
|
||||||
};
|
};
|
||||||
|
|
||||||
ErrorOr<AddressInfoVector> getaddrinfo(char const* nodename, char const* servname, struct addrinfo const& hints);
|
ErrorOr<AddressInfoVector> getaddrinfo(char const* nodename, char const* servname, struct addrinfo const& hints);
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue