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
14namespace 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.
62template <typename T>
63class 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.
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).
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).
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.
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