AK+Kernel: Use requires expression when invoking ref counting hooks

Replace some old-school template trickery with C++20 requires. :^)
This commit is contained in:
Andreas Kling 2022-01-08 15:15:55 +01:00
parent ec74afdb8d
commit c4a0f01b02
Notes: sideshowbarker 2024-07-17 21:25:50 +09:00
3 changed files with 22 additions and 62 deletions

View file

@ -18,32 +18,6 @@
namespace AK {
template<class T>
constexpr auto call_will_be_destroyed_if_present(const T* object) -> decltype(const_cast<T*>(object)->will_be_destroyed(), TrueType {})
{
const_cast<T*>(object)->will_be_destroyed();
return {};
}
// NOLINTNEXTLINE(cert-dcl50-cpp) variadic argument used to implement "is detected" pattern
constexpr auto call_will_be_destroyed_if_present(...) -> FalseType
{
return {};
}
template<class T>
constexpr auto call_one_ref_left_if_present(const T* object) -> decltype(const_cast<T*>(object)->one_ref_left(), TrueType {})
{
const_cast<T*>(object)->one_ref_left();
return {};
}
// NOLINTNEXTLINE(cert-dcl50-cpp) variadic argument used to implement "is detected" pattern
constexpr auto call_one_ref_left_if_present(...) -> FalseType
{
return {};
}
class RefCountedBase {
AK_MAKE_NONCOPYABLE(RefCountedBase);
AK_MAKE_NONMOVABLE(RefCountedBase);
@ -87,13 +61,17 @@ class RefCounted : public RefCountedBase {
public:
bool unref() const
{
auto const* that = static_cast<T const*>(this);
auto new_ref_count = deref_base();
if (new_ref_count == 0) {
call_will_be_destroyed_if_present(static_cast<const T*>(this));
if constexpr (requires { that->will_be_destroyed(); })
that->will_be_destroyed();
delete static_cast<const T*>(this);
return true;
} else if (new_ref_count == 1) {
call_one_ref_left_if_present(static_cast<const T*>(this));
if constexpr (requires { that->one_ref_left(); })
that->one_ref_left();
}
return false;
}

View file

@ -25,10 +25,12 @@ class ListedRefCounted : public RefCountedBase {
public:
bool unref() const
{
auto const* that = static_cast<T const*>(this);
auto callback = [&](auto& list) {
auto new_ref_count = deref_base();
if (new_ref_count == 0)
list.remove(const_cast<T&>(static_cast<T const&>(*this)));
list.remove(const_cast<T&>(*that));
return new_ref_count;
};
@ -38,10 +40,12 @@ public:
else if constexpr (Lock == LockType::Mutex)
new_ref_count = T::all_instances().with_exclusive(callback);
if (new_ref_count == 0) {
call_will_be_destroyed_if_present(static_cast<const T*>(this));
delete const_cast<T*>(static_cast<T const*>(this));
if constexpr (requires { that->will_be_destroyed(); })
that->will_be_destroyed();
delete that;
} else if (new_ref_count == 1) {
call_one_ref_left_if_present(static_cast<T const*>(this));
if constexpr (requires { that->one_ref_left(); })
that->one_ref_left();
}
return new_ref_count == 0;
}

View file

@ -15,32 +15,6 @@
namespace AK {
template<class T>
constexpr auto call_will_be_destroyed_if_present(const T* object) -> decltype(const_cast<T*>(object)->will_be_destroyed(), TrueType {})
{
const_cast<T*>(object)->will_be_destroyed();
return {};
}
// NOLINTNEXTLINE(cert-dcl50-cpp) variadic argument used to implement "is detected" pattern
constexpr auto call_will_be_destroyed_if_present(...) -> FalseType
{
return {};
}
template<class T>
constexpr auto call_one_ref_left_if_present(const T* object) -> decltype(const_cast<T*>(object)->one_ref_left(), TrueType {})
{
const_cast<T*>(object)->one_ref_left();
return {};
}
// NOLINTNEXTLINE(cert-dcl50-cpp) variadic argument used to implement "is detected" pattern
constexpr auto call_one_ref_left_if_present(...) -> FalseType
{
return {};
}
class RefCountedBase {
AK_MAKE_NONCOPYABLE(RefCountedBase);
AK_MAKE_NONMOVABLE(RefCountedBase);
@ -95,14 +69,18 @@ class RefCounted : public RefCountedBase {
public:
bool unref() const
{
auto const* that = static_cast<T const*>(this);
auto new_ref_count = deref_base();
if (new_ref_count == 0) {
call_will_be_destroyed_if_present(static_cast<const T*>(this));
delete static_cast<const T*>(this);
if constexpr (requires { that->will_be_destroyed(); })
that->will_be_destroyed();
delete that;
return true;
}
if (new_ref_count == 1)
call_one_ref_left_if_present(static_cast<const T*>(this));
if (new_ref_count == 1) {
if constexpr (requires { that->one_ref_left(); })
that->one_ref_left();
}
return false;
}
};