Apache Mesos
shared.hpp
Go to the documentation of this file.
1 // Licensed under the Apache License, Version 2.0 (the "License");
2 // you may not use this file except in compliance with the License.
3 // You may obtain a copy of the License at
4 //
5 // http://www.apache.org/licenses/LICENSE-2.0
6 //
7 // Unless required by applicable law or agreed to in writing, software
8 // distributed under the License is distributed on an "AS IS" BASIS,
9 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
10 // See the License for the specific language governing permissions and
11 // limitations under the License
12 
13 #ifndef __PROCESS_SHARED_HPP__
14 #define __PROCESS_SHARED_HPP__
15 
16 #include <atomic>
17 #include <cstddef>
18 #include <memory>
19 
20 #include <glog/logging.h>
21 
22 #include <process/future.hpp>
23 
24 namespace process {
25 
26 // Forward declaration.
27 template <typename T>
28 class Owned;
29 
30 
31 // Represents a shared pointer and therefore enforces 'const' access.
32 template <typename T>
33 class Shared
34 {
35 public:
36  Shared();
37  explicit Shared(T* t);
38  /*implicit*/ Shared(std::nullptr_t) : Shared(static_cast<T*>(nullptr)) {}
39 
40  bool operator==(const Shared<T>& that) const;
41  bool operator<(const Shared<T>& that) const;
42 
43  // Enforces const access semantics.
44  const T& operator*() const;
45  const T* operator->() const;
46  const T* get() const;
47 
48  bool unique() const;
49 
50  void reset();
51  void reset(T* t);
52  void swap(Shared<T>& that);
53 
54  // Transfers ownership of the pointer by waiting for exclusive
55  // access (i.e., no other Shared instances). This shared pointer
56  // will be reset after this function is invoked. If multiple shared
57  // pointers pointing to the same object all want to be upgraded,
58  // only one of them may succeed and the rest will get failures.
60 
61 private:
62  struct Data
63  {
64  explicit Data(T* _t);
65  ~Data();
66 
67  T* t;
68  std::atomic_bool owned;
70  };
71 
72  std::shared_ptr<Data> data;
73 };
74 
75 
76 template <typename T>
78 
79 
80 template <typename T>
82 {
83  if (t != nullptr) {
84  data.reset(new Data(t));
85  }
86 }
87 
88 
89 template <typename T>
90 bool Shared<T>::operator==(const Shared<T>& that) const
91 {
92  return data == that.data;
93 }
94 
95 
96 template <typename T>
97 bool Shared<T>::operator<(const Shared<T>& that) const
98 {
99  return data < that.data;
100 }
101 
102 
103 template <typename T>
104 const T& Shared<T>::operator*() const
105 {
106  return *CHECK_NOTNULL(get());
107 }
108 
109 
110 template <typename T>
111 const T* Shared<T>::operator->() const
112 {
113  return CHECK_NOTNULL(get());
114 }
115 
116 
117 template <typename T>
118 const T* Shared<T>::get() const
119 {
120  if (data == nullptr) {
121  return nullptr;
122  } else {
123  return data->t;
124  }
125 }
126 
127 
128 template <typename T>
129 bool Shared<T>::unique() const
130 {
131  return data.unique();
132 }
133 
134 
135 template <typename T>
137 {
138  data.reset();
139 }
140 
141 
142 template <typename T>
144 {
145  if (t == nullptr) {
146  data.reset();
147  } else {
148  data.reset(new Data(t));
149  }
150 }
151 
152 
153 template <typename T>
155 {
156  data.swap(that.data);
157 }
158 
159 
160 template <typename T>
162 {
163  // If two threads simultaneously access this object and at least one
164  // of them is a write, the behavior is undefined. This is similar to
165  // boost::shared_ptr. For more details, please refer to the boost
166  // shared_ptr document (section "Thread Safety").
167  if (data == nullptr) {
168  return Owned<T>(nullptr);
169  }
170 
171  bool false_value = false;
172  if (!data->owned.compare_exchange_strong(false_value, true)) {
173  return Failure("Ownership has already been transferred");
174  }
175 
176  Future<Owned<T>> future = data->promise.future();
177  data.reset();
178  return future;
179 }
180 
181 
182 template <typename T>
184  : t(CHECK_NOTNULL(_t)), owned(false) {}
185 
186 
187 template <typename T>
189 {
190  if (owned.load()) {
191  promise.set(Owned<T>(t));
192  } else {
193  delete t;
194  }
195 }
196 
197 } // namespace process {
198 
199 #endif // __PROCESS_SHARED_HPP__
Definition: future.hpp:665
void reset()
Definition: shared.hpp:136
bool operator<(const Shared< T > &that) const
Definition: shared.hpp:97
bool operator==(const Shared< T > &that) const
Definition: shared.hpp:90
Definition: owned.hpp:26
bool unique() const
Definition: shared.hpp:129
Definition: future.hpp:73
Protocol< PromiseRequest, PromiseResponse > promise
Shared(std::nullptr_t)
Definition: shared.hpp:38
const T * operator->() const
Definition: shared.hpp:111
Definition: executor.hpp:47
Shared()
Definition: shared.hpp:77
const T & operator*() const
Definition: shared.hpp:104
Future< Owned< T > > own()
Definition: shared.hpp:161
Definition: owned.hpp:36
const T * get() const
Definition: shared.hpp:118
void swap(Shared< T > &that)
Definition: shared.hpp:154
Definition: future.hpp:57