diff --git a/Kernel/Locking/NonnullRefContendedPtr.h b/Kernel/Locking/NonnullRefContendedPtr.h new file mode 100644 index 0000000000..47ee850805 --- /dev/null +++ b/Kernel/Locking/NonnullRefContendedPtr.h @@ -0,0 +1,17 @@ +/* + * Copyright (c) 2021, the SerenityOS developers. + * + * SPDX-License-Identifier: BSD-2-Clause + */ + +#pragma once + +#include +#include + +namespace Kernel { + +template +using NonnullRefContendedPtr = NonnullRefPtr>; + +} diff --git a/Kernel/Locking/NonnullRefContendedPtrVector.h b/Kernel/Locking/NonnullRefContendedPtrVector.h new file mode 100644 index 0000000000..bb7f2cbf2c --- /dev/null +++ b/Kernel/Locking/NonnullRefContendedPtrVector.h @@ -0,0 +1,17 @@ +/* + * Copyright (c) 2021, the SerenityOS developers. + * + * SPDX-License-Identifier: BSD-2-Clause + */ + +#pragma once + +#include +#include + +namespace Kernel { + +template +using NonnullRefContendedPtrVector = AK::NonnullPtrVector, inline_capacity>; + +} diff --git a/Kernel/Locking/RefContendedPtr.h b/Kernel/Locking/RefContendedPtr.h new file mode 100644 index 0000000000..314406eca9 --- /dev/null +++ b/Kernel/Locking/RefContendedPtr.h @@ -0,0 +1,17 @@ +/* + * Copyright (c) 2021, the SerenityOS developers. + * + * SPDX-License-Identifier: BSD-2-Clause + */ + +#pragma once + +#include +#include + +namespace Kernel { + +template +using RefContendedPtr = RefPtr>; + +} diff --git a/Kernel/Locking/RefCountedContended.h b/Kernel/Locking/RefCountedContended.h new file mode 100644 index 0000000000..507c88788b --- /dev/null +++ b/Kernel/Locking/RefCountedContended.h @@ -0,0 +1,77 @@ +/* + * Copyright (c) 2021, the SerenityOS developers. + * + * SPDX-License-Identifier: BSD-2-Clause + */ + +#pragma once + +#include +#include +#include + +namespace Kernel { + +template +class RefCountedContended : public ContendedResource + , public AK::RefCountedBase { + AK_MAKE_NONCOPYABLE(RefCountedContended); + AK_MAKE_NONMOVABLE(RefCountedContended); + +protected: + using LockedShared = LockedResource; + using LockedExclusive = LockedResource; + + LockedShared lock_shared() const { return LockedShared(static_cast(this), this->ContendedResource::m_mutex); } + LockedExclusive lock_exclusive() { return LockedExclusive(static_cast(this), this->ContendedResource::m_mutex); } + +public: + RefCountedContended() = default; + + bool unref() const + { + auto new_ref_count = deref_base(); + if (new_ref_count == 0) { + AK::call_will_be_destroyed_if_present(static_cast(const_cast(this)->lock_exclusive().get())); + delete static_cast(this); + return true; + } else if (new_ref_count == 1) { + AK::call_one_ref_left_if_present(static_cast(const_cast(this)->lock_exclusive().get())); + } + return false; + } + + template + decltype(auto) with_shared(Callback callback) const + { + auto lock = lock_shared(); + return callback(*lock); + } + + template + decltype(auto) with_exclusive(Callback callback) + { + auto lock = lock_exclusive(); + return callback(*lock); + } + + template + void for_each_shared(Callback callback) const + { + with_shared([&](const auto& value) { + for (auto& item : value) + callback(item); + }); + } + + template + void for_each_exclusive(Callback callback) + { + with_exclusive([&](auto& value) { + for (auto& item : value) + callback(item); + }); + } +}; + +}