/* * Copyright (c) 2021, the SerenityOS developers. * * SPDX-License-Identifier: BSD-2-Clause */ #pragma once #include #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(LockLocation const& location) const { return LockedShared(static_cast(this), this->ContendedResource::m_mutex, location); } LockedExclusive lock_exclusive(LockLocation const& location) { return LockedExclusive(static_cast(this), this->ContendedResource::m_mutex, location); } 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, LockLocation const& location = LockLocation::current()) const { auto lock = lock_shared(location); return callback(*lock); } template decltype(auto) with_exclusive(Callback callback, LockLocation const& location = LockLocation::current()) { auto lock = lock_exclusive(location); return callback(*lock); } template void for_each_shared(Callback callback, LockLocation const& location = LockLocation::current()) const { with_shared([&](const auto& value) { for (auto& item : value) callback(item); }, location); } template void for_each_exclusive(Callback callback, LockLocation const& location = LockLocation::current()) { with_exclusive([&](auto& value) { for (auto& item : value) callback(item); }, location); } }; }