Add logging for comparison behaviors
[hiphop-php.git] / hphp / util / lock.h
blob7a74bc1050f0b334290f7fcfec7e6ac17dbc0016
1 /*
2 +----------------------------------------------------------------------+
3 | HipHop for PHP |
4 +----------------------------------------------------------------------+
5 | Copyright (c) 2010-present Facebook, Inc. (http://www.facebook.com) |
6 +----------------------------------------------------------------------+
7 | This source file is subject to version 3.01 of the PHP license, |
8 | that is bundled with this package in the file LICENSE, and is |
9 | available through the world-wide-web at the following url: |
10 | http://www.php.net/license/3_01.txt |
11 | If you did not receive a copy of the PHP license and are unable to |
12 | obtain it through the world-wide-web, please send a note to |
13 | license@php.net so we can mail you a copy immediately. |
14 +----------------------------------------------------------------------+
17 #ifndef incl_HPHP_LOCK_H_
18 #define incl_HPHP_LOCK_H_
20 #include "hphp/util/mutex.h"
21 #include "hphp/util/synchronizable.h"
22 #include "hphp/util/synchronizable-multi.h"
24 namespace HPHP {
25 ///////////////////////////////////////////////////////////////////////////////
27 /**
28 * Lock instrumentation for mutex stats.
30 struct LockProfiler {
31 typedef void (*PFUNC_PROFILE)(const std::string &stack, int64_t elapsed_us);
32 static PFUNC_PROFILE s_pfunc_profile;
33 static bool s_profile;
34 static int s_profile_sampling;
36 explicit LockProfiler(bool profile);
37 ~LockProfiler();
39 private:
40 bool m_profiling;
41 timespec m_lockTime;
44 ///////////////////////////////////////////////////////////////////////////////
46 template <typename MutexT>
47 struct BaseConditionalLock {
48 BaseConditionalLock(MutexT &mutex, bool condition, bool profile = true)
49 : m_profiler(profile), m_mutex(mutex), m_acquired(false) {
50 if (condition) {
51 m_mutex.lock(); // must not throw
52 m_acquired = true;
55 ~BaseConditionalLock() {
56 if (m_acquired) {
57 m_mutex.unlock(); // must not throw
60 private:
61 LockProfiler m_profiler;
62 MutexT& m_mutex;
63 bool m_acquired;
66 struct ConditionalLock : BaseConditionalLock<Mutex> {
67 ConditionalLock(Mutex &mutex,
68 bool condition, bool profile = true)
69 : BaseConditionalLock<Mutex>(mutex, condition, profile)
71 ConditionalLock(Synchronizable *obj,
72 bool condition, bool profile = true)
73 : BaseConditionalLock<Mutex>(obj->getMutex(), condition, profile)
75 ConditionalLock(SynchronizableMulti *obj,
76 bool condition, bool profile = true)
77 : BaseConditionalLock<Mutex>(obj->getMutex(), condition, profile)
81 /**
82 * Just a helper class that automatically unlocks a mutex when it goes out of
83 * scope.
85 * {
86 * Lock lock(mutex);
87 * // inside lock
88 * } // unlock here
90 struct Lock : ConditionalLock {
91 explicit Lock(Mutex &mutex, bool profile = true)
92 : ConditionalLock(mutex, true, profile) {}
93 explicit Lock(Synchronizable *obj, bool profile = true)
94 : ConditionalLock(obj, true, profile) {}
95 explicit Lock(SynchronizableMulti *obj, bool profile = true)
96 : ConditionalLock(obj, true, profile) {}
99 struct ScopedUnlock {
100 explicit ScopedUnlock(Mutex &mutex) : m_mutex(mutex) {
101 m_mutex.unlock();
103 explicit ScopedUnlock(Synchronizable *obj) : m_mutex(obj->getMutex()) {
104 m_mutex.unlock();
106 explicit ScopedUnlock(SynchronizableMulti *obj) : m_mutex(obj->getMutex()) {
107 m_mutex.unlock();
110 ~ScopedUnlock() {
111 m_mutex.lock();
114 private:
115 Mutex &m_mutex;
118 struct SimpleConditionalLock : BaseConditionalLock<SimpleMutex> {
119 SimpleConditionalLock(SimpleMutex &mutex,
120 bool condition, bool profile = true)
121 : BaseConditionalLock<SimpleMutex>(mutex, condition, profile)
123 if (condition) {
124 mutex.assertOwnedBySelf();
129 struct SimpleLock : SimpleConditionalLock {
130 explicit SimpleLock(SimpleMutex &mutex, bool profile = true)
131 : SimpleConditionalLock(mutex, true, profile) {}
134 ///////////////////////////////////////////////////////////////////////////////
136 struct ReadLock {
137 explicit ReadLock(ReadWriteMutex& mutex, bool profile = true)
138 : m_profiler(profile)
139 , m_mutex(mutex)
141 m_mutex.acquireRead();
144 ReadLock(const ReadLock&) = delete;
145 ReadLock& operator=(const ReadLock&) = delete;
147 ~ReadLock() {
148 m_mutex.release();
151 private:
152 LockProfiler m_profiler;
153 ReadWriteMutex& m_mutex;
156 struct WriteLock {
157 explicit WriteLock(ReadWriteMutex& mutex, bool profile = true)
158 : m_profiler(profile)
159 , m_mutex(mutex)
161 m_mutex.acquireWrite();
164 WriteLock(const WriteLock&) = delete;
165 WriteLock& operator=(const WriteLock&) = delete;
167 ~WriteLock() {
168 m_mutex.release();
171 private:
172 LockProfiler m_profiler;
173 ReadWriteMutex& m_mutex;
176 ///////////////////////////////////////////////////////////////////////////////
179 #endif // incl_HPHP_LOCK_H_