Overte C++ Documentation
ReadWriteLockable.h
1 //
2 // Created by Bradley Austin Davis on 2015/09/10
3 // Copyright 2013-2015 High Fidelity, Inc.
4 //
5 // Distributed under the Apache License, Version 2.0.
6 // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
7 //
8 
9 #pragma once
10 #ifndef hifi_ReadWriteLockable_h
11 #define hifi_ReadWriteLockable_h
12 
13 #include <utility>
14 
15 #include <QtCore/QReadWriteLock>
16 
17 #include "QTryReadLocker.h"
18 #include "QTryWriteLocker.h"
19 
20 class ReadWriteLockable {
21 public:
22  // Write locks
23  template <typename F>
24  void withWriteLock(F&& f) const;
25 
26  template <typename T, typename F>
27  T resultWithWriteLock(F&& f) const;
28 
29  template <typename F>
30  bool withWriteLock(F&& f, bool require) const;
31 
32  template <typename F>
33  bool withTryWriteLock(F&& f) const;
34 
35  template <typename F>
36  bool withTryWriteLock(F&& f, int timeout) const;
37 
38  // Read locks
39  template <typename F>
40  void withReadLock(F&& f) const;
41 
42  template <typename T, typename F>
43  T resultWithReadLock(F&& f) const;
44 
45  template <typename F>
46  bool withReadLock(F&& f, bool require) const;
47 
48  template <typename F>
49  bool withTryReadLock(F&& f) const;
50 
51  template <typename F>
52  bool withTryReadLock(F&& f, int timeout) const;
53 
54  QReadWriteLock& getLock() const { return _lock; }
55 
56 private:
57  mutable QReadWriteLock _lock { QReadWriteLock::Recursive };
58 };
59 
60 // ReadWriteLockable
61 template <typename F>
62 inline void ReadWriteLockable::withWriteLock(F&& f) const {
63  QWriteLocker locker(&_lock);
64  f();
65 }
66 
67 template <typename F>
68 inline bool ReadWriteLockable::withWriteLock(F&& f, bool require) const {
69  if (require) {
70  withWriteLock(std::forward<F>(f));
71  return true;
72  } else {
73  return withTryReadLock(std::forward<F>(f));
74  }
75 }
76 
77 template <typename T, typename F>
78 inline T ReadWriteLockable::resultWithWriteLock(F&& f) const {
79  T result;
80  withWriteLock([&] {
81  result = f();
82  });
83  return result;
84 }
85 
86 template <typename F>
87 inline bool ReadWriteLockable::withTryWriteLock(F&& f) const {
88  QTryWriteLocker locker(&_lock);
89  if (locker.isLocked()) {
90  f();
91  return true;
92  }
93  return false;
94 }
95 
96 template <typename F>
97 inline bool ReadWriteLockable::withTryWriteLock(F&& f, int timeout) const {
98  QTryWriteLocker locker(&_lock, timeout);
99  if (locker.isLocked()) {
100  f();
101  return true;
102  }
103  return false;
104 }
105 
106 template <typename F>
107 inline void ReadWriteLockable::withReadLock(F&& f) const {
108  QReadLocker locker(&_lock);
109  f();
110 }
111 
112 template <typename T, typename F>
113 inline T ReadWriteLockable::resultWithReadLock(F&& f) const {
114  T result;
115  withReadLock([&] {
116  result = f();
117  });
118  return result;
119 }
120 
121 template <typename F>
122 inline bool ReadWriteLockable::withReadLock(F&& f, bool require) const {
123  if (require) {
124  withReadLock(std::forward<F>(f));
125  return true;
126  } else {
127  return withTryReadLock(std::forward<F>(f));
128  }
129 }
130 
131 template <typename F>
132 inline bool ReadWriteLockable::withTryReadLock(F&& f) const {
133  QTryReadLocker locker(&_lock);
134  if (locker.isLocked()) {
135  f();
136  return true;
137  }
138  return false;
139 }
140 
141 template <typename F>
142 inline bool ReadWriteLockable::withTryReadLock(F&& f, int timeout) const {
143  QTryReadLocker locker(&_lock, timeout);
144  if (locker.isLocked()) {
145  f();
146  return true;
147  }
148  return false;
149 }
150 
151 
152 #endif