Skip to content

Commit d575b28

Browse files
authored
Refactor co lock (#5646)
* refactor co lock * fix * fix 2, --filter=[unit] * fix 3, --filter=[unit]
1 parent 25837a8 commit d575b28

14 files changed

+255
-53
lines changed

ext-src/php_swoole.cc

+1
Original file line numberDiff line numberDiff line change
@@ -762,6 +762,7 @@ PHP_MINIT_FUNCTION(swoole) {
762762
php_swoole_coroutine_minit(module_number);
763763
php_swoole_coroutine_system_minit(module_number);
764764
php_swoole_coroutine_scheduler_minit(module_number);
765+
php_swoole_coroutine_lock_minit(module_number);
765766
php_swoole_channel_coro_minit(module_number);
766767
php_swoole_runtime_minit(module_number);
767768
// client

ext-src/php_swoole_private.h

+1
Original file line numberDiff line numberDiff line change
@@ -267,6 +267,7 @@ void php_swoole_timer_minit(int module_number);
267267
void php_swoole_coroutine_minit(int module_number);
268268
void php_swoole_coroutine_system_minit(int module_number);
269269
void php_swoole_coroutine_scheduler_minit(int module_number);
270+
void php_swoole_coroutine_lock_minit(int module_number);
270271
void php_swoole_channel_coro_minit(int module_number);
271272
void php_swoole_runtime_minit(int module_number);
272273
// client
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
<?php
2+
namespace Swoole\Coroutine {
3+
class Lock {
4+
public function __construct(bool $shared = false) {}
5+
public function __destruct() {}
6+
public function lock(): bool {}
7+
public function trylock(): bool {}
8+
public function unlock(): bool {}
9+
}
10+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
/* This is a generated file, edit the .stub.php file instead.
2+
* Stub hash: 4b242a9587c917aa331408d30218fee19c7d8105 */
3+
4+
ZEND_BEGIN_ARG_INFO_EX(arginfo_class_Swoole_Coroutine_Lock___construct, 0, 0, 0)
5+
ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, shared, _IS_BOOL, 0, "false")
6+
ZEND_END_ARG_INFO()
7+
8+
ZEND_BEGIN_ARG_INFO_EX(arginfo_class_Swoole_Coroutine_Lock___destruct, 0, 0, 0)
9+
ZEND_END_ARG_INFO()
10+
11+
ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_class_Swoole_Coroutine_Lock_lock, 0, 0, _IS_BOOL, 0)
12+
ZEND_END_ARG_INFO()
13+
14+
#define arginfo_class_Swoole_Coroutine_Lock_trylock arginfo_class_Swoole_Coroutine_Lock_lock
15+
16+
#define arginfo_class_Swoole_Coroutine_Lock_unlock arginfo_class_Swoole_Coroutine_Lock_lock

ext-src/stubs/php_swoole_lock.stub.php

-1
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,5 @@ public function trylock(): bool {}
99
public function lock_read(): bool {}
1010
public function trylock_read(): bool {}
1111
public function unlock(): bool {}
12-
public function destroy(): void {}
1312
}
1413
}

ext-src/stubs/php_swoole_lock_arginfo.h

+1-4
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/* This is a generated file, edit the .stub.php file instead.
2-
* Stub hash: e81e08c6ba7d087c2a3e55dade7b2dd3c788ae3f */
2+
* Stub hash: 078bbefb0c45cb686da54e4c700bad31710589ef */
33

44
ZEND_BEGIN_ARG_INFO_EX(arginfo_class_Swoole_Lock___construct, 0, 0, 0)
55
ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, type, IS_LONG, 0, "SWOOLE_MUTEX")
@@ -22,6 +22,3 @@ ZEND_END_ARG_INFO()
2222
#define arginfo_class_Swoole_Lock_trylock_read arginfo_class_Swoole_Lock_lock
2323

2424
#define arginfo_class_Swoole_Lock_unlock arginfo_class_Swoole_Lock_lock
25-
26-
ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_class_Swoole_Lock_destroy, 0, 0, IS_VOID, 0)
27-
ZEND_END_ARG_INFO()

ext-src/swoole_coroutine_lock.cc

+147
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,147 @@
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 "swoole_memory.h"
19+
#include "swoole_lock.h"
20+
21+
BEGIN_EXTERN_C()
22+
#include "stubs/php_swoole_coroutine_lock_arginfo.h"
23+
END_EXTERN_C()
24+
25+
using swoole::CoroutineLock;
26+
27+
static zend_class_entry *swoole_coroutine_lock_ce;
28+
static zend_object_handlers swoole_coroutine_lock_handlers;
29+
30+
struct CoLockObject {
31+
CoroutineLock *lock;
32+
bool shared;
33+
zend_object std;
34+
};
35+
36+
static sw_inline CoLockObject *co_lock_fetch_object(zend_object *obj) {
37+
return (CoLockObject *) ((char *) obj - swoole_coroutine_lock_handlers.offset);
38+
}
39+
40+
static CoroutineLock *co_lock_get_ptr(zval *zobject) {
41+
return co_lock_fetch_object(Z_OBJ_P(zobject))->lock;
42+
}
43+
44+
static CoroutineLock *co_lock_get_and_check_ptr(zval *zobject) {
45+
CoroutineLock *lock = co_lock_get_ptr(zobject);
46+
if (UNEXPECTED(!lock)) {
47+
swoole_fatal_error(SW_ERROR_WRONG_OPERATION, "must call constructor first");
48+
}
49+
return lock;
50+
}
51+
52+
void co_lock_set_ptr(zval *zobject, CoroutineLock *ptr) {
53+
co_lock_fetch_object(Z_OBJ_P(zobject))->lock = ptr;
54+
}
55+
56+
static void co_lock_free_object(zend_object *object) {
57+
CoLockObject *o = co_lock_fetch_object(object);
58+
if (o->lock && !o->shared) {
59+
delete o->lock;
60+
}
61+
zend_object_std_dtor(object);
62+
}
63+
64+
static zend_object *co_lock_create_object(zend_class_entry *ce) {
65+
CoLockObject *lock = (CoLockObject *) zend_object_alloc(sizeof(CoLockObject), ce);
66+
zend_object_std_init(&lock->std, ce);
67+
object_properties_init(&lock->std, ce);
68+
lock->std.handlers = &swoole_coroutine_lock_handlers;
69+
return &lock->std;
70+
}
71+
72+
SW_EXTERN_C_BEGIN
73+
static PHP_METHOD(swoole_coroutine_lock, __construct);
74+
static PHP_METHOD(swoole_coroutine_lock, __destruct);
75+
static PHP_METHOD(swoole_coroutine_lock, lock);
76+
static PHP_METHOD(swoole_coroutine_lock, trylock);
77+
static PHP_METHOD(swoole_coroutine_lock, unlock);
78+
SW_EXTERN_C_END
79+
80+
// clang-format off
81+
static const zend_function_entry swoole_coroutine_lock_methods[] =
82+
{
83+
PHP_ME(swoole_coroutine_lock, __construct, arginfo_class_Swoole_Coroutine_Lock___construct, ZEND_ACC_PUBLIC)
84+
PHP_ME(swoole_coroutine_lock, __destruct, arginfo_class_Swoole_Coroutine_Lock___destruct, ZEND_ACC_PUBLIC)
85+
PHP_ME(swoole_coroutine_lock, lock, arginfo_class_Swoole_Coroutine_Lock_lock, ZEND_ACC_PUBLIC)
86+
PHP_ME(swoole_coroutine_lock, trylock, arginfo_class_Swoole_Coroutine_Lock_trylock, ZEND_ACC_PUBLIC)
87+
PHP_ME(swoole_coroutine_lock, unlock, arginfo_class_Swoole_Coroutine_Lock_unlock, ZEND_ACC_PUBLIC)
88+
PHP_FE_END
89+
};
90+
// clang-format on
91+
92+
void php_swoole_coroutine_lock_minit(int module_number) {
93+
SW_INIT_CLASS_ENTRY(swoole_coroutine_lock, "Swoole\\Coroutine\\Lock", nullptr, swoole_coroutine_lock_methods);
94+
SW_SET_CLASS_NOT_SERIALIZABLE(swoole_coroutine_lock);
95+
SW_SET_CLASS_CLONEABLE(swoole_coroutine_lock, sw_zend_class_clone_deny);
96+
SW_SET_CLASS_UNSET_PROPERTY_HANDLER(swoole_coroutine_lock, sw_zend_class_unset_property_deny);
97+
SW_SET_CLASS_CUSTOM_OBJECT(
98+
swoole_coroutine_lock, co_lock_create_object, co_lock_free_object, CoLockObject, std);
99+
zend_declare_property_long(swoole_coroutine_lock_ce, ZEND_STRL("errCode"), 0, ZEND_ACC_PUBLIC);
100+
}
101+
102+
static PHP_METHOD(swoole_coroutine_lock, __construct) {
103+
CoroutineLock *lock = co_lock_get_ptr(ZEND_THIS);
104+
if (lock != nullptr) {
105+
zend_throw_error(NULL, "Constructor of %s can only be called once", SW_Z_OBJCE_NAME_VAL_P(ZEND_THIS));
106+
RETURN_FALSE;
107+
}
108+
109+
zend_bool shared = false;
110+
111+
ZEND_PARSE_PARAMETERS_START(0, 1)
112+
Z_PARAM_OPTIONAL
113+
Z_PARAM_BOOL(shared)
114+
ZEND_PARSE_PARAMETERS_END_EX(RETURN_FALSE);
115+
116+
lock = new CoroutineLock(shared);
117+
co_lock_set_ptr(ZEND_THIS, lock);
118+
RETURN_TRUE;
119+
}
120+
121+
static PHP_METHOD(swoole_coroutine_lock, __destruct) {}
122+
123+
static PHP_METHOD(swoole_coroutine_lock, lock) {
124+
CoroutineLock *lock = co_lock_get_and_check_ptr(ZEND_THIS);
125+
SW_LOCK_CHECK_RETURN(lock->lock());
126+
}
127+
128+
static PHP_METHOD(swoole_coroutine_lock, unlock) {
129+
CoroutineLock *lock = co_lock_get_and_check_ptr(ZEND_THIS);
130+
SW_LOCK_CHECK_RETURN(lock->unlock());
131+
}
132+
133+
static PHP_METHOD(swoole_coroutine_lock, trylock) {
134+
CoroutineLock *lock = co_lock_get_and_check_ptr(ZEND_THIS);
135+
SW_LOCK_CHECK_RETURN(lock->trylock());
136+
}
137+
138+
static PHP_METHOD(swoole_coroutine_lock, trylock_read) {
139+
CoroutineLock *lock = co_lock_get_and_check_ptr(ZEND_THIS);
140+
SW_LOCK_CHECK_RETURN(lock->trylock_rd());
141+
}
142+
143+
static PHP_METHOD(swoole_coroutine_lock, lock_read) {
144+
CoroutineLock *lock = co_lock_get_and_check_ptr(ZEND_THIS);
145+
SW_LOCK_CHECK_RETURN(lock->lock_rd());
146+
}
147+

ext-src/swoole_lock.cc

-16
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,6 @@ using swoole::SpinLock;
3030
#ifdef HAVE_RWLOCK
3131
using swoole::RWLock;
3232
#endif
33-
using swoole::CoroutineLock;
3433

3534
static zend_class_entry *swoole_lock_ce;
3635
static zend_object_handlers swoole_lock_handlers;
@@ -62,9 +61,6 @@ void php_swoole_lock_set_ptr(zval *zobject, Lock *ptr) {
6261

6362
static void php_swoole_lock_free_object(zend_object *object) {
6463
LockObject *o = php_swoole_lock_fetch_object(object);
65-
if (o->lock) {
66-
delete o->lock;
67-
}
6864
zend_object_std_dtor(object);
6965
}
7066

@@ -85,7 +81,6 @@ static PHP_METHOD(swoole_lock, trylock);
8581
static PHP_METHOD(swoole_lock, lock_read);
8682
static PHP_METHOD(swoole_lock, trylock_read);
8783
static PHP_METHOD(swoole_lock, unlock);
88-
static PHP_METHOD(swoole_lock, destroy);
8984
SW_EXTERN_C_END
9085

9186
// clang-format off
@@ -99,7 +94,6 @@ static const zend_function_entry swoole_lock_methods[] =
9994
PHP_ME(swoole_lock, lock_read, arginfo_class_Swoole_Lock_lock_read, ZEND_ACC_PUBLIC)
10095
PHP_ME(swoole_lock, trylock_read, arginfo_class_Swoole_Lock_trylock_read, ZEND_ACC_PUBLIC)
10196
PHP_ME(swoole_lock, unlock, arginfo_class_Swoole_Lock_unlock, ZEND_ACC_PUBLIC)
102-
PHP_ME(swoole_lock, destroy, arginfo_class_Swoole_Lock_destroy, ZEND_ACC_PUBLIC)
10397
PHP_FE_END
10498
};
10599
// clang-format on
@@ -128,7 +122,6 @@ void php_swoole_lock_minit(int module_number) {
128122
#ifdef HAVE_SPINLOCK
129123
SW_REGISTER_LONG_CONSTANT("SWOOLE_SPINLOCK", Lock::SPIN_LOCK);
130124
#endif
131-
SW_REGISTER_LONG_CONSTANT("SWOOLE_COROLOCK", Lock::COROUTINE_LOCK);
132125
}
133126

134127
static PHP_METHOD(swoole_lock, __construct) {
@@ -160,9 +153,6 @@ static PHP_METHOD(swoole_lock, __construct) {
160153
case Lock::MUTEX:
161154
lock = new Mutex(Mutex::PROCESS_SHARED);
162155
break;
163-
case Lock::COROUTINE_LOCK:
164-
lock = new CoroutineLock();
165-
break;
166156
default:
167157
zend_throw_exception(swoole_exception_ce, "lock type[%d] is not support", type);
168158
RETURN_FALSE;
@@ -219,9 +209,3 @@ static PHP_METHOD(swoole_lock, lock_read) {
219209
Lock *lock = php_swoole_lock_get_and_check_ptr(ZEND_THIS);
220210
SW_LOCK_CHECK_RETURN(lock->lock_rd());
221211
}
222-
223-
static PHP_METHOD(swoole_lock, destroy) {
224-
Lock *lock = php_swoole_lock_get_and_check_ptr(ZEND_THIS);
225-
delete lock;
226-
php_swoole_lock_set_ptr(ZEND_THIS, nullptr);
227-
}

ext-src/swoole_thread_lock.cc

-5
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,6 @@ using swoole::SpinLock;
3333
#ifdef HAVE_RWLOCK
3434
using swoole::RWLock;
3535
#endif
36-
using swoole::CoroutineLock;
3736

3837
zend_class_entry *swoole_thread_lock_ce;
3938
static zend_object_handlers swoole_thread_lock_handlers;
@@ -52,9 +51,6 @@ struct LockResource : public ThreadResource {
5251
lock_ = new RWLock(0);
5352
break;
5453
#endif
55-
case Lock::COROUTINE_LOCK:
56-
lock_ = new CoroutineLock();
57-
break;
5854
case Lock::MUTEX:
5955
default:
6056
lock_ = new Mutex(0);
@@ -124,7 +120,6 @@ static PHP_METHOD(swoole_thread_lock, trylock);
124120
static PHP_METHOD(swoole_thread_lock, lock_read);
125121
static PHP_METHOD(swoole_thread_lock, trylock_read);
126122
static PHP_METHOD(swoole_thread_lock, unlock);
127-
static PHP_METHOD(swoole_thread_lock, destroy);
128123
SW_EXTERN_C_END
129124

130125
// clang-format off

include/swoole_lock.h

+1-1
Original file line numberDiff line numberDiff line change
@@ -115,7 +115,7 @@ class CoroutineLock : public Lock {
115115
int lock_impl(bool blocking = true);
116116

117117
public:
118-
CoroutineLock();
118+
CoroutineLock(bool shared);
119119
~CoroutineLock();
120120
int lock_rd() override;
121121
int lock() override;

src/lock/coroutine_lock.cc

+12-3
Original file line numberDiff line numberDiff line change
@@ -26,14 +26,23 @@ using swoole::coroutine::System;
2626
#include "swoole_lock.h"
2727

2828
namespace swoole {
29-
CoroutineLock::CoroutineLock() : Lock() {
29+
CoroutineLock::CoroutineLock(bool shared) : Lock() {
3030
type_ = COROUTINE_LOCK;
31-
value = (sw_atomic_t *) sw_mem_pool()->alloc(sizeof(sw_atomic_t));
31+
shared_ = shared;
32+
if (shared) {
33+
value = (sw_atomic_t *) sw_mem_pool()->alloc(sizeof(sw_atomic_t));
34+
} else {
35+
value = new sw_atomic_t;
36+
}
3237
*value = 0;
3338
}
3439

3540
CoroutineLock::~CoroutineLock() {
36-
sw_mem_pool()->free((void *) value);
41+
if (shared_) {
42+
sw_mem_pool()->free((void *) value);
43+
} else {
44+
delete value;
45+
}
3746
value = nullptr;
3847
}
3948

tests/swoole_lock/coroutine_lock.phpt tests/swoole_coroutine_lock/lock.phpt

+9-9
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,10 @@
11
--TEST--
2-
swoole_lock: coroutine lock
2+
swoole_coroutine_lock: lock
33
--FILE--
44
<?php
55
require __DIR__ . '/../include/bootstrap.php';
66

7-
use Swoole\Lock;
7+
use Swoole\Coroutine\Lock;
88
use Swoole\Runtime;
99
use Swoole\Http\Server;
1010
use function Swoole\Coroutine\run;
@@ -53,9 +53,13 @@ $pm->parentFunc = function ($pid) use ($pm) {
5353
};
5454

5555
$pm->childFunc = function () use ($pm) {
56-
$lock = new Lock(SWOOLE_COROLOCK);
57-
var_dump($lock->lock());
58-
var_dump($lock->unlock());
56+
swoole_async_set([
57+
'log_file' => '/dev/null',
58+
]);
59+
$lock = new Lock(true);
60+
Assert::false($lock->lock());
61+
Assert::false($lock->unlock());
62+
Assert::eq($lock->errCode, SWOOLE_ERROR_CO_OUT_OF_COROUTINE);
5963
$serv = new Server('127.0.0.1', $pm->getFreePort());
6064
$serv->set([
6165
'log_file' => '/dev/null',
@@ -87,10 +91,6 @@ $pm->childFirst();
8791
$pm->run();
8892
?>
8993
--EXPECTF--
90-
%s
91-
bool(false)
92-
%s
93-
bool(false)
9494
array(1) {
9595
["result"]=>
9696
string(7) "value 3"

0 commit comments

Comments
 (0)