xref: /aosp_15_r20/external/cronet/base/scoped_generic.h (revision 6777b5387eb2ff775bb5750e3f5d96f37fb7352b)
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