Flutter Engine
ref_counted_internal.h
Go to the documentation of this file.
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 // Internal implementation details for ref_counted.h.
6 
7 #ifndef FLUTTER_FML_MEMORY_REF_COUNTED_INTERNAL_H_
8 #define FLUTTER_FML_MEMORY_REF_COUNTED_INTERNAL_H_
9 
10 #include <atomic>
11 
12 #include "flutter/fml/logging.h"
13 #include "flutter/fml/macros.h"
14 
15 namespace fml {
16 namespace internal {
17 
18 // See ref_counted.h for comments on the public methods.
20  public:
21  void AddRef() const {
22 #ifndef NDEBUG
23  FML_DCHECK(!adoption_required_);
24  FML_DCHECK(!destruction_started_);
25 #endif
26  ref_count_.fetch_add(1u, std::memory_order_relaxed);
27  }
28 
29  bool HasOneRef() const {
30  return ref_count_.load(std::memory_order_acquire) == 1u;
31  }
32 
33  void AssertHasOneRef() const { FML_DCHECK(HasOneRef()); }
34 
35  protected:
38 
39  // Returns true if the object should self-delete.
40  bool Release() const {
41 #ifndef NDEBUG
42  FML_DCHECK(!adoption_required_);
43  FML_DCHECK(!destruction_started_);
44 #endif
45  FML_DCHECK(ref_count_.load(std::memory_order_acquire) != 0u);
46  // TODO(vtl): We could add the following:
47  // if (ref_count_.load(std::memory_order_relaxed) == 1u) {
48  // #ifndef NDEBUG
49  // destruction_started_= true;
50  // #endif
51  // return true;
52  // }
53  // This would be correct. On ARM (an Nexus 4), in *single-threaded* tests,
54  // this seems to make the destruction case marginally faster (barely
55  // measurable), and while the non-destruction case remains about the same
56  // (possibly marginally slower, but my measurements aren't good enough to
57  // have any confidence in that). I should try multithreaded/multicore tests.
58  if (ref_count_.fetch_sub(1u, std::memory_order_release) == 1u) {
59  std::atomic_thread_fence(std::memory_order_acquire);
60 #ifndef NDEBUG
61  destruction_started_ = true;
62 #endif
63  return true;
64  }
65  return false;
66  }
67 
68 #ifndef NDEBUG
69  void Adopt() {
70  FML_DCHECK(adoption_required_);
71  adoption_required_ = false;
72  }
73 #endif
74 
75  private:
76  mutable std::atomic_uint_fast32_t ref_count_;
77 
78 #ifndef NDEBUG
79  mutable bool adoption_required_;
80  mutable bool destruction_started_;
81 #endif
82 
83  FML_DISALLOW_COPY_AND_ASSIGN(RefCountedThreadSafeBase);
84 };
85 
87  : ref_count_(1u)
88 #ifndef NDEBUG
89  ,
90  adoption_required_(true),
91  destruction_started_(false)
92 #endif
93 {
94 }
95 
97 #ifndef NDEBUG
98  FML_DCHECK(!adoption_required_);
99  // Should only be destroyed as a result of |Release()|.
100  FML_DCHECK(destruction_started_);
101 #endif
102 }
103 
104 } // namespace internal
105 } // namespace fml
106 
107 #endif // FLUTTER_FML_MEMORY_REF_COUNTED_INTERNAL_H_
#define FML_DCHECK(condition)
Definition: logging.h:86
Definition: ascii_trie.cc:9