Mir
synchronised.h
Go to the documentation of this file.
1 /*
2  * Copyright © 2017 Canonical Ltd.
3  *
4  * This program is free software: you can redistribute it and/or modify it
5  * under the terms of the GNU Lesser General Public License version 2 or 3,
6  * as published by the Free Software Foundation.
7  *
8  * This program is distributed in the hope that it will be useful,
9  * but WITHOUT ANY WARRANTY; without even the implied warranty of
10  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11  * GNU Lesser General Public License for more details.
12  *
13  * You should have received a copy of the GNU Lesser General Public License
14  * along with this program. If not, see <http://www.gnu.org/licenses/>.
15  */
16 
17 #ifndef MIR_SYNCHRONISED_H_
18 #define MIR_SYNCHRONISED_H_
19 
20 #include <mutex>
21 
22 namespace mir
23 {
24 
25 /**
26  * An object that enforces unique access to the data it contains
27  *
28  * This behaves like a mutex which owns the data it guards, and
29  * can give out a smart-pointer-esque handle to lock and access it.
30  *
31  * \tparam T The type of data contained
32  */
33 template<typename T>
35 {
36 public:
37  Synchronised() = default;
38  Synchronised(T&& initial_value)
39  : value{std::move(initial_value)}
40  {
41  }
42 
43  Synchronised(Synchronised const&) = delete;
44  Synchronised& operator=(Synchronised const&) = delete;
45 
46  /**
47  * Smart-pointer-esque accessor for the protected data.
48  *
49  * Ensures exclusive access to the referenced data.
50  *
51  * \note Instances of Locked must not outlive the Synchronised
52  * they are derived from.
53  */
54  template<typename U>
55  class LockedImpl
56  {
57  public:
58  LockedImpl(LockedImpl&& from) noexcept
59  : value{from.value},
60  lock{std::move(from.lock)}
61  {
62  from.value = nullptr;
63  }
64 
65  ~LockedImpl() = default;
66 
67  auto operator*() const -> U&
68  {
69  return *value;
70  }
71 
72  auto operator->() const -> U*
73  {
74  return value;
75  }
76 
77  /**
78  * Relinquish access to the data
79  *
80  * This prevents further access to the contained data through
81  * this handle, and allows other code to acquire access.
82  */
83  void drop()
84  {
85  value = nullptr;
86  lock.unlock();
87  }
88 
89  private:
90  friend class Synchronised;
91  LockedImpl(std::unique_lock<std::mutex>&& lock, U& value)
92  : value{&value},
93  lock{std::move(lock)}
94  {
95  }
96 
97  U* value;
98  std::unique_lock<std::mutex> lock;
99  };
100 
101  /**
102  * Smart-pointer-esque accessor for the protected data.
103  *
104  * Ensures exclusive access to the referenced data.
105  *
106  * \note Instances of Locked must not outlive the Synchronised
107  * they are derived from.
108  */
109  using Locked = LockedImpl<T>;
110  /**
111  * Lock the data and return an accessor.
112  *
113  * \return A smart-pointer-esque accessor for the contained data.
114  * While code has access to a live Locked instance it is
115  * guaranteed to have unique access to the contained data.
116  */
117  auto lock() -> Locked
118  {
119  return LockedImpl<T>{std::unique_lock{mutex}, value};
120  }
121 
122  /**
123  * Smart-pointer-esque accessor for the protected data.
124  *
125  * Provides const access to the protected data, with the guarantee
126  * that no changes to the data can be made while this handle
127  * is live.
128  *
129  * \note Instances of Locked must not outlive the Synchronised
130  * they are derived from.
131  */
132  using LockedView = LockedImpl<T const>;
133  /**
134  * Lock the data and return an accessor.
135  *
136  * \return A smart-pointer-esque accessor for the contained data.
137  * While code has access to a live Locked instance it is
138  * guaranteed to have unique access to the contained data.
139  */
140  auto lock() const -> LockedView
141  {
142  return LockedImpl<T const>{std::unique_lock{mutex}, value};
143  }
144 private:
145  std::mutex mutable mutex;
146  T value;
147 };
148 
149 }
150 
151 #endif //MIR_SYNCHRONISED_H_

Copyright © 2012-2022 Canonical Ltd.
Generated on Thu Sep 8 12:37:23 UTC 2022
This documentation is licensed under the GPL version 2 or 3.