make (array) of ArrayObject return the contents
[hiphop-php.git] / hphp / util / lock.h
blobca65488746c7c40bccc0c63c0591b3690ce276d5
1 /*
2 +----------------------------------------------------------------------+
3 | HipHop for PHP |
4 +----------------------------------------------------------------------+
5 | Copyright (c) 2010-2013 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 class LockProfiler {
31 public:
32 typedef void (*PFUNC_PROFILE)(const std::string &stack, int64_t elapsed_us);
33 static PFUNC_PROFILE s_pfunc_profile;
34 static bool s_profile;
35 static int s_profile_sampling;
37 explicit LockProfiler(bool profile);
38 ~LockProfiler();
40 private:
41 bool m_profiling;
42 timespec m_lockTime;
45 ///////////////////////////////////////////////////////////////////////////////
47 template <typename MutexT>
48 class BaseConditionalLock {
49 public:
50 BaseConditionalLock(MutexT &mutex, bool condition, bool profile = true)
51 : m_profiler(profile), m_mutex(mutex), m_acquired(false) {
52 if (condition) {
53 m_mutex.lock(); // must not throw
54 m_acquired = true;
57 ~BaseConditionalLock() {
58 if (m_acquired) {
59 m_mutex.unlock(); // must not throw
62 private:
63 LockProfiler m_profiler;
64 MutexT& m_mutex;
65 bool m_acquired;
68 class ConditionalLock : public BaseConditionalLock<Mutex> {
69 public:
70 ConditionalLock(Mutex &mutex,
71 bool condition, bool profile = true)
72 : BaseConditionalLock<Mutex>(mutex, condition, profile)
74 ConditionalLock(Synchronizable *obj,
75 bool condition, bool profile = true)
76 : BaseConditionalLock<Mutex>(obj->getMutex(), condition, profile)
78 ConditionalLock(SynchronizableMulti *obj,
79 bool condition, bool profile = true)
80 : BaseConditionalLock<Mutex>(obj->getMutex(), condition, profile)
84 /**
85 * Just a helper class that automatically unlocks a mutex when it goes out of
86 * scope.
88 * {
89 * Lock lock(mutex);
90 * // inside lock
91 * } // unlock here
93 class Lock : public ConditionalLock {
94 public:
95 explicit Lock(Mutex &mutex, bool profile = true)
96 : ConditionalLock(mutex, true, profile) {}
97 explicit Lock(Synchronizable *obj, bool profile = true)
98 : ConditionalLock(obj, true, profile) {}
99 explicit Lock(SynchronizableMulti *obj, bool profile = true)
100 : ConditionalLock(obj, true, profile) {}
103 class ScopedUnlock {
104 public:
105 explicit ScopedUnlock(Mutex &mutex) : m_mutex(mutex) {
106 m_mutex.unlock();
108 explicit ScopedUnlock(Synchronizable *obj) : m_mutex(obj->getMutex()) {
109 m_mutex.unlock();
111 explicit ScopedUnlock(SynchronizableMulti *obj) : m_mutex(obj->getMutex()) {
112 m_mutex.unlock();
115 ~ScopedUnlock() {
116 m_mutex.lock();
119 private:
120 Mutex &m_mutex;
123 class SimpleConditionalLock : public BaseConditionalLock<SimpleMutex> {
124 public:
125 SimpleConditionalLock(SimpleMutex &mutex,
126 bool condition, bool profile = true)
127 : BaseConditionalLock<SimpleMutex>(mutex, condition, profile)
129 if (condition) {
130 mutex.assertOwnedBySelf();
135 class SimpleLock : public SimpleConditionalLock {
136 public:
137 explicit SimpleLock(SimpleMutex &mutex, bool profile = true)
138 : SimpleConditionalLock(mutex, true, profile) {}
141 ///////////////////////////////////////////////////////////////////////////////
143 class ConditionalReadLock {
144 public:
145 ConditionalReadLock(ReadWriteMutex &mutex, bool condition,
146 bool profile = true)
147 : m_profiler(profile), m_mutex(mutex), m_acquired(false) {
148 if (condition) {
149 m_mutex.acquireRead();
150 m_acquired = true;
154 ~ConditionalReadLock() {
155 if (m_acquired) {
156 m_mutex.release();
160 private:
161 LockProfiler m_profiler;
162 ReadWriteMutex &m_mutex;
163 bool m_acquired;
166 class ReadLock : public ConditionalReadLock {
167 public:
168 explicit ReadLock(ReadWriteMutex &mutex, bool profile = true)
169 : ConditionalReadLock(mutex, true, profile) {}
172 class WriteLock {
173 public:
174 explicit WriteLock(ReadWriteMutex &mutex, bool profile = true)
175 : m_profiler(profile), m_mutex(mutex) {
176 m_mutex.acquireWrite();
179 ~WriteLock() {
180 m_mutex.release();
183 private:
184 LockProfiler m_profiler;
185 ReadWriteMutex &m_mutex;
188 ///////////////////////////////////////////////////////////////////////////////
191 #endif // incl_HPHP_LOCK_H_