• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2013 The Flutter Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 // Provides a base class for reference-counted classes.
6 
7 #ifndef FLUTTER_FML_MEMORY_REF_COUNTED_H_
8 #define FLUTTER_FML_MEMORY_REF_COUNTED_H_
9 
10 #include "flutter/fml/macros.h"
11 #include "flutter/fml/memory/ref_counted_internal.h"
12 #include "flutter/fml/memory/ref_ptr.h"
13 
14 namespace fml {
15 
16 // A base class for (thread-safe) reference-counted classes. Use like:
17 //
18 //   class Foo : public RefCountedThreadSafe<Foo> {
19 //     ...
20 //   };
21 //
22 // |~Foo()| *may* be made private (e.g., to avoid accidental deletion of objects
23 // while there are still references to them), |Foo| should friend
24 // |RefCountedThreadSafe<Foo>|; use |FML_FRIEND_REF_COUNTED_THREAD_SAFE()|
25 // for this:
26 //
27 //   class Foo : public RefCountedThreadSafe<Foo> {
28 //     ...
29 //    private:
30 //     FML_FRIEND_REF_COUNTED_THREAD_SAFE(Foo);
31 //     ~Foo();
32 //     ...
33 //   };
34 //
35 // Similarly, |Foo(...)| may be made private. In this case, there should either
36 // be a static factory method performing the requisite adoption:
37 //
38 //   class Foo : public RefCountedThreadSafe<Foo> {
39 //     ...
40 //    public:
41 //     inline static RefPtr<Foo> Create() { return AdoptRef(new Foo()); }
42 //     ...
43 //    private:
44 //     Foo();
45 //     ...
46 //   };
47 //
48 // Or, to allow |MakeRefCounted()| to be used, use
49 // |FML_FRIEND_MAKE_REF_COUNTED()|:
50 //
51 //   class Foo : public RefCountedThreadSafe<Foo> {
52 //     ...
53 //    private:
54 //     FML_FRIEND_MAKE_REF_COUNTED(Foo);
55 //     Foo();
56 //     Foo(const Bar& bar, bool maybe);
57 //     ...
58 //   };
59 //
60 // For now, we only have thread-safe reference counting, since that's all we
61 // need. It's easy enough to add thread-unsafe versions if necessary.
62 template <typename T>
63 class RefCountedThreadSafe : public internal::RefCountedThreadSafeBase {
64  public:
65   // Adds a reference to this object.
66   // Inherited from the internal superclass:
67   //   void AddRef() const;
68 
69   // Releases a reference to this object. This will destroy this object once the
70   // last reference is released.
Release()71   void Release() const {
72     if (internal::RefCountedThreadSafeBase::Release())
73       delete static_cast<const T*>(this);
74   }
75 
76   // Returns true if there is exactly one reference to this object. Use of this
77   // is subtle, and should usually be avoided. To assert that there is only one
78   // reference (typically held by the calling thread, possibly in a local
79   // variable), use |AssertHasOneRef()| instead. However, a use is:
80   //
81   //   if (foo->HasOneRef()) {
82   //     // Do something "fast", since |foo| is the only reference and no other
83   //     // thread can get another reference.
84   //     ...
85   //   } else {
86   //     // Do something slower, but still valid even if there were only one
87   //     // reference.
88   //     ...
89   //   }
90   //
91   // Inherited from the internal superclass:
92   //   bool HasOneRef();
93 
94   // Asserts that there is exactly one reference to this object; does nothing in
95   // Release builds (when |NDEBUG| is defined).
96   // Inherited from the internal superclass:
97   //   void AssertHasOneRef();
98 
99  protected:
100   // Constructor. Note that the object is constructed with a reference count of
101   // 1, and then must be adopted (see |AdoptRef()| in ref_ptr.h).
RefCountedThreadSafe()102   RefCountedThreadSafe() {}
103 
104   // Destructor. Note that this object should only be destroyed via |Release()|
105   // (see above), or something that calls |Release()| (see, e.g., |RefPtr<>| in
106   // ref_ptr.h).
~RefCountedThreadSafe()107   ~RefCountedThreadSafe() {}
108 
109  private:
110 #ifndef NDEBUG
111   template <typename U>
112   friend RefPtr<U> AdoptRef(U*);
113   // Marks the initial reference (assumed on construction) as adopted. This is
114   // only required for Debug builds (when |NDEBUG| is not defined).
115   // TODO(vtl): Should this really be private? This makes manual ref-counting
116   // and also writing one's own ref pointer class impossible.
Adopt()117   void Adopt() { internal::RefCountedThreadSafeBase::Adopt(); }
118 #endif
119 
120   FML_DISALLOW_COPY_AND_ASSIGN(RefCountedThreadSafe);
121 };
122 
123 // If you subclass |RefCountedThreadSafe| and want to keep your destructor
124 // private, use this. (See the example above |RefCountedThreadSafe|.)
125 #define FML_FRIEND_REF_COUNTED_THREAD_SAFE(T) \
126   friend class ::fml::RefCountedThreadSafe<T>
127 
128 // If you want to keep your constructor(s) private and still want to use
129 // |MakeRefCounted<T>()|, use this. (See the example above
130 // |RefCountedThreadSafe|.)
131 #define FML_FRIEND_MAKE_REF_COUNTED(T) \
132   friend class ::fml::internal::MakeRefCountedHelper<T>
133 
134 }  // namespace fml
135 
136 #endif  // FLUTTER_FML_MEMORY_REF_COUNTED_H_
137