Flutter Engine
The Flutter Engine
Loading...
Searching...
No Matches
scoped_typeref.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#ifndef FLUTTER_FML_PLATFORM_DARWIN_SCOPED_TYPEREF_H_
6#define FLUTTER_FML_PLATFORM_DARWIN_SCOPED_TYPEREF_H_
7
8#include "flutter/fml/compiler_specific.h"
9#include "flutter/fml/platform/darwin/scoped_policy.h"
10
11namespace fml {
12
13// ScopedTypeRef<> is patterned after std::unique_ptr<>, but maintains ownership
14// of a reference to any type that is maintained by Retain and Release methods.
15//
16// The Traits structure must provide the Retain and Release methods for type T.
17// A default ScopedTypeRefTraits is used but not defined, and should be defined
18// for each type to use this interface. For example, an appropriate definition
19// of ScopedTypeRefTraits for CGLContextObj would be:
20//
21// template<>
22// struct ScopedTypeRefTraits<CGLContextObj> {
23// static CGLContextObj InvalidValue() { return nullptr; }
24// static CGLContextObj Retain(CGLContextObj object) {
25// CGLContextRetain(object);
26// return object;
27// }
28// static void Release(CGLContextObj object) { CGLContextRelease(object); }
29// };
30//
31// For the many types that have pass-by-pointer create functions, the function
32// InitializeInto() is provided to allow direct initialization and assumption
33// of ownership of the object. For example, continuing to use the above
34// CGLContextObj specialization:
35//
36// fml::ScopedTypeRef<CGLContextObj> context;
37// CGLCreateContext(pixel_format, share_group, context.InitializeInto());
38//
39// For initialization with an existing object, the caller may specify whether
40// the ScopedTypeRef<> being initialized is assuming the caller's existing
41// ownership of the object (and should not call Retain in initialization) or if
42// it should not assume this ownership and must create its own (by calling
43// Retain in initialization). This behavior is based on the |policy| parameter,
44// with |kAssume| for the former and |kRetain| for the latter. The default
45// policy is to |kAssume|.
46
47template <typename T>
49
50template <typename T, typename Traits = ScopedTypeRefTraits<T>>
52 public:
53 typedef T element_type;
54
55 explicit ScopedTypeRef(
56 __unsafe_unretained T object = Traits::InvalidValue(),
58 : object_(object) {
59 if (object_ && policy == fml::scoped_policy::kRetain) {
60 object_ = Traits::Retain(object_);
61 }
62 }
63
64 // NOLINTNEXTLINE(google-explicit-constructor)
65 ScopedTypeRef(const ScopedTypeRef<T, Traits>& that) : object_(that.object_) {
66 if (object_) {
67 object_ = Traits::Retain(object_);
68 }
69 }
70
71 // This allows passing an object to a function that takes its superclass.
72 template <typename R, typename RTraits>
73 explicit ScopedTypeRef(const ScopedTypeRef<R, RTraits>& that_as_subclass)
74 : object_(that_as_subclass.get()) {
75 if (object_) {
76 object_ = Traits::Retain(object_);
77 }
78 }
79
80 // NOLINTNEXTLINE(google-explicit-constructor)
81 ScopedTypeRef(ScopedTypeRef<T, Traits>&& that) : object_(that.object_) {
82 that.object_ = Traits::InvalidValue();
83 }
84
86 if (object_) {
87 Traits::Release(object_);
88 }
89 }
90
93 return *this;
94 }
95
96 // This is to be used only to take ownership of objects that are created
97 // by pass-by-pointer create functions. To enforce this, require that the
98 // object be reset to NULL before this may be used.
99 [[nodiscard]] T* InitializeInto() {
100 FML_DCHECK(!object_);
101 return &object_;
102 }
103
104 void reset(__unsafe_unretained T object = Traits::InvalidValue(),
107 if (object && policy == fml::scoped_policy::kRetain) {
108 object = Traits::Retain(object);
109 }
110 if (object_) {
111 Traits::Release(object_);
112 }
113 object_ = object;
114 }
115
116 bool operator==(__unsafe_unretained T that) const { return object_ == that; }
117
118 bool operator!=(__unsafe_unretained T that) const { return object_ != that; }
119
120 // NOLINTNEXTLINE(google-explicit-constructor)
121 operator T() const __attribute((ns_returns_not_retained)) { return object_; }
122
123 T get() const __attribute((ns_returns_not_retained)) { return object_; }
124
125 void swap(ScopedTypeRef& that) {
126 __unsafe_unretained T temp = that.object_;
127 that.object_ = object_;
128 object_ = temp;
129 }
130
131 protected:
132 // ScopedTypeRef<>::release() is like std::unique_ptr<>::release. It is NOT
133 // a wrapper for Release(). To force a ScopedTypeRef<> object to call
134 // Release(), use ScopedTypeRef<>::reset().
135 [[nodiscard]] T release() __attribute((ns_returns_not_retained)) {
136 __unsafe_unretained T temp = object_;
137 object_ = Traits::InvalidValue();
138 return temp;
139 }
140
141 private:
142 __unsafe_unretained T object_;
143};
144
145} // namespace fml
146
147#endif // FLUTTER_FML_PLATFORM_DARWIN_SCOPED_TYPEREF_H_
m reset()
T get() const __attribute((ns_returns_not_retained))
ScopedTypeRef(__unsafe_unretained T object=Traits::InvalidValue(), fml::scoped_policy::OwnershipPolicy policy=fml::scoped_policy::kAssume)
ScopedTypeRef & operator=(const ScopedTypeRef< T, Traits > &that)
T release() __attribute((ns_returns_not_retained))
void reset(__unsafe_unretained T object=Traits::InvalidValue(), fml::scoped_policy::OwnershipPolicy policy=fml::scoped_policy::kAssume)
bool operator==(__unsafe_unretained T that) const
void swap(ScopedTypeRef &that)
bool operator!=(__unsafe_unretained T that) const
ScopedTypeRef(const ScopedTypeRef< R, RTraits > &that_as_subclass)
ScopedTypeRef(const ScopedTypeRef< T, Traits > &that)
ScopedTypeRef(ScopedTypeRef< T, Traits > &&that)
#define FML_DCHECK(condition)
Definition logging.h:103
#define T