| // Copyright 2018 The Fuchsia Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| #pragma once |
| |
| #include <fbl/ref_counted_upgradeable.h> |
| #include <zircon/assert.h> |
| #include <zircon/compiler.h> |
| #include <zircon/types.h> |
| |
| #include <atomic> |
| |
| namespace fs { |
| |
| // VnodeRefCounted implements a customized RefCounted object. |
| // |
| // It adds an additional method, "ResurrectRef", which allows Vnodes to be |
| // re-used after a reference count of zero has been reached. |
| template <typename T, |
| bool EnableAdoptionValidator = ZX_DEBUG_ASSERT_IMPLEMENTED> |
| class VnodeRefCounted : |
| private ::fbl::internal::RefCountedUpgradeableBase<EnableAdoptionValidator> { |
| public: |
| constexpr VnodeRefCounted() {} |
| ~VnodeRefCounted() {} |
| |
| using ::fbl::internal::RefCountedBase<EnableAdoptionValidator>::AddRef; |
| using ::fbl::internal::RefCountedBase<EnableAdoptionValidator>::Release; |
| using ::fbl::internal::RefCountedBase<EnableAdoptionValidator>::Adopt; |
| using ::fbl::internal::RefCountedBase<EnableAdoptionValidator>::ref_count_debug; |
| |
| // Don't use this method. See the relevant RefPtr implementation for details. |
| using ::fbl::internal::RefCountedUpgradeableBase<EnableAdoptionValidator>:: |
| AddRefMaybeInDestructor; |
| |
| // VnodeRefCounted<> instances may not be copied, assigned or moved. |
| DISALLOW_COPY_ASSIGN_AND_MOVE(VnodeRefCounted); |
| |
| // This method should only be called if the refcount was "zero", implying the |
| // object is currently executing fbl_recycle. In this case, the refcount |
| // is increased by one. |
| // |
| // This method may be called to prevent fbl_recycle from following the |
| // typical path of object deletion: instead of destroying the object, |
| // this function can be called to "reset" the lifecycle of the RefCounted |
| // object to the initialized state of "ref_count_ = 1", so it can |
| // continue to be utilized after there are no strong references. |
| // |
| // This function should be used EXCLUSIVELY from within fbl_recycle. |
| // If other clients (outside fbl_recycle) attempt to resurrect the Vnode |
| // concurrently with a call to Vnode::fbl_recycle, they risk going through |
| // the entire Vnode lifecycle and destroying it (with another call to |
| // Vnode::fbl_recycle) before the initial recycle execution terminates. |
| void ResurrectRef() const { |
| if (EnableAdoptionValidator) { |
| int32_t old = this->ref_count_.load(std::memory_order_relaxed); |
| ZX_DEBUG_ASSERT_MSG(old == 0, "count %d(0x%08x) != 0\n", old, old); |
| } |
| this->ref_count_.store(1, std::memory_order_relaxed); |
| } |
| }; |
| |
| } // namespace fs |