1*6777b538SAndroid Build Coastguard Worker // Copyright 2014 The Chromium Authors
2*6777b538SAndroid Build Coastguard Worker // Use of this source code is governed by a BSD-style license that can be
3*6777b538SAndroid Build Coastguard Worker // found in the LICENSE file.
4*6777b538SAndroid Build Coastguard Worker
5*6777b538SAndroid Build Coastguard Worker #ifndef BASE_SCOPED_GENERIC_H_
6*6777b538SAndroid Build Coastguard Worker #define BASE_SCOPED_GENERIC_H_
7*6777b538SAndroid Build Coastguard Worker
8*6777b538SAndroid Build Coastguard Worker #include <stdlib.h>
9*6777b538SAndroid Build Coastguard Worker
10*6777b538SAndroid Build Coastguard Worker #include <concepts>
11*6777b538SAndroid Build Coastguard Worker #include <type_traits>
12*6777b538SAndroid Build Coastguard Worker
13*6777b538SAndroid Build Coastguard Worker #include "base/check.h"
14*6777b538SAndroid Build Coastguard Worker #include "base/memory/raw_ptr.h"
15*6777b538SAndroid Build Coastguard Worker
16*6777b538SAndroid Build Coastguard Worker namespace base {
17*6777b538SAndroid Build Coastguard Worker
18*6777b538SAndroid Build Coastguard Worker // This class acts like unique_ptr with a custom deleter (although is slightly
19*6777b538SAndroid Build Coastguard Worker // less fancy in some of the more escoteric respects) except that it keeps a
20*6777b538SAndroid Build Coastguard Worker // copy of the object rather than a pointer, and we require that the contained
21*6777b538SAndroid Build Coastguard Worker // object has some kind of "invalid" value.
22*6777b538SAndroid Build Coastguard Worker //
23*6777b538SAndroid Build Coastguard Worker // Defining a scoper based on this class allows you to get a scoper for
24*6777b538SAndroid Build Coastguard Worker // non-pointer types without having to write custom code for set, reset, and
25*6777b538SAndroid Build Coastguard Worker // move, etc. and get almost identical semantics that people are used to from
26*6777b538SAndroid Build Coastguard Worker // unique_ptr.
27*6777b538SAndroid Build Coastguard Worker //
28*6777b538SAndroid Build Coastguard Worker // It is intended that you will typedef this class with an appropriate deleter
29*6777b538SAndroid Build Coastguard Worker // to implement clean up tasks for objects that act like pointers from a
30*6777b538SAndroid Build Coastguard Worker // resource management standpoint but aren't, such as file descriptors and
31*6777b538SAndroid Build Coastguard Worker // various types of operating system handles. Using unique_ptr for these
32*6777b538SAndroid Build Coastguard Worker // things requires that you keep a pointer to the handle valid for the lifetime
33*6777b538SAndroid Build Coastguard Worker // of the scoper (which is easy to mess up).
34*6777b538SAndroid Build Coastguard Worker //
35*6777b538SAndroid Build Coastguard Worker // For an object to be able to be put into a ScopedGeneric, it must support
36*6777b538SAndroid Build Coastguard Worker // standard copyable semantics and have a specific "invalid" value. The traits
37*6777b538SAndroid Build Coastguard Worker // must define a free function and also the invalid value to assign for
38*6777b538SAndroid Build Coastguard Worker // default-constructed and released objects.
39*6777b538SAndroid Build Coastguard Worker //
40*6777b538SAndroid Build Coastguard Worker // struct FooScopedTraits {
41*6777b538SAndroid Build Coastguard Worker // // It's assumed that this is a fast inline function with little-to-no
42*6777b538SAndroid Build Coastguard Worker // // penalty for duplicate calls. This must be a static function even
43*6777b538SAndroid Build Coastguard Worker // // for stateful traits.
44*6777b538SAndroid Build Coastguard Worker // static int InvalidValue() {
45*6777b538SAndroid Build Coastguard Worker // return 0;
46*6777b538SAndroid Build Coastguard Worker // }
47*6777b538SAndroid Build Coastguard Worker //
48*6777b538SAndroid Build Coastguard Worker // // This free function will not be called if f == InvalidValue()!
49*6777b538SAndroid Build Coastguard Worker // static void Free(int f) {
50*6777b538SAndroid Build Coastguard Worker // ::FreeFoo(f);
51*6777b538SAndroid Build Coastguard Worker // }
52*6777b538SAndroid Build Coastguard Worker // };
53*6777b538SAndroid Build Coastguard Worker //
54*6777b538SAndroid Build Coastguard Worker // using ScopedFoo = ScopedGeneric<int, FooScopedTraits>;
55*6777b538SAndroid Build Coastguard Worker //
56*6777b538SAndroid Build Coastguard Worker // A Traits type may choose to track ownership of objects in parallel with
57*6777b538SAndroid Build Coastguard Worker // ScopedGeneric. To do so, it must implement the Acquire and Release methods,
58*6777b538SAndroid Build Coastguard Worker // which will be called by ScopedGeneric during ownership transfers and extend
59*6777b538SAndroid Build Coastguard Worker // the ScopedGenericOwnershipTracking tag type.
60*6777b538SAndroid Build Coastguard Worker //
61*6777b538SAndroid Build Coastguard Worker // struct BarScopedTraits : public ScopedGenericOwnershipTracking {
62*6777b538SAndroid Build Coastguard Worker // using ScopedGenericType = ScopedGeneric<int, BarScopedTraits>;
63*6777b538SAndroid Build Coastguard Worker // static int InvalidValue() {
64*6777b538SAndroid Build Coastguard Worker // return 0;
65*6777b538SAndroid Build Coastguard Worker // }
66*6777b538SAndroid Build Coastguard Worker //
67*6777b538SAndroid Build Coastguard Worker // static void Free(int b) {
68*6777b538SAndroid Build Coastguard Worker // ::FreeBar(b);
69*6777b538SAndroid Build Coastguard Worker // }
70*6777b538SAndroid Build Coastguard Worker //
71*6777b538SAndroid Build Coastguard Worker // static void Acquire(const ScopedGenericType& owner, int b) {
72*6777b538SAndroid Build Coastguard Worker // ::TrackAcquisition(b, owner);
73*6777b538SAndroid Build Coastguard Worker // }
74*6777b538SAndroid Build Coastguard Worker //
75*6777b538SAndroid Build Coastguard Worker // static void Release(const ScopedGenericType& owner, int b) {
76*6777b538SAndroid Build Coastguard Worker // ::TrackRelease(b, owner);
77*6777b538SAndroid Build Coastguard Worker // }
78*6777b538SAndroid Build Coastguard Worker // };
79*6777b538SAndroid Build Coastguard Worker //
80*6777b538SAndroid Build Coastguard Worker // using ScopedBar = ScopedGeneric<int, BarScopedTraits>;
81*6777b538SAndroid Build Coastguard Worker struct ScopedGenericOwnershipTracking {};
82*6777b538SAndroid Build Coastguard Worker
83*6777b538SAndroid Build Coastguard Worker template<typename T, typename Traits>
84*6777b538SAndroid Build Coastguard Worker class ScopedGeneric {
85*6777b538SAndroid Build Coastguard Worker private:
86*6777b538SAndroid Build Coastguard Worker // This must be first since it's used inline below.
87*6777b538SAndroid Build Coastguard Worker //
88*6777b538SAndroid Build Coastguard Worker // Use the empty base class optimization to allow us to have a D
89*6777b538SAndroid Build Coastguard Worker // member, while avoiding any space overhead for it when D is an
90*6777b538SAndroid Build Coastguard Worker // empty class. See e.g. http://www.cantrip.org/emptyopt.html for a good
91*6777b538SAndroid Build Coastguard Worker // discussion of this technique.
92*6777b538SAndroid Build Coastguard Worker struct Data : public Traits {
DataData93*6777b538SAndroid Build Coastguard Worker explicit Data(const T& in) : generic(in) {}
DataData94*6777b538SAndroid Build Coastguard Worker Data(const T& in, const Traits& other) : Traits(other), generic(in) {}
95*6777b538SAndroid Build Coastguard Worker T generic;
96*6777b538SAndroid Build Coastguard Worker };
97*6777b538SAndroid Build Coastguard Worker
98*6777b538SAndroid Build Coastguard Worker public:
99*6777b538SAndroid Build Coastguard Worker typedef T element_type;
100*6777b538SAndroid Build Coastguard Worker typedef Traits traits_type;
101*6777b538SAndroid Build Coastguard Worker
ScopedGeneric()102*6777b538SAndroid Build Coastguard Worker ScopedGeneric() : data_(traits_type::InvalidValue()) {}
103*6777b538SAndroid Build Coastguard Worker
104*6777b538SAndroid Build Coastguard Worker // Constructor. Takes responsibility for freeing the resource associated with
105*6777b538SAndroid Build Coastguard Worker // the object T.
ScopedGeneric(const element_type & value)106*6777b538SAndroid Build Coastguard Worker explicit ScopedGeneric(const element_type& value) : data_(value) {
107*6777b538SAndroid Build Coastguard Worker TrackAcquire(data_.generic);
108*6777b538SAndroid Build Coastguard Worker }
109*6777b538SAndroid Build Coastguard Worker
110*6777b538SAndroid Build Coastguard Worker // Constructor. Allows initialization of a stateful traits object.
ScopedGeneric(const element_type & value,const traits_type & traits)111*6777b538SAndroid Build Coastguard Worker ScopedGeneric(const element_type& value, const traits_type& traits)
112*6777b538SAndroid Build Coastguard Worker : data_(value, traits) {
113*6777b538SAndroid Build Coastguard Worker TrackAcquire(data_.generic);
114*6777b538SAndroid Build Coastguard Worker }
115*6777b538SAndroid Build Coastguard Worker
116*6777b538SAndroid Build Coastguard Worker // Move constructor. Allows initialization from a ScopedGeneric rvalue.
ScopedGeneric(ScopedGeneric<T,Traits> && rvalue)117*6777b538SAndroid Build Coastguard Worker ScopedGeneric(ScopedGeneric<T, Traits>&& rvalue)
118*6777b538SAndroid Build Coastguard Worker : data_(rvalue.release(), rvalue.get_traits()) {
119*6777b538SAndroid Build Coastguard Worker TrackAcquire(data_.generic);
120*6777b538SAndroid Build Coastguard Worker }
121*6777b538SAndroid Build Coastguard Worker ScopedGeneric(const ScopedGeneric&) = delete;
122*6777b538SAndroid Build Coastguard Worker ScopedGeneric& operator=(const ScopedGeneric&) = delete;
123*6777b538SAndroid Build Coastguard Worker
~ScopedGeneric()124*6777b538SAndroid Build Coastguard Worker virtual ~ScopedGeneric() {
125*6777b538SAndroid Build Coastguard Worker CHECK(!receiving_); // ScopedGeneric destroyed with active receiver.
126*6777b538SAndroid Build Coastguard Worker FreeIfNecessary();
127*6777b538SAndroid Build Coastguard Worker }
128*6777b538SAndroid Build Coastguard Worker
129*6777b538SAndroid Build Coastguard Worker // operator=. Allows assignment from a ScopedGeneric rvalue.
130*6777b538SAndroid Build Coastguard Worker ScopedGeneric& operator=(ScopedGeneric<T, Traits>&& rvalue) {
131*6777b538SAndroid Build Coastguard Worker reset(rvalue.release());
132*6777b538SAndroid Build Coastguard Worker return *this;
133*6777b538SAndroid Build Coastguard Worker }
134*6777b538SAndroid Build Coastguard Worker
135*6777b538SAndroid Build Coastguard Worker // Frees the currently owned object, if any. Then takes ownership of a new
136*6777b538SAndroid Build Coastguard Worker // object, if given. Self-resets are not allowd as on unique_ptr. See
137*6777b538SAndroid Build Coastguard Worker // http://crbug.com/162971
138*6777b538SAndroid Build Coastguard Worker void reset(const element_type& value = traits_type::InvalidValue()) {
139*6777b538SAndroid Build Coastguard Worker if (data_.generic != traits_type::InvalidValue() && data_.generic == value)
140*6777b538SAndroid Build Coastguard Worker abort();
141*6777b538SAndroid Build Coastguard Worker FreeIfNecessary();
142*6777b538SAndroid Build Coastguard Worker data_.generic = value;
143*6777b538SAndroid Build Coastguard Worker TrackAcquire(value);
144*6777b538SAndroid Build Coastguard Worker }
145*6777b538SAndroid Build Coastguard Worker
146*6777b538SAndroid Build Coastguard Worker // Release the object. The return value is the current object held by this
147*6777b538SAndroid Build Coastguard Worker // object. After this operation, this object will hold a null value, and
148*6777b538SAndroid Build Coastguard Worker // will not own the object any more.
release()149*6777b538SAndroid Build Coastguard Worker [[nodiscard]] element_type release() {
150*6777b538SAndroid Build Coastguard Worker element_type old_generic = data_.generic;
151*6777b538SAndroid Build Coastguard Worker data_.generic = traits_type::InvalidValue();
152*6777b538SAndroid Build Coastguard Worker TrackRelease(old_generic);
153*6777b538SAndroid Build Coastguard Worker return old_generic;
154*6777b538SAndroid Build Coastguard Worker }
155*6777b538SAndroid Build Coastguard Worker
156*6777b538SAndroid Build Coastguard Worker // A helper class that provides a T* that can be used to take ownership of
157*6777b538SAndroid Build Coastguard Worker // a value returned from a function via out-parameter. When the Receiver is
158*6777b538SAndroid Build Coastguard Worker // destructed (which should usually be at the end of the statement in which
159*6777b538SAndroid Build Coastguard Worker // receive is called), ScopedGeneric::reset() will be called with the
160*6777b538SAndroid Build Coastguard Worker // Receiver's value.
161*6777b538SAndroid Build Coastguard Worker //
162*6777b538SAndroid Build Coastguard Worker // In the simple case of a function that assigns the value before it returns,
163*6777b538SAndroid Build Coastguard Worker // C++'s lifetime extension can be used as follows:
164*6777b538SAndroid Build Coastguard Worker //
165*6777b538SAndroid Build Coastguard Worker // ScopedFoo foo;
166*6777b538SAndroid Build Coastguard Worker // bool result = GetFoo(ScopedFoo::Receiver(foo).get());
167*6777b538SAndroid Build Coastguard Worker //
168*6777b538SAndroid Build Coastguard Worker // Note that the lifetime of the Receiver is extended until the semicolon,
169*6777b538SAndroid Build Coastguard Worker // and ScopedGeneric is assigned the value upon destruction of the Receiver,
170*6777b538SAndroid Build Coastguard Worker // so the following code would not work:
171*6777b538SAndroid Build Coastguard Worker //
172*6777b538SAndroid Build Coastguard Worker // // BROKEN!
173*6777b538SAndroid Build Coastguard Worker // ScopedFoo foo;
174*6777b538SAndroid Build Coastguard Worker // UseFoo(&foo, GetFoo(ScopedFoo::Receiver(foo).get()));
175*6777b538SAndroid Build Coastguard Worker //
176*6777b538SAndroid Build Coastguard Worker // In more complicated scenarios, you may need to provide an explicit scope
177*6777b538SAndroid Build Coastguard Worker // for the Receiver, as in the following:
178*6777b538SAndroid Build Coastguard Worker //
179*6777b538SAndroid Build Coastguard Worker // std::vector<ScopedFoo> foos(64);
180*6777b538SAndroid Build Coastguard Worker //
181*6777b538SAndroid Build Coastguard Worker // {
182*6777b538SAndroid Build Coastguard Worker // std::vector<ScopedFoo::Receiver> foo_receivers;
183*6777b538SAndroid Build Coastguard Worker // for (auto foo : foos) {
184*6777b538SAndroid Build Coastguard Worker // foo_receivers_.emplace_back(foo);
185*6777b538SAndroid Build Coastguard Worker // }
186*6777b538SAndroid Build Coastguard Worker // for (auto receiver : foo_receivers) {
187*6777b538SAndroid Build Coastguard Worker // SubmitGetFooRequest(receiver.get());
188*6777b538SAndroid Build Coastguard Worker // }
189*6777b538SAndroid Build Coastguard Worker // WaitForFooRequests();
190*6777b538SAndroid Build Coastguard Worker // }
191*6777b538SAndroid Build Coastguard Worker // UseFoos(foos);
192*6777b538SAndroid Build Coastguard Worker class Receiver {
193*6777b538SAndroid Build Coastguard Worker public:
Receiver(ScopedGeneric & parent)194*6777b538SAndroid Build Coastguard Worker explicit Receiver(ScopedGeneric& parent) : scoped_generic_(&parent) {
195*6777b538SAndroid Build Coastguard Worker // Check if we attempted to construct a Receiver for ScopedGeneric with an
196*6777b538SAndroid Build Coastguard Worker // existing Receiver.
197*6777b538SAndroid Build Coastguard Worker CHECK(!scoped_generic_->receiving_);
198*6777b538SAndroid Build Coastguard Worker scoped_generic_->receiving_ = true;
199*6777b538SAndroid Build Coastguard Worker }
200*6777b538SAndroid Build Coastguard Worker Receiver(const Receiver&) = delete;
201*6777b538SAndroid Build Coastguard Worker Receiver& operator=(const Receiver&) = delete;
Receiver(Receiver && move)202*6777b538SAndroid Build Coastguard Worker Receiver(Receiver&& move) {
203*6777b538SAndroid Build Coastguard Worker CHECK(!used_); // Moving into already-used Receiver.
204*6777b538SAndroid Build Coastguard Worker CHECK(!move.used_); // Moving from already-used Receiver.
205*6777b538SAndroid Build Coastguard Worker scoped_generic_ = move.scoped_generic_;
206*6777b538SAndroid Build Coastguard Worker move.scoped_generic_ = nullptr;
207*6777b538SAndroid Build Coastguard Worker }
208*6777b538SAndroid Build Coastguard Worker
209*6777b538SAndroid Build Coastguard Worker Receiver& operator=(Receiver&& move) {
210*6777b538SAndroid Build Coastguard Worker CHECK(!used_); // Moving into already-used Receiver.
211*6777b538SAndroid Build Coastguard Worker CHECK(!move.used_); // Moving from already-used Receiver.
212*6777b538SAndroid Build Coastguard Worker scoped_generic_ = move.scoped_generic_;
213*6777b538SAndroid Build Coastguard Worker move.scoped_generic_ = nullptr;
214*6777b538SAndroid Build Coastguard Worker }
~Receiver()215*6777b538SAndroid Build Coastguard Worker ~Receiver() {
216*6777b538SAndroid Build Coastguard Worker if (scoped_generic_) {
217*6777b538SAndroid Build Coastguard Worker CHECK(scoped_generic_->receiving_);
218*6777b538SAndroid Build Coastguard Worker scoped_generic_->reset(value_);
219*6777b538SAndroid Build Coastguard Worker scoped_generic_->receiving_ = false;
220*6777b538SAndroid Build Coastguard Worker }
221*6777b538SAndroid Build Coastguard Worker }
222*6777b538SAndroid Build Coastguard Worker // We hand out a pointer to a field in Receiver instead of directly to
223*6777b538SAndroid Build Coastguard Worker // ScopedGeneric's internal storage in order to make it so that users can't
224*6777b538SAndroid Build Coastguard Worker // accidentally silently break ScopedGeneric's invariants. This way, an
225*6777b538SAndroid Build Coastguard Worker // incorrect use-after-scope-exit is more detectable by ASan or static
226*6777b538SAndroid Build Coastguard Worker // analysis tools, as the pointer is only valid for the lifetime of the
227*6777b538SAndroid Build Coastguard Worker // Receiver, not the ScopedGeneric.
get()228*6777b538SAndroid Build Coastguard Worker T* get() {
229*6777b538SAndroid Build Coastguard Worker used_ = true;
230*6777b538SAndroid Build Coastguard Worker return &value_;
231*6777b538SAndroid Build Coastguard Worker }
232*6777b538SAndroid Build Coastguard Worker
233*6777b538SAndroid Build Coastguard Worker private:
234*6777b538SAndroid Build Coastguard Worker T value_ = Traits::InvalidValue();
235*6777b538SAndroid Build Coastguard Worker raw_ptr<ScopedGeneric<T, Traits>> scoped_generic_;
236*6777b538SAndroid Build Coastguard Worker bool used_ = false;
237*6777b538SAndroid Build Coastguard Worker };
238*6777b538SAndroid Build Coastguard Worker
get()239*6777b538SAndroid Build Coastguard Worker const element_type& get() const { return data_.generic; }
240*6777b538SAndroid Build Coastguard Worker
241*6777b538SAndroid Build Coastguard Worker // Returns true if this object doesn't hold the special null value for the
242*6777b538SAndroid Build Coastguard Worker // associated data type.
is_valid()243*6777b538SAndroid Build Coastguard Worker bool is_valid() const { return data_.generic != traits_type::InvalidValue(); }
244*6777b538SAndroid Build Coastguard Worker
245*6777b538SAndroid Build Coastguard Worker bool operator==(const element_type& value) const {
246*6777b538SAndroid Build Coastguard Worker return data_.generic == value;
247*6777b538SAndroid Build Coastguard Worker }
248*6777b538SAndroid Build Coastguard Worker bool operator!=(const element_type& value) const {
249*6777b538SAndroid Build Coastguard Worker return data_.generic != value;
250*6777b538SAndroid Build Coastguard Worker }
251*6777b538SAndroid Build Coastguard Worker
get_traits()252*6777b538SAndroid Build Coastguard Worker Traits& get_traits() { return data_; }
get_traits()253*6777b538SAndroid Build Coastguard Worker const Traits& get_traits() const { return data_; }
254*6777b538SAndroid Build Coastguard Worker
255*6777b538SAndroid Build Coastguard Worker private:
FreeIfNecessary()256*6777b538SAndroid Build Coastguard Worker void FreeIfNecessary() {
257*6777b538SAndroid Build Coastguard Worker if (data_.generic != traits_type::InvalidValue()) {
258*6777b538SAndroid Build Coastguard Worker TrackRelease(data_.generic);
259*6777b538SAndroid Build Coastguard Worker data_.Free(data_.generic);
260*6777b538SAndroid Build Coastguard Worker data_.generic = traits_type::InvalidValue();
261*6777b538SAndroid Build Coastguard Worker }
262*6777b538SAndroid Build Coastguard Worker }
263*6777b538SAndroid Build Coastguard Worker
TrackAcquire(const T & value)264*6777b538SAndroid Build Coastguard Worker void TrackAcquire(const T& value) {
265*6777b538SAndroid Build Coastguard Worker if constexpr (std::derived_from<Traits, ScopedGenericOwnershipTracking>) {
266*6777b538SAndroid Build Coastguard Worker if (value != traits_type::InvalidValue()) {
267*6777b538SAndroid Build Coastguard Worker data_.Acquire(static_cast<const ScopedGeneric&>(*this), value);
268*6777b538SAndroid Build Coastguard Worker }
269*6777b538SAndroid Build Coastguard Worker }
270*6777b538SAndroid Build Coastguard Worker }
271*6777b538SAndroid Build Coastguard Worker
TrackRelease(const T & value)272*6777b538SAndroid Build Coastguard Worker void TrackRelease(const T& value) {
273*6777b538SAndroid Build Coastguard Worker if constexpr (std::derived_from<Traits, ScopedGenericOwnershipTracking>) {
274*6777b538SAndroid Build Coastguard Worker if (value != traits_type::InvalidValue()) {
275*6777b538SAndroid Build Coastguard Worker data_.Release(static_cast<const ScopedGeneric&>(*this), value);
276*6777b538SAndroid Build Coastguard Worker }
277*6777b538SAndroid Build Coastguard Worker }
278*6777b538SAndroid Build Coastguard Worker }
279*6777b538SAndroid Build Coastguard Worker
280*6777b538SAndroid Build Coastguard Worker // Forbid comparison. If U != T, it totally doesn't make sense, and if U ==
281*6777b538SAndroid Build Coastguard Worker // T, it still doesn't make sense because you should never have the same
282*6777b538SAndroid Build Coastguard Worker // object owned by two different ScopedGenerics.
283*6777b538SAndroid Build Coastguard Worker template <typename T2, typename Traits2> bool operator==(
284*6777b538SAndroid Build Coastguard Worker const ScopedGeneric<T2, Traits2>& p2) const;
285*6777b538SAndroid Build Coastguard Worker template <typename T2, typename Traits2> bool operator!=(
286*6777b538SAndroid Build Coastguard Worker const ScopedGeneric<T2, Traits2>& p2) const;
287*6777b538SAndroid Build Coastguard Worker
288*6777b538SAndroid Build Coastguard Worker Data data_;
289*6777b538SAndroid Build Coastguard Worker bool receiving_ = false;
290*6777b538SAndroid Build Coastguard Worker };
291*6777b538SAndroid Build Coastguard Worker
292*6777b538SAndroid Build Coastguard Worker template<class T, class Traits>
swap(const ScopedGeneric<T,Traits> & a,const ScopedGeneric<T,Traits> & b)293*6777b538SAndroid Build Coastguard Worker void swap(const ScopedGeneric<T, Traits>& a,
294*6777b538SAndroid Build Coastguard Worker const ScopedGeneric<T, Traits>& b) {
295*6777b538SAndroid Build Coastguard Worker a.swap(b);
296*6777b538SAndroid Build Coastguard Worker }
297*6777b538SAndroid Build Coastguard Worker
298*6777b538SAndroid Build Coastguard Worker template<class T, class Traits>
299*6777b538SAndroid Build Coastguard Worker bool operator==(const T& value, const ScopedGeneric<T, Traits>& scoped) {
300*6777b538SAndroid Build Coastguard Worker return value == scoped.get();
301*6777b538SAndroid Build Coastguard Worker }
302*6777b538SAndroid Build Coastguard Worker
303*6777b538SAndroid Build Coastguard Worker template<class T, class Traits>
304*6777b538SAndroid Build Coastguard Worker bool operator!=(const T& value, const ScopedGeneric<T, Traits>& scoped) {
305*6777b538SAndroid Build Coastguard Worker return value != scoped.get();
306*6777b538SAndroid Build Coastguard Worker }
307*6777b538SAndroid Build Coastguard Worker
308*6777b538SAndroid Build Coastguard Worker } // namespace base
309*6777b538SAndroid Build Coastguard Worker
310*6777b538SAndroid Build Coastguard Worker #endif // BASE_SCOPED_GENERIC_H_
311