Skip to content

Commit 4f75a4d

Browse files
committed
Added Swoole\Thread\Barrier
1 parent 105eea8 commit 4f75a4d

10 files changed

+206
-10
lines changed

ext-src/php_swoole.cc

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -766,6 +766,7 @@ PHP_MINIT_FUNCTION(swoole) {
766766
php_swoole_thread_minit(module_number);
767767
php_swoole_thread_atomic_minit(module_number);
768768
php_swoole_thread_lock_minit(module_number);
769+
php_swoole_thread_barrier_minit(module_number);
769770
php_swoole_thread_queue_minit(module_number);
770771
php_swoole_thread_map_minit(module_number);
771772
php_swoole_thread_arraylist_minit(module_number);

ext-src/php_swoole_private.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -271,6 +271,7 @@ void php_swoole_name_resolver_minit(int module_number);
271271
void php_swoole_thread_minit(int module_number);
272272
void php_swoole_thread_atomic_minit(int module_number);
273273
void php_swoole_thread_lock_minit(int module_number);
274+
void php_swoole_thread_barrier_minit(int module_number);
274275
void php_swoole_thread_queue_minit(int module_number);
275276
void php_swoole_thread_map_minit(int module_number);
276277
void php_swoole_thread_arraylist_minit(int module_number);
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
<?php
2+
namespace Swoole\Thread {
3+
class Barrier {
4+
public function __construct(int $count) {}
5+
public function wait(): void {}
6+
public function __wakeup(): void {}
7+
}
8+
}
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
/* This is a generated file, edit the .stub.php file instead.
2+
* Stub hash: eac62993bfb3fbd87587a8e6997c16bca7dc5dbc */
3+
4+
ZEND_BEGIN_ARG_INFO_EX(arginfo_class_Swoole_Thread_Barrier___construct, 0, 0, 1)
5+
ZEND_ARG_TYPE_INFO(0, count, IS_LONG, 0)
6+
ZEND_END_ARG_INFO()
7+
8+
ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_class_Swoole_Thread_Barrier_wait, 0, 0, IS_VOID, 0)
9+
ZEND_END_ARG_INFO()
10+
11+
#define arginfo_class_Swoole_Thread_Barrier___wakeup arginfo_class_Swoole_Thread_Barrier_wait

ext-src/swoole_thread_atomic.cc

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -114,19 +114,15 @@ static PHP_METHOD(swoole_thread_atomic, set);
114114
static PHP_METHOD(swoole_thread_atomic, cmpset);
115115
static PHP_METHOD(swoole_thread_atomic, wait);
116116
static PHP_METHOD(swoole_thread_atomic, wakeup);
117-
#ifdef SW_THREAD
118117
static PHP_METHOD(swoole_thread_atomic, __wakeup);
119-
#endif
120118

121119
static PHP_METHOD(swoole_thread_atomic_long, __construct);
122120
static PHP_METHOD(swoole_thread_atomic_long, add);
123121
static PHP_METHOD(swoole_thread_atomic_long, sub);
124122
static PHP_METHOD(swoole_thread_atomic_long, get);
125123
static PHP_METHOD(swoole_thread_atomic_long, set);
126124
static PHP_METHOD(swoole_thread_atomic_long, cmpset);
127-
#ifdef SW_THREAD
128125
static PHP_METHOD(swoole_thread_atomic_long, __wakeup);
129-
#endif
130126
SW_EXTERN_C_END
131127

132128
// clang-format off

ext-src/swoole_thread_barrier.cc

Lines changed: 145 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,145 @@
1+
/*
2+
+----------------------------------------------------------------------+
3+
| Swoole |
4+
+----------------------------------------------------------------------+
5+
| This source file is subject to version 2.0 of the Apache license, |
6+
| that is bundled with this package in the file LICENSE, and is |
7+
| available through the world-wide-web at the following url: |
8+
| http://www.apache.org/licenses/LICENSE-2.0.html |
9+
| If you did not receive a copy of the Apache2.0 license and are unable|
10+
| to obtain it through the world-wide-web, please send a note to |
11+
| [email protected] so we can mail you a copy immediately. |
12+
+----------------------------------------------------------------------+
13+
| Author: Tianfeng Han <[email protected]> |
14+
+----------------------------------------------------------------------+
15+
*/
16+
17+
#include "php_swoole_private.h"
18+
#include "php_swoole_thread.h"
19+
#include "swoole_memory.h"
20+
#include "swoole_lock.h"
21+
22+
#ifdef SW_THREAD
23+
24+
BEGIN_EXTERN_C()
25+
#include "stubs/php_swoole_thread_barrier_arginfo.h"
26+
END_EXTERN_C()
27+
28+
using swoole::Barrier;
29+
30+
static zend_class_entry *swoole_thread_barrier_ce;
31+
static zend_object_handlers swoole_thread_barrier_handlers;
32+
33+
34+
struct BarrierResource : public ThreadResource {
35+
Barrier barrier_;
36+
BarrierResource(int count) : ThreadResource() {
37+
barrier_.init(false, count);
38+
}
39+
void wait() {
40+
barrier_.wait();
41+
}
42+
~BarrierResource() {
43+
barrier_.destroy();
44+
}
45+
};
46+
47+
struct BarrierObject {
48+
BarrierResource *barrier;
49+
zend_object std;
50+
};
51+
52+
static sw_inline BarrierObject *php_swoole_thread_barrier_fetch_object(zend_object *obj) {
53+
return (BarrierObject *) ((char *) obj - swoole_thread_barrier_handlers.offset);
54+
}
55+
56+
static BarrierResource *php_swoole_thread_barrier_get_ptr(zval *zobject) {
57+
return php_swoole_thread_barrier_fetch_object(Z_OBJ_P(zobject))->barrier;
58+
}
59+
60+
static BarrierResource *php_swoole_thread_barrier_get_and_check_ptr(zval *zobject) {
61+
BarrierResource *barrier = php_swoole_thread_barrier_get_ptr(zobject);
62+
if (!barrier) {
63+
php_swoole_fatal_error(E_ERROR, "must call constructor first");
64+
}
65+
return barrier;
66+
}
67+
68+
static void php_swoole_thread_barrier_free_object(zend_object *object) {
69+
BarrierObject *bo = php_swoole_thread_barrier_fetch_object(object);
70+
zend_long resource_id = zend::object_get_long(object, ZEND_STRL("id"));
71+
if (bo->barrier && php_swoole_thread_resource_free(resource_id, bo->barrier)) {
72+
delete bo->barrier;
73+
bo->barrier = nullptr;
74+
}
75+
zend_object_std_dtor(object);
76+
}
77+
78+
static zend_object *php_swoole_thread_barrier_create_object(zend_class_entry *ce) {
79+
BarrierObject *bo = (BarrierObject *) zend_object_alloc(sizeof(BarrierObject), ce);
80+
zend_object_std_init(&bo->std, ce);
81+
object_properties_init(&bo->std, ce);
82+
bo->std.handlers = &swoole_thread_barrier_handlers;
83+
return &bo->std;
84+
}
85+
86+
SW_EXTERN_C_BEGIN
87+
static PHP_METHOD(swoole_thread_barrier, __construct);
88+
static PHP_METHOD(swoole_thread_barrier, wait);
89+
static PHP_METHOD(swoole_thread_barrier, __wakeup);
90+
SW_EXTERN_C_END
91+
92+
// clang-format off
93+
static const zend_function_entry swoole_thread_barrier_methods[] =
94+
{
95+
PHP_ME(swoole_thread_barrier, __construct, arginfo_class_Swoole_Thread_Barrier___construct, ZEND_ACC_PUBLIC)
96+
PHP_ME(swoole_thread_barrier, wait, arginfo_class_Swoole_Thread_Barrier_wait, ZEND_ACC_PUBLIC)
97+
PHP_ME(swoole_thread_barrier, __wakeup, arginfo_class_Swoole_Thread_Barrier___wakeup, ZEND_ACC_PUBLIC)
98+
PHP_FE_END
99+
};
100+
// clang-format on
101+
102+
void php_swoole_thread_barrier_minit(int module_number) {
103+
SW_INIT_CLASS_ENTRY(swoole_thread_barrier, "Swoole\\Thread\\Barrier", nullptr, swoole_thread_barrier_methods);
104+
zend_declare_property_long(swoole_thread_barrier_ce, ZEND_STRL("id"), 0, ZEND_ACC_PUBLIC);
105+
SW_SET_CLASS_CLONEABLE(swoole_thread_barrier, sw_zend_class_clone_deny);
106+
SW_SET_CLASS_UNSET_PROPERTY_HANDLER(swoole_thread_barrier, sw_zend_class_unset_property_deny);
107+
SW_SET_CLASS_CUSTOM_OBJECT(
108+
swoole_thread_barrier, php_swoole_thread_barrier_create_object, php_swoole_thread_barrier_free_object, BarrierObject, std);
109+
}
110+
111+
static PHP_METHOD(swoole_thread_barrier, __construct) {
112+
auto bo = php_swoole_thread_barrier_fetch_object(Z_OBJ_P(ZEND_THIS));
113+
if (bo->barrier != nullptr) {
114+
zend_throw_error(NULL, "Constructor of %s can only be called once", SW_Z_OBJCE_NAME_VAL_P(ZEND_THIS));
115+
RETURN_FALSE;
116+
}
117+
118+
zend_long count;
119+
ZEND_PARSE_PARAMETERS_START(1, 1)
120+
Z_PARAM_LONG(count)
121+
ZEND_PARSE_PARAMETERS_END();
122+
123+
bo->barrier = new BarrierResource(count);
124+
auto resource_id = php_swoole_thread_resource_insert(bo->barrier);
125+
zend_update_property_long(swoole_thread_barrier_ce, SW_Z8_OBJ_P(ZEND_THIS), ZEND_STRL("id"), resource_id);
126+
RETURN_TRUE;
127+
}
128+
129+
static PHP_METHOD(swoole_thread_barrier, wait) {
130+
BarrierResource *barrier = php_swoole_thread_barrier_get_and_check_ptr(ZEND_THIS);
131+
if (barrier) {
132+
barrier->wait();
133+
}
134+
}
135+
136+
static PHP_METHOD(swoole_thread_barrier, __wakeup) {
137+
auto bo = php_swoole_thread_barrier_fetch_object(Z_OBJ_P(ZEND_THIS));
138+
zend_long resource_id = zend::object_get_long(ZEND_THIS, ZEND_STRL("id"));
139+
bo->barrier = static_cast<BarrierResource *>(php_swoole_thread_resource_fetch(resource_id));
140+
if (!bo->barrier) {
141+
zend_throw_exception(swoole_exception_ce, EMSG_NO_RESOURCE, ECODE_NO_RESOURCE);
142+
return;
143+
}
144+
}
145+
#endif

ext-src/swoole_thread_lock.cc

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,6 @@ using swoole::RWLock;
3737
static zend_class_entry *swoole_thread_lock_ce;
3838
static zend_object_handlers swoole_thread_lock_handlers;
3939

40-
#ifdef SW_THREAD
4140
struct LockResource : public ThreadResource {
4241
Lock *lock_;
4342
LockResource(int type) : ThreadResource() {
@@ -62,7 +61,6 @@ struct LockResource : public ThreadResource {
6261
delete lock_;
6362
}
6463
};
65-
#endif
6664

6765
struct LockObject {
6866
LockResource *lock;
@@ -113,9 +111,7 @@ static PHP_METHOD(swoole_thread_lock, lock_read);
113111
static PHP_METHOD(swoole_thread_lock, trylock_read);
114112
static PHP_METHOD(swoole_thread_lock, unlock);
115113
static PHP_METHOD(swoole_thread_lock, destroy);
116-
#ifdef SW_THREAD
117114
static PHP_METHOD(swoole_thread_lock, __wakeup);
118-
#endif
119115
SW_EXTERN_C_END
120116

121117
// clang-format off

include/swoole_lock.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -106,7 +106,7 @@ class SpinLock : public Lock {
106106
};
107107
#endif
108108

109-
#if defined(HAVE_PTHREAD_BARRIER) && !(defined(__FreeBSD__) || defined(__OpenBSD__) || defined(__NetBSD__))
109+
#if defined(HAVE_PTHREAD_BARRIER) && !(defined(__FreeBSD__) || defined(__OpenBSD__) || defined(__NetBSD__) || 1)
110110
#define SW_USE_PTHREAD_BARRIER
111111
#endif
112112

src/lock/barrier.cc

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,7 @@ void Barrier::wait() {
4242
#else
4343
sw_atomic_add_fetch(&barrier_, 1);
4444
SW_LOOP {
45-
if (*barrier_ == count_) {
45+
if (barrier_ == count_) {
4646
break;
4747
}
4848
usleep(BARRIER_USEC);

tests/swoole_thread/barrier.phpt

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
--TEST--
2+
swoole_thread: barrier
3+
--SKIPIF--
4+
<?php
5+
require __DIR__ . '/../include/skipif.inc';
6+
skip_if_nts();
7+
?>
8+
--FILE--
9+
<?php
10+
require __DIR__ . '/../include/bootstrap.php';
11+
12+
use Swoole\Thread;
13+
use Swoole\Thread\Barrier;
14+
15+
$tm = new \SwooleTest\ThreadManager();
16+
17+
$tm->parentFunc = function () {
18+
$barrier = new Barrier(2);
19+
$s = microtime(true);
20+
$thread = new Thread(__FILE__, $barrier);
21+
$barrier->wait();
22+
Assert::greaterThanEq(microtime(true) - $s, 0.2);
23+
echo "main thread\n";
24+
$thread->join();
25+
};
26+
27+
$tm->childFunc = function ($barrier) {
28+
echo "child thread\n";
29+
usleep(200_000);
30+
$barrier->wait();
31+
exit(0);
32+
};
33+
34+
$tm->run();
35+
?>
36+
--EXPECTF--
37+
child thread
38+
main thread

0 commit comments

Comments
 (0)