|  | // Copyright 2017 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. | 
|  |  | 
|  | #ifndef SRC_UI_LIB_ESCHER_BASE_REFFABLE_H_ | 
|  | #define SRC_UI_LIB_ESCHER_BASE_REFFABLE_H_ | 
|  |  | 
|  | #include <lib/syslog/cpp/macros.h> | 
|  |  | 
|  | #include <cstdint> | 
|  |  | 
|  | #include "src/lib/fxl/memory/ref_ptr.h" | 
|  | #include "src/ui/lib/escher/base/make.h" | 
|  |  | 
|  | namespace escher { | 
|  |  | 
|  | // Reffable is a non-threadsafe ref-counted base class that is suitable for use | 
|  | // with fxl::RefPtr.  It provides a virtual OnZeroRefCount() method that | 
|  | // subclasses can use to avoid immediate destruction when their ref-count | 
|  | // becomes zero. | 
|  | // | 
|  | // Use this class similarly to fxl::RefCountedThreadSafe.  For example, instead | 
|  | // of: | 
|  | //    class Foo : public RefCountedThreadSafe<Foo> { ... | 
|  | // simply say: | 
|  | //    class Foo : public Reffable { ... | 
|  | // | 
|  | // Other than thread-safety, the main difference from RefCountedThreadSafe is | 
|  | // that Reffable allows subclasses to defer destruction by overriding | 
|  | // OnZeroRefCount(); see below. | 
|  | class Reffable { | 
|  | public: | 
|  | Reffable() = default; | 
|  | virtual ~Reffable(); | 
|  |  | 
|  | // Return the number of references to this object. | 
|  | uint32_t ref_count() const { return ref_count_; } | 
|  |  | 
|  | protected: | 
|  | // Return true if the object should be destroyed immediately, or false if its | 
|  | // destruction should be deferred.  Subclass that override this method to | 
|  | // return false are responsible for ensuring that the object is eventually | 
|  | // destroyed. | 
|  | virtual bool OnZeroRefCount() { return true; } | 
|  |  | 
|  | private: | 
|  | template <typename T> | 
|  | friend class fxl::RefPtr; | 
|  |  | 
|  | // Called by fxl::RefPtr. | 
|  | void Release() { | 
|  | if (--ref_count_ == 0) { | 
|  | if (OnZeroRefCount()) { | 
|  | delete this; | 
|  | } | 
|  | } | 
|  | } | 
|  |  | 
|  | // Called by fxl::RefPtr. | 
|  | void AddRef() const { | 
|  | #ifndef NDEBUG | 
|  | FX_DCHECK(!adoption_required_); | 
|  | #endif | 
|  | ++ref_count_; | 
|  | } | 
|  |  | 
|  | mutable uint32_t ref_count_ = 1; | 
|  |  | 
|  | #ifndef NDEBUG | 
|  | // Called by fxl::RefPtr, but only in debug builds. | 
|  | template <typename U> | 
|  | friend fxl::RefPtr<U> fxl::AdoptRef(U*); | 
|  | void Adopt(); | 
|  | bool adoption_required_ = true; | 
|  | #endif | 
|  |  | 
|  | FXL_DISALLOW_COPY_AND_ASSIGN(Reffable); | 
|  | }; | 
|  |  | 
|  | }  // namespace escher | 
|  |  | 
|  | #endif  // SRC_UI_LIB_ESCHER_BASE_REFFABLE_H_ |