1 | #pragma once |
2 | |
3 | #include <mutex> |
4 | |
5 | #include <c10/util/C++17.h> |
6 | |
7 | namespace c10 { |
8 | |
9 | /** |
10 | * A very simple Synchronization class for error-free use of data |
11 | * in a multi-threaded context. See folly/docs/Synchronized.md for |
12 | * the inspiration of this class. |
13 | * |
14 | * Full URL: |
15 | * https://github.com/facebook/folly/blob/main/folly/docs/Synchronized.md |
16 | * |
17 | * This class implements a small subset of the generic functionality |
18 | * implemented by folly:Synchronized<T>. Specifically, only withLock<T> |
19 | * is implemeted here since it's the smallest possible API that is |
20 | * able to cover a large surface area of functionality offered by |
21 | * folly::Synchronized<T>. |
22 | */ |
23 | template <typename T> |
24 | class Synchronized final { |
25 | mutable std::mutex mutex_; |
26 | T data_; |
27 | |
28 | public: |
29 | Synchronized() = default; |
30 | Synchronized(T const& data) : data_(data) {} |
31 | Synchronized(T&& data) : data_(data) {} |
32 | |
33 | // Don't permit copy construction, move, assignment, or |
34 | // move assignment, since the underlying std::mutex |
35 | // isn't necessarily copyable/moveable. |
36 | Synchronized(Synchronized const&) = delete; |
37 | Synchronized(Synchronized&&) = delete; |
38 | Synchronized operator=(Synchronized const&) = delete; |
39 | Synchronized operator=(Synchronized&&) = delete; |
40 | |
41 | /** |
42 | * To use, call withLock<T> with a callback that accepts T either |
43 | * by copy or by reference. Use the protected variable in the |
44 | * provided callback safely. |
45 | */ |
46 | template <typename CB> |
47 | typename c10::invoke_result_t<CB, T&> withLock(CB cb) { |
48 | std::lock_guard<std::mutex> guard(this->mutex_); |
49 | return cb(this->data_); |
50 | } |
51 | |
52 | /** |
53 | * To use, call withLock<T> with a callback that accepts T either |
54 | * by copy or by const reference. Use the protected variable in |
55 | * the provided callback safely. |
56 | */ |
57 | template <typename CB> |
58 | typename c10::invoke_result_t<CB, T const&> withLock(CB cb) const { |
59 | std::lock_guard<std::mutex> guard(this->mutex_); |
60 | return cb(this->data_); |
61 | } |
62 | }; |
63 | } // end namespace c10 |
64 | |