Toplevel entrypoints for classes/traits/interfaces
[hiphop-php.git] / hphp / util / synchronizable-multi.cpp
blob53d01343fc8d6e1fdf14a75ed93070f5f38b76e1
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 #include "hphp/util/synchronizable-multi.h"
18 #include "hphp/util/compatibility.h"
19 #include "hphp/util/lock.h"
20 #include "hphp/util/rank.h"
21 #include "hphp/util/timer.h"
23 #ifndef _MSC_VER
24 #include <sys/errno.h>
25 #endif
27 namespace HPHP {
28 ///////////////////////////////////////////////////////////////////////////////
30 SynchronizableMulti::SynchronizableMulti(int size) :
31 m_mutex(RankLeaf), m_group(0), m_conds(size), m_cond_list_vec(1) {
32 assert(size > 0);
35 inline
36 bool SynchronizableMulti::waitImpl(int id, int q, Priority pri, timespec *ts) {
37 assert(id >= 0 && id < m_conds.size());
38 auto& cond = m_conds[id];
40 assert(q >= 0);
41 const uint32_t num_lists = m_cond_list_vec.size();
42 uint32_t list_index = 0;
43 if (num_lists == 2) list_index = q & 1;
44 else if (num_lists > 2) list_index = q % num_lists;
45 auto& cond_list = m_cond_list_vec[list_index];
47 cond_list.push(cond, pri);
49 int ret;
50 if (ts) {
51 ret = pthread_cond_timedwait(cond, &m_mutex.getRaw(), ts);
52 } else {
53 ret = pthread_cond_wait(cond, &m_mutex.getRaw());
55 assert(ret != EPERM); // did you lock the mutex?
57 if (ret) {
58 cond.unlink();
61 return ret != ETIMEDOUT;
64 void SynchronizableMulti::wait(int id, int q, Priority pri) {
65 waitImpl(id, q, pri, nullptr);
68 bool SynchronizableMulti::wait(int id, int q, Priority pri, long seconds) {
69 return wait(id, q, pri, seconds, 0);
72 bool SynchronizableMulti::wait(int id, int q, Priority pri, long seconds,
73 long long nanosecs) {
74 struct timespec ts;
75 Timer::GetRealtimeTime(ts);
76 ts.tv_sec += seconds;
77 ts.tv_nsec += nanosecs;
78 return waitImpl(id, q, pri, &ts);
81 void SynchronizableMulti::setNumGroups(int num_groups) {
82 Lock l(this);
83 if (num_groups != m_cond_list_vec.size()) {
84 assert(num_groups > m_cond_list_vec.size());
85 m_cond_list_vec.resize(num_groups);
89 void SynchronizableMulti::notifySpecific(int id) {
90 assert(id >= 0 && id < m_conds.size());
91 auto& cond = m_conds[id];
92 pthread_cond_signal(cond);
93 cond.unlink();
96 void SynchronizableMulti::notify() {
97 for (int i = 0, s = m_cond_list_vec.size(); i < s; i++) {
98 assert(m_group < s);
99 auto& cond_list = m_cond_list_vec[m_group++];
100 if (m_group == s) m_group = 0;
101 if (!cond_list.empty()) {
102 auto& cond = cond_list.front();
103 pthread_cond_signal(cond);
104 cond_list.pop_front();
105 break;
110 void SynchronizableMulti::notifyAll() {
111 for (auto& cond_list : m_cond_list_vec) {
112 while (!cond_list.empty()) {
113 pthread_cond_signal(cond_list.front());
114 cond_list.pop_front();
119 ///////////////////////////////////////////////////////////////////////////////