Flutter Engine
unique_object.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_UNIQUE_OBJECT_H_
6 #define FLUTTER_FML_UNIQUE_OBJECT_H_
7 
8 #include <utility>
9 
10 #include "flutter/fml/compiler_specific.h"
11 #include "flutter/fml/logging.h"
12 #include "flutter/fml/macros.h"
13 
14 namespace fml {
15 
16 // struct UniqueFooTraits {
17 // // This function should be fast and inline.
18 // static int InvalidValue() { return 0; }
19 //
20 // // This function should be fast and inline.
21 // static bool IsValid(const T& value) { return value != InvalidValue(); }
22 //
23 // // This free function will not be called if f == InvalidValue()!
24 // static void Free(int f) { ::FreeFoo(f); }
25 // };
26 
27 template <typename T, typename Traits>
28 class UniqueObject {
29  private:
30  // This must be first since it's used inline below.
31  //
32  // Use the empty base class optimization to allow us to have a Traits
33  // member, while avoiding any space overhead for it when Traits is an
34  // empty class. See e.g. http://www.cantrip.org/emptyopt.html for a good
35  // discussion of this technique.
36  struct Data : public Traits {
37  explicit Data(const T& in) : generic(in) {}
38  Data(const T& in, const Traits& other) : Traits(other), generic(in) {}
39 
40  T generic;
41  };
42 
43  public:
44  using element_type = T;
45  using traits_type = Traits;
46 
47  UniqueObject() : data_(Traits::InvalidValue()) {}
48  explicit UniqueObject(const T& value) : data_(value) {}
49 
50  UniqueObject(const T& value, const Traits& traits) : data_(value, traits) {}
51 
53  : data_(other.release(), other.get_traits()) {}
54 
55  ~UniqueObject() { FreeIfNecessary(); }
56 
58  reset(other.release());
59  return *this;
60  }
61 
62  void reset(const T& value = Traits::InvalidValue()) {
63  FML_CHECK(data_.generic == Traits::InvalidValue() ||
64  data_.generic != value);
65  FreeIfNecessary();
66  data_.generic = value;
67  }
68 
69  void swap(UniqueObject& other) {
70  // Standard swap idiom: 'using std::swap' ensures that std::swap is
71  // present in the overload set, but we call swap unqualified so that
72  // any more-specific overloads can be used, if available.
73  using std::swap;
74  swap(static_cast<Traits&>(data_), static_cast<Traits&>(other.data_));
75  swap(data_.generic, other.data_.generic);
76  }
77 
78  // Release the object. The return value is the current object held by this
79  // object. After this operation, this object will hold an invalid value, and
80  // will not own the object any more.
81  [[nodiscard]] T release() {
82  T old_generic = data_.generic;
83  data_.generic = Traits::InvalidValue();
84  return old_generic;
85  }
86 
87  const T& get() const { return data_.generic; }
88 
89  bool is_valid() const { return Traits::IsValid(data_.generic); }
90 
91  bool operator==(const T& value) const { return data_.generic == value; }
92 
93  bool operator!=(const T& value) const { return data_.generic != value; }
94 
95  Traits& get_traits() { return data_; }
96  const Traits& get_traits() const { return data_; }
97 
98  private:
99  void FreeIfNecessary() {
100  if (data_.generic != Traits::InvalidValue()) {
101  data_.Free(data_.generic);
102  data_.generic = Traits::InvalidValue();
103  }
104  }
105 
106  // Forbid comparison. If U != T, it totally doesn't make sense, and if U ==
107  // T, it still doesn't make sense because you should never have the same
108  // object owned by two different UniqueObject.
109  template <typename T2, typename Traits2>
110  bool operator==(const UniqueObject<T2, Traits2>& p2) const = delete;
111 
112  template <typename T2, typename Traits2>
113  bool operator!=(const UniqueObject<T2, Traits2>& p2) const = delete;
114 
115  Data data_;
116 
118 };
119 
120 template <class T, class Traits>
122  a.swap(b);
123 }
124 
125 template <class T, class Traits>
126 bool operator==(const T& value, const UniqueObject<T, Traits>& object) {
127  return value == object.get();
128 }
129 
130 template <class T, class Traits>
131 bool operator!=(const T& value, const UniqueObject<T, Traits>& object) {
132  return !(value == object.get());
133 }
134 
135 } // namespace fml
136 
137 #endif // FLUTTER_FML_UNIQUE_OBJECT_H_
UniqueObject(const T &value)
Definition: unique_object.h:48
void swap(UniqueObject &other)
Definition: unique_object.h:69
void reset(const T &value=Traits::InvalidValue())
Definition: unique_object.h:62
bool operator==(const T &value) const
Definition: unique_object.h:91
Definition: ascii_trie.cc:9
bool is_valid() const
Definition: unique_object.h:89
uint8_t value
void swap(const UniqueObject< T, Traits > &a, const UniqueObject< T, Traits > &b)
UniqueObject(UniqueObject &&other)
Definition: unique_object.h:52
const Traits & get_traits() const
Definition: unique_object.h:96
UniqueObject & operator=(UniqueObject &&other)
Definition: unique_object.h:57
#define FML_CHECK(condition)
Definition: logging.h:68
bool operator!=(const T &value) const
Definition: unique_object.h:93
UniqueObject(const T &value, const Traits &traits)
Definition: unique_object.h:50
#define FML_DISALLOW_COPY_AND_ASSIGN(TypeName)
Definition: macros.h:27
Traits & get_traits()
Definition: unique_object.h:95