Apache Mesos
mutex.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_MUTEX_HPP__
14 #define __PROCESS_MUTEX_HPP__
15 
16 #include <atomic>
17 #include <memory>
18 #include <queue>
19 
20 #include <process/future.hpp>
21 #include <process/owned.hpp>
22 
23 #include <stout/nothing.hpp>
24 #include <stout/synchronized.hpp>
25 
26 namespace process {
27 
28 class Mutex
29 {
30 public:
31  Mutex() : data(new Data()) {}
32 
34  {
35  Future<Nothing> future = Nothing();
36 
37  synchronized (data->lock) {
38  if (!data->locked) {
39  data->locked = true;
40  } else {
41  Promise<Nothing> waiter;
42  future = waiter.future();
43  data->waiters.push(std::move(waiter));
44  }
45  }
46 
47  return future;
48  }
49 
50  void unlock()
51  {
52  // NOTE: We need to grab the promise 'date->promises.front()' but
53  // set it outside of the critical section because setting it might
54  // trigger callbacks that try to reacquire the lock.
56 
57  synchronized (data->lock) {
58  if (!data->waiters.empty()) {
59  // TODO(benh): Skip a future that has been discarded?
60  waiter = std::move(data->waiters.front());
61  data->waiters.pop();
62  } else {
63  data->locked = false;
64  }
65  }
66 
67  if (waiter.isSome()) {
68  waiter->set(Nothing());
69  }
70  }
71 
72 private:
73  struct Data
74  {
75  Data() : locked(false) {}
76 
77  ~Data()
78  {
79  // TODO(benh): Fail promises?
80  }
81 
82  // Rather than use a process to serialize access to the mutex's
83  // internal data we use a 'std::atomic_flag'.
84  std::atomic_flag lock = ATOMIC_FLAG_INIT;
85 
86  // Describes the state of this mutex.
87  bool locked;
88 
89  // Represents "waiters" for this lock.
90  std::queue<Promise<Nothing>> waiters;
91  };
92 
93  std::shared_ptr<Data> data;
94 };
95 
96 } // namespace process {
97 
98 #endif // __PROCESS_MUTEX_HPP__
Definition: nothing.hpp:16
void unlock()
Definition: mutex.hpp:50
Definition: option.hpp:28
bool isSome() const
Definition: option.hpp:115
Mutex()
Definition: mutex.hpp:31
Future< Nothing > lock()
Definition: mutex.hpp:33
Result< Process > process(pid_t pid)
Definition: freebsd.hpp:30
Future< T > future() const
Definition: future.hpp:912
Definition: mutex.hpp:28