Arquivos
hhvm/hphp/util/synchronizable_multi.cpp
T
2013-07-09 13:45:35 -07:00

106 linhas
3.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. |
+----------------------------------------------------------------------+
*/
#include "hphp/util/synchronizable_multi.h"
#include "hphp/util/compatibility.h"
#include "hphp/util/timer.h"
namespace HPHP {
///////////////////////////////////////////////////////////////////////////////
SynchronizableMulti::SynchronizableMulti(int size) : m_mutex(RankLeaf) {
assert(size > 0);
m_conds.resize(size);
for (unsigned int i = 0; i < m_conds.size(); i++) {
pthread_cond_init(&m_conds[i], nullptr);
}
}
SynchronizableMulti::~SynchronizableMulti() {
for (unsigned int i = 0; i < m_conds.size(); i++) {
pthread_cond_destroy(&m_conds[i]);
}
}
void SynchronizableMulti::wait(int id, bool front) {
waitImpl(id, front, nullptr);
}
bool SynchronizableMulti::wait(int id, bool front, long seconds) {
return wait(id, front, seconds, 0);
}
bool SynchronizableMulti::wait(int id, bool front, long seconds,
long long nanosecs) {
struct timespec ts;
Timer::GetRealtimeTime(ts);
ts.tv_sec += seconds;
ts.tv_nsec += nanosecs;
return waitImpl(id, front, &ts);
}
bool SynchronizableMulti::waitImpl(int id, bool front, timespec *ts) {
assert(id >= 0);
int index = id % m_conds.size();
pthread_cond_t *cond = &m_conds[index];
if (front) {
m_cond_list.push_front(cond);
m_cond_map.insert(make_pair(cond, m_cond_list.begin()));
} else {
m_cond_list.push_back(cond);
m_cond_map.insert(make_pair(cond, --m_cond_list.end()));
}
int ret;
if (ts) {
ret = pthread_cond_timedwait(cond, &m_mutex.getRaw(), ts);
} else {
ret = pthread_cond_wait(cond, &m_mutex.getRaw());
}
assert(ret != EPERM); // did you lock the mutex?
if (ret) {
CondIterMap::iterator iter = m_cond_map.find(cond);
if (iter != m_cond_map.end()) {
m_cond_list.erase(iter->second);
m_cond_map.erase(iter);
}
}
return ret != ETIMEDOUT;
}
void SynchronizableMulti::notify() {
if (!m_cond_list.empty()) {
pthread_cond_t *cond = m_cond_list.front();
pthread_cond_signal(cond);
m_cond_list.pop_front();
m_cond_map.erase(cond);
}
}
void SynchronizableMulti::notifyAll() {
while (!m_cond_list.empty()) {
pthread_cond_signal(m_cond_list.front());
m_cond_list.pop_front();
}
m_cond_map.clear();
}
///////////////////////////////////////////////////////////////////////////////
}