2 +----------------------------------------------------------------------+
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"
24 #include <sys/errno.h>
28 ///////////////////////////////////////////////////////////////////////////////
30 SynchronizableMulti::SynchronizableMulti(int size
) :
31 m_mutex(RankLeaf
), m_group(0), m_conds(size
), m_cond_list_vec(1) {
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
];
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
);
51 ret
= pthread_cond_timedwait(cond
, &m_mutex
.getRaw(), ts
);
53 ret
= pthread_cond_wait(cond
, &m_mutex
.getRaw());
55 assert(ret
!= EPERM
); // did you lock the mutex?
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
,
75 Timer::GetRealtimeTime(ts
);
77 ts
.tv_nsec
+= nanosecs
;
78 return waitImpl(id
, q
, pri
, &ts
);
81 void SynchronizableMulti::setNumGroups(int num_groups
) {
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
);
96 void SynchronizableMulti::notify() {
97 for (int i
= 0, s
= m_cond_list_vec
.size(); i
< s
; i
++) {
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();
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 ///////////////////////////////////////////////////////////////////////////////