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