Fabcoin Core  0.16.2
P2P Digital Currency
Guards.h
Go to the documentation of this file.
1 /*
2  This file is part of cpp-ethereum.
3 
4  cpp-ethereum is free software: you can redistribute it and/or modify
5  it under the terms of the GNU General Public License as published by
6  the Free Software Foundation, either version 3 of the License, or
7  (at your option) any later version.
8 
9  cpp-ethereum is distributed in the hope that it will be useful,
10  but WITHOUT ANY WARRANTY; without even the implied warranty of
11  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12  GNU General Public License for more details.
13 
14  You should have received a copy of the GNU General Public License
15  along with cpp-ethereum. If not, see <http://www.gnu.org/licenses/>.
16 */
22 #pragma once
23 
24 #include <mutex>
25 #include <condition_variable>
26 #include <atomic>
27 #pragma warning(push)
28 #pragma GCC diagnostic push
29 #pragma GCC diagnostic ignored "-Wunused-parameter"
30 #include <boost/thread.hpp>
31 #pragma warning(pop)
32 #pragma GCC diagnostic pop
33 
34 namespace dev
35 {
36 
37 using Mutex = std::mutex;
38 using RecursiveMutex = std::recursive_mutex;
39 using SharedMutex = boost::shared_mutex;
40 
41 using Guard = std::lock_guard<std::mutex>;
42 using UniqueGuard = std::unique_lock<std::mutex>;
43 using RecursiveGuard = std::lock_guard<std::recursive_mutex>;
44 using ReadGuard = boost::shared_lock<boost::shared_mutex>;
45 using UpgradableGuard = boost::upgrade_lock<boost::shared_mutex>;
46 using UpgradeGuard = boost::upgrade_to_unique_lock<boost::shared_mutex>;
47 using WriteGuard = boost::unique_lock<boost::shared_mutex>;
48 
49 template <class GuardType, class MutexType>
50 struct GenericGuardBool: GuardType
51 {
52  GenericGuardBool(MutexType& _m): GuardType(_m) {}
53  bool b = true;
54 };
55 template <class MutexType>
57 {
58  GenericUnguardBool(MutexType& _m): m(_m) { m.unlock(); }
59  ~GenericUnguardBool() { m.lock(); }
60  bool b = true;
61  MutexType& m;
62 };
63 template <class MutexType>
65 {
66  GenericUnguardSharedBool(MutexType& _m): m(_m) { m.unlock_shared(); }
67  ~GenericUnguardSharedBool() { m.lock_shared(); }
68  bool b = true;
69  MutexType& m;
70 };
71 
73 class SpinLock
74 {
75 public:
76  SpinLock() { m_lock.clear(); }
77  void lock() { while (m_lock.test_and_set(std::memory_order_acquire)) {} }
78  void unlock() { m_lock.clear(std::memory_order_release); }
79 private:
80  std::atomic_flag m_lock;
81 };
82 using SpinGuard = std::lock_guard<SpinLock>;
83 
84 template <class N>
85 class Notified
86 {
87 public:
88  Notified() {}
89  Notified(N const& _v): m_value(_v) {}
90  Notified(Notified const&) = delete;
91  Notified& operator=(N const& _v) { UniqueGuard l(m_mutex); m_value = _v; m_cv.notify_all(); return *this; }
92 
93  operator N() const { UniqueGuard l(m_mutex); return m_value; }
94 
95  void wait() const { N old; { UniqueGuard l(m_mutex); old = m_value; } waitNot(old); }
96  void wait(N const& _v) const { UniqueGuard l(m_mutex); m_cv.wait(l, [&](){return m_value == _v;}); }
97  void waitNot(N const& _v) const { UniqueGuard l(m_mutex); m_cv.wait(l, [&](){return m_value != _v;}); }
98  template <class F> void wait(F const& _f) const { UniqueGuard l(m_mutex); m_cv.wait(l, _f); }
99 
100  template <class R, class P> void wait(std::chrono::duration<R, P> _d) const { N old; { UniqueGuard l(m_mutex); old = m_value; } waitNot(_d, old); }
101  template <class R, class P> void wait(std::chrono::duration<R, P> _d, N const& _v) const { UniqueGuard l(m_mutex); m_cv.wait_for(l, _d, [&](){return m_value == _v;}); }
102  template <class R, class P> void waitNot(std::chrono::duration<R, P> _d, N const& _v) const { UniqueGuard l(m_mutex); m_cv.wait_for(l, _d, [&](){return m_value != _v;}); }
103  template <class R, class P, class F> void wait(std::chrono::duration<R, P> _d, F const& _f) const { UniqueGuard l(m_mutex); m_cv.wait_for(l, _d, _f); }
104 
105 private:
106  mutable Mutex m_mutex;
107  mutable std::condition_variable m_cv;
109 };
110 
144 #define DEV_GUARDED(MUTEX) \
145  for (GenericGuardBool<Guard, Mutex> __eth_l(MUTEX); __eth_l.b; __eth_l.b = false)
146 #define DEV_READ_GUARDED(MUTEX) \
147  for (GenericGuardBool<ReadGuard, SharedMutex> __eth_l(MUTEX); __eth_l.b; __eth_l.b = false)
148 #define DEV_WRITE_GUARDED(MUTEX) \
149  for (GenericGuardBool<WriteGuard, SharedMutex> __eth_l(MUTEX); __eth_l.b; __eth_l.b = false)
150 #define DEV_RECURSIVE_GUARDED(MUTEX) \
151  for (GenericGuardBool<RecursiveGuard, RecursiveMutex> __eth_l(MUTEX); __eth_l.b; __eth_l.b = false)
152 #define DEV_UNGUARDED(MUTEX) \
153  for (GenericUnguardBool<Mutex> __eth_l(MUTEX); __eth_l.b; __eth_l.b = false)
154 #define DEV_READ_UNGUARDED(MUTEX) \
155  for (GenericUnguardSharedBool<SharedMutex> __eth_l(MUTEX); __eth_l.b; __eth_l.b = false)
156 #define DEV_WRITE_UNGUARDED(MUTEX) \
157  for (GenericUnguardBool<SharedMutex> __eth_l(MUTEX); __eth_l.b; __eth_l.b = false)
158 
159 }
GenericUnguardBool(MutexType &_m)
Definition: Guards.h:58
GenericUnguardSharedBool(MutexType &_m)
Definition: Guards.h:66
void lock()
Definition: Guards.h:77
Adapted from code found on http://stackoverflow.com/questions/180947/base64-decode-snippet-in-c Origi...
Definition: Arith256.cpp:15
MutexType & m
Definition: Guards.h:61
boost::upgrade_to_unique_lock< boost::shared_mutex > UpgradeGuard
Definition: Guards.h:46
Simple lock that waits for release without making context switch.
Definition: Guards.h:73
boost::upgrade_lock< boost::shared_mutex > UpgradableGuard
Definition: Guards.h:45
GenericGuardBool(MutexType &_m)
Definition: Guards.h:52
std::unique_lock< std::mutex > UniqueGuard
Definition: Guards.h:42
std::recursive_mutex RecursiveMutex
Definition: Guards.h:38
void wait(F const &_f) const
Definition: Guards.h:98
void wait(std::chrono::duration< R, P > _d, N const &_v) const
Definition: Guards.h:101
Mutex m_mutex
Definition: Guards.h:106
std::lock_guard< std::mutex > Guard
Definition: Guards.h:41
Notified(N const &_v)
Definition: Guards.h:89
void wait(std::chrono::duration< R, P > _d) const
Definition: Guards.h:100
Notified & operator=(N const &_v)
Definition: Guards.h:91
std::lock_guard< SpinLock > SpinGuard
Definition: Guards.h:82
void waitNot(N const &_v) const
Definition: Guards.h:97
boost::shared_lock< boost::shared_mutex > ReadGuard
Definition: Guards.h:44
#define F(x, y, z)
Definition: Hash.cpp:79
boost::unique_lock< boost::shared_mutex > WriteGuard
Definition: Guards.h:47
void wait() const
Definition: Guards.h:95
std::atomic_flag m_lock
Definition: Guards.h:80
void unlock()
Definition: Guards.h:78
std::condition_variable m_cv
Definition: Guards.h:107
boost::shared_mutex SharedMutex
Definition: Guards.h:39
std::lock_guard< std::recursive_mutex > RecursiveGuard
Definition: Guards.h:43
std::mutex Mutex
Definition: Guards.h:37
void wait(std::chrono::duration< R, P > _d, F const &_f) const
Definition: Guards.h:103
void wait(N const &_v) const
Definition: Guards.h:96
void waitNot(std::chrono::duration< R, P > _d, N const &_v) const
Definition: Guards.h:102