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 <memory>
18 
19 #include <glog/logging.h>
20 
21 #include <process/future.hpp>
22 
23 namespace process {
24 
25 // Forward declaration.
26 template <typename T>
27 class Owned;
28 
29 
30 // Represents a shared pointer and therefore enforces 'const' access.
31 template <typename T>
32 class Shared
33 {
34 public:
35  Shared();
36  explicit Shared(T* t);
37 
38  bool operator==(const Shared<T>& that) const;
39  bool operator<(const Shared<T>& that) const;
40 
41  // Enforces const access semantics.
42  const T& operator*() const;
43  const T* operator->() const;
44  const T* get() const;
45 
46  bool unique() const;
47 
48  void reset();
49  void reset(T* t);
50  void swap(Shared<T>& that);
51 
52  // Transfers ownership of the pointer by waiting for exclusive
53  // access (i.e., no other Shared instances). This shared pointer
54  // will be reset after this function is invoked. If multiple shared
55  // pointers pointing to the same object all want to be upgraded,
56  // only one of them may succeed and the rest will get failures.
57  Future<Owned<T>> own();
58 
59 private:
60  struct Data
61  {
62  explicit Data(T* _t);
63  ~Data();
64 
65  T* t;
66  std::atomic_bool owned;
67  Promise<Owned<T>> promise;
68  };
69 
70  std::shared_ptr<Data> data;
71 };
72 
73 
74 template <typename T>
76 
77 
78 template <typename T>
80 {
81  if (t != nullptr) {
82  data.reset(new Data(t));
83  }
84 }
85 
86 
87 template <typename T>
88 bool Shared<T>::operator==(const Shared<T>& that) const
89 {
90  return data == that.data;
91 }
92 
93 
94 template <typename T>
95 bool Shared<T>::operator<(const Shared<T>& that) const
96 {
97  return data < that.data;
98 }
99 
100 
101 template <typename T>
102 const T& Shared<T>::operator*() const
103 {
104  return *CHECK_NOTNULL(get());
105 }
106 
107 
108 template <typename T>
109 const T* Shared<T>::operator->() const
110 {
111  return CHECK_NOTNULL(get());
112 }
113 
114 
115 template <typename T>
116 const T* Shared<T>::get() const
117 {
118  if (data == nullptr) {
119  return nullptr;
120  } else {
121  return data->t;
122  }
123 }
124 
125 
126 template <typename T>
127 bool Shared<T>::unique() const
128 {
129  return data.unique();
130 }
131 
132 
133 template <typename T>
135 {
136  data.reset();
137 }
138 
139 
140 template <typename T>
142 {
143  if (t == nullptr) {
144  data.reset();
145  } else {
146  data.reset(new Data(t));
147  }
148 }
149 
150 
151 template <typename T>
153 {
154  data.swap(that.data);
155 }
156 
157 
158 template <typename T>
160 {
161  // If two threads simultaneously access this object and at least one
162  // of them is a write, the behavior is undefined. This is similar to
163  // boost::shared_ptr. For more details, please refer to the boost
164  // shared_ptr document (section "Thread Safety").
165  if (data == nullptr) {
166  return Owned<T>(nullptr);
167  }
168 
169  bool false_value = false;
170  if (!data->owned.compare_exchange_strong(false_value, true)) {
171  return Failure("Ownership has already been transferred");
172  }
173 
174  Future<Owned<T>> future = data->promise.future();
175  data.reset();
176  return future;
177 }
178 
179 
180 template <typename T>
182  : t(CHECK_NOTNULL(_t)), owned(false) {}
183 
184 
185 template <typename T>
186 Shared<T>::Data::~Data()
187 {
188  if (owned.load()) {
189  promise.set(Owned<T>(t));
190  } else {
191  delete t;
192  }
193 }
194 
195 } // namespace process {
196 
197 #endif // __PROCESS_SHARED_HPP__
Definition: future.hpp:664
void reset()
Definition: shared.hpp:134
bool operator<(const Shared< T > &that) const
Definition: shared.hpp:95
bool operator==(const Shared< T > &that) const
Definition: shared.hpp:88
Definition: owned.hpp:25
bool unique() const
Definition: shared.hpp:127
Protocol< PromiseRequest, PromiseResponse > promise
Result< Process > process(pid_t pid)
Definition: freebsd.hpp:30
const T * operator->() const
Definition: shared.hpp:109
Shared()
Definition: shared.hpp:75
const T & operator*() const
Definition: shared.hpp:102
Future< Owned< T > > own()
Definition: shared.hpp:159
Definition: owned.hpp:35
const T * get() const
Definition: shared.hpp:116
void swap(Shared< T > &that)
Definition: shared.hpp:152
Definition: future.hpp:57