mirror of
https://github.com/RGBCube/serenity
synced 2025-07-28 18:47:44 +00:00
AK+Kernel: Make automatically locking RefPtr & co a kernel-only thing
Some time ago, automatic locking was added to the AK smart pointers to paper over various race conditions in the kernel. Until we've actually solved the issues in the kernel, we're stuck with the locking. However, we don't need to punish single-threaded userspace programs with the high cost of locking. This patch moves the thread-safe variants of RefPtr, NonnullRefPtr, WeakPtr and RefCounted into Kernel/Library/.
This commit is contained in:
parent
ca060d8566
commit
5b1f697460
8 changed files with 1418 additions and 470 deletions
70
AK/WeakPtr.h
70
AK/WeakPtr.h
|
@ -6,7 +6,11 @@
|
|||
|
||||
#pragma once
|
||||
|
||||
#include <AK/Weakable.h>
|
||||
#ifdef KERNEL
|
||||
# include <Kernel/Library/ThreadSafeWeakPtr.h>
|
||||
#else
|
||||
|
||||
# include <AK/Weakable.h>
|
||||
|
||||
namespace AK {
|
||||
|
||||
|
@ -65,21 +69,16 @@ public:
|
|||
}
|
||||
|
||||
template<typename U, typename EnableIf<IsBaseOf<T, U>>::Type* = nullptr>
|
||||
WeakPtr(const RefPtr<U>& object)
|
||||
WeakPtr(RefPtr<U> const& object)
|
||||
{
|
||||
object.do_while_locked([&](U* obj) {
|
||||
if (obj)
|
||||
m_link = obj->template make_weak_ptr<U>().take_link();
|
||||
});
|
||||
if (object)
|
||||
m_link = object->template make_weak_ptr<U>().take_link();
|
||||
}
|
||||
|
||||
template<typename U, typename EnableIf<IsBaseOf<T, U>>::Type* = nullptr>
|
||||
WeakPtr(const NonnullRefPtr<U>& object)
|
||||
WeakPtr(NonnullRefPtr<U> const& object)
|
||||
{
|
||||
object.do_while_locked([&](U* obj) {
|
||||
if (obj)
|
||||
m_link = obj->template make_weak_ptr<U>().take_link();
|
||||
});
|
||||
m_link = object->template make_weak_ptr<U>().take_link();
|
||||
}
|
||||
|
||||
template<typename U, typename EnableIf<IsBaseOf<T, U>>::Type* = nullptr>
|
||||
|
@ -102,61 +101,36 @@ public:
|
|||
template<typename U, typename EnableIf<IsBaseOf<T, U>>::Type* = nullptr>
|
||||
WeakPtr& operator=(const RefPtr<U>& object)
|
||||
{
|
||||
object.do_while_locked([&](U* obj) {
|
||||
if (obj)
|
||||
m_link = obj->template make_weak_ptr<U>().take_link();
|
||||
else
|
||||
m_link = nullptr;
|
||||
});
|
||||
if (object)
|
||||
m_link = object->template make_weak_ptr<U>().take_link();
|
||||
else
|
||||
m_link = nullptr;
|
||||
return *this;
|
||||
}
|
||||
|
||||
template<typename U, typename EnableIf<IsBaseOf<T, U>>::Type* = nullptr>
|
||||
WeakPtr& operator=(const NonnullRefPtr<U>& object)
|
||||
{
|
||||
object.do_while_locked([&](U* obj) {
|
||||
if (obj)
|
||||
m_link = obj->template make_weak_ptr<U>().take_link();
|
||||
else
|
||||
m_link = nullptr;
|
||||
});
|
||||
m_link = object->template make_weak_ptr<U>().take_link();
|
||||
return *this;
|
||||
}
|
||||
|
||||
[[nodiscard]] RefPtr<T> strong_ref() const
|
||||
{
|
||||
// This only works with RefCounted objects, but it is the only
|
||||
// safe way to get a strong reference from a WeakPtr. Any code
|
||||
// that uses objects not derived from RefCounted will have to
|
||||
// use unsafe_ptr(), but as the name suggests, it is not safe...
|
||||
RefPtr<T> ref;
|
||||
// Using do_while_locked protects against a race with clear()!
|
||||
m_link.do_while_locked([&](WeakLink* link) {
|
||||
if (link)
|
||||
ref = link->template strong_ref<T>();
|
||||
});
|
||||
return ref;
|
||||
return RefPtr<T> { ptr() };
|
||||
}
|
||||
|
||||
#ifndef KERNEL
|
||||
// A lot of user mode code is single-threaded. But for kernel mode code
|
||||
// this is generally not true as everything is multi-threaded. So make
|
||||
// these shortcuts and aliases only available to non-kernel code.
|
||||
T* ptr() const { return unsafe_ptr(); }
|
||||
T* operator->() { return unsafe_ptr(); }
|
||||
const T* operator->() const { return unsafe_ptr(); }
|
||||
operator const T*() const { return unsafe_ptr(); }
|
||||
operator T*() { return unsafe_ptr(); }
|
||||
#endif
|
||||
|
||||
[[nodiscard]] T* unsafe_ptr() const
|
||||
{
|
||||
T* ptr = nullptr;
|
||||
m_link.do_while_locked([&](WeakLink* link) {
|
||||
if (link)
|
||||
ptr = link->unsafe_ptr<T>();
|
||||
});
|
||||
return ptr;
|
||||
if (m_link)
|
||||
return m_link->template unsafe_ptr<T>();
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
operator bool() const { return m_link ? !m_link->is_null() : false; }
|
||||
|
@ -219,12 +193,7 @@ template<typename T>
|
|||
struct Formatter<WeakPtr<T>> : Formatter<const T*> {
|
||||
void format(FormatBuilder& builder, const WeakPtr<T>& value)
|
||||
{
|
||||
#ifdef KERNEL
|
||||
auto ref = value.strong_ref();
|
||||
Formatter<const T*>::format(builder, ref.ptr());
|
||||
#else
|
||||
Formatter<const T*>::format(builder, value.ptr());
|
||||
#endif
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -240,3 +209,4 @@ WeakPtr<T> try_make_weak_ptr(const T* ptr)
|
|||
}
|
||||
|
||||
using AK::WeakPtr;
|
||||
#endif
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue