Arquivos
hhvm/hphp/util/lock.h
T
Tim Starling 998951619f update copyright date
We did not intend to imply our copyrights last forever

Closes #759
2013-06-03 12:43:56 -07:00

196 linhas
5.2 KiB
C++

/*
+----------------------------------------------------------------------+
| HipHop for PHP |
+----------------------------------------------------------------------+
| Copyright (c) 2010-2013 Facebook, Inc. (http://www.facebook.com) |
+----------------------------------------------------------------------+
| This source file is subject to version 3.01 of the PHP license, |
| that is bundled with this package in the file LICENSE, and is |
| available through the world-wide-web at the following url: |
| http://www.php.net/license/3_01.txt |
| If you did not receive a copy of the PHP license and are unable to |
| obtain it through the world-wide-web, please send a note to |
| license@php.net so we can mail you a copy immediately. |
+----------------------------------------------------------------------+
*/
#ifndef incl_HPHP_LOCK_H_
#define incl_HPHP_LOCK_H_
#include "hphp/util/mutex.h"
#include "hphp/util/synchronizable.h"
#include "hphp/util/synchronizable_multi.h"
namespace HPHP {
///////////////////////////////////////////////////////////////////////////////
/**
* Lock instrumentation for mutex stats.
*/
class LockProfiler {
public:
typedef void (*PFUNC_PROFILE)(const std::string &stack, int64_t elapsed_us);
static PFUNC_PROFILE s_pfunc_profile;
static bool s_profile;
static int s_profile_sampling;
explicit LockProfiler(bool profile);
~LockProfiler();
private:
bool m_profiling;
#if defined(__APPLE__)
timeval m_lockTime;
#else
timespec m_lockTime;
#endif
};
///////////////////////////////////////////////////////////////////////////////
template <typename MutexT>
class BaseConditionalLock {
public:
BaseConditionalLock(MutexT &mutex, bool condition, bool profile = true)
: m_profiler(profile), m_mutex(mutex), m_acquired(false) {
if (condition) {
m_mutex.lock(); // must not throw
m_acquired = true;
}
}
~BaseConditionalLock() {
if (m_acquired) {
m_mutex.unlock(); // must not throw
}
}
private:
LockProfiler m_profiler;
MutexT& m_mutex;
bool m_acquired;
};
class ConditionalLock : public BaseConditionalLock<Mutex> {
public:
ConditionalLock(Mutex &mutex,
bool condition, bool profile = true)
: BaseConditionalLock<Mutex>(mutex, condition, profile)
{}
ConditionalLock(Synchronizable *obj,
bool condition, bool profile = true)
: BaseConditionalLock<Mutex>(obj->getMutex(), condition, profile)
{}
ConditionalLock(SynchronizableMulti *obj,
bool condition, bool profile = true)
: BaseConditionalLock<Mutex>(obj->getMutex(), condition, profile)
{}
};
/**
* Just a helper class that automatically unlocks a mutex when it goes out of
* scope.
*
* {
* Lock lock(mutex);
* // inside lock
* } // unlock here
*/
class Lock : public ConditionalLock {
public:
explicit Lock(Mutex &mutex, bool profile = true)
: ConditionalLock(mutex, true, profile) {}
explicit Lock(Synchronizable *obj, bool profile = true)
: ConditionalLock(obj, true, profile) {}
explicit Lock(SynchronizableMulti *obj, bool profile = true)
: ConditionalLock(obj, true, profile) {}
};
class ScopedUnlock {
public:
explicit ScopedUnlock(Mutex &mutex) : m_mutex(mutex) {
m_mutex.unlock();
}
explicit ScopedUnlock(Synchronizable *obj) : m_mutex(obj->getMutex()) {
m_mutex.unlock();
}
explicit ScopedUnlock(SynchronizableMulti *obj) : m_mutex(obj->getMutex()) {
m_mutex.unlock();
}
~ScopedUnlock() {
m_mutex.lock();
}
private:
Mutex &m_mutex;
};
class SimpleConditionalLock : public BaseConditionalLock<SimpleMutex> {
public:
SimpleConditionalLock(SimpleMutex &mutex,
bool condition, bool profile = true)
: BaseConditionalLock<SimpleMutex>(mutex, condition, profile)
{
if (condition) {
mutex.assertOwnedBySelf();
}
}
};
class SimpleLock : public SimpleConditionalLock {
public:
explicit SimpleLock(SimpleMutex &mutex, bool profile = true)
: SimpleConditionalLock(mutex, true, profile) {}
};
///////////////////////////////////////////////////////////////////////////////
class ConditionalReadLock {
public:
ConditionalReadLock(ReadWriteMutex &mutex, bool condition,
bool profile = true)
: m_profiler(profile), m_mutex(mutex), m_acquired(false) {
if (condition) {
m_mutex.acquireRead();
m_acquired = true;
}
}
~ConditionalReadLock() {
if (m_acquired) {
m_mutex.release();
}
}
private:
LockProfiler m_profiler;
ReadWriteMutex &m_mutex;
bool m_acquired;
};
class ReadLock : public ConditionalReadLock {
public:
explicit ReadLock(ReadWriteMutex &mutex, bool profile = true)
: ConditionalReadLock(mutex, true, profile) {}
};
class WriteLock {
public:
explicit WriteLock(ReadWriteMutex &mutex, bool profile = true)
: m_profiler(profile), m_mutex(mutex) {
m_mutex.acquireWrite();
}
~WriteLock() {
m_mutex.release();
}
private:
LockProfiler m_profiler;
ReadWriteMutex &m_mutex;
};
///////////////////////////////////////////////////////////////////////////////
}
#endif // incl_HPHP_LOCK_H_