Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Refactor co lock #5646

Merged
merged 4 commits into from
Dec 30, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions ext-src/php_swoole.cc
Original file line number Diff line number Diff line change
Expand Up @@ -762,6 +762,7 @@ PHP_MINIT_FUNCTION(swoole) {
php_swoole_coroutine_minit(module_number);
php_swoole_coroutine_system_minit(module_number);
php_swoole_coroutine_scheduler_minit(module_number);
php_swoole_coroutine_lock_minit(module_number);
php_swoole_channel_coro_minit(module_number);
php_swoole_runtime_minit(module_number);
// client
Expand Down
1 change: 1 addition & 0 deletions ext-src/php_swoole_private.h
Original file line number Diff line number Diff line change
Expand Up @@ -267,6 +267,7 @@ void php_swoole_timer_minit(int module_number);
void php_swoole_coroutine_minit(int module_number);
void php_swoole_coroutine_system_minit(int module_number);
void php_swoole_coroutine_scheduler_minit(int module_number);
void php_swoole_coroutine_lock_minit(int module_number);
void php_swoole_channel_coro_minit(int module_number);
void php_swoole_runtime_minit(int module_number);
// client
Expand Down
10 changes: 10 additions & 0 deletions ext-src/stubs/php_swoole_coroutine_lock.stub.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
<?php
namespace Swoole\Coroutine {
class Lock {
public function __construct(bool $shared = false) {}
public function __destruct() {}
public function lock(): bool {}
public function trylock(): bool {}
public function unlock(): bool {}
}
}
16 changes: 16 additions & 0 deletions ext-src/stubs/php_swoole_coroutine_lock_arginfo.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
/* This is a generated file, edit the .stub.php file instead.
* Stub hash: 4b242a9587c917aa331408d30218fee19c7d8105 */

ZEND_BEGIN_ARG_INFO_EX(arginfo_class_Swoole_Coroutine_Lock___construct, 0, 0, 0)
ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, shared, _IS_BOOL, 0, "false")
ZEND_END_ARG_INFO()

ZEND_BEGIN_ARG_INFO_EX(arginfo_class_Swoole_Coroutine_Lock___destruct, 0, 0, 0)
ZEND_END_ARG_INFO()

ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_class_Swoole_Coroutine_Lock_lock, 0, 0, _IS_BOOL, 0)
ZEND_END_ARG_INFO()

#define arginfo_class_Swoole_Coroutine_Lock_trylock arginfo_class_Swoole_Coroutine_Lock_lock

#define arginfo_class_Swoole_Coroutine_Lock_unlock arginfo_class_Swoole_Coroutine_Lock_lock
1 change: 0 additions & 1 deletion ext-src/stubs/php_swoole_lock.stub.php
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,5 @@ public function trylock(): bool {}
public function lock_read(): bool {}
public function trylock_read(): bool {}
public function unlock(): bool {}
public function destroy(): void {}
}
}
5 changes: 1 addition & 4 deletions ext-src/stubs/php_swoole_lock_arginfo.h
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/* This is a generated file, edit the .stub.php file instead.
* Stub hash: e81e08c6ba7d087c2a3e55dade7b2dd3c788ae3f */
* Stub hash: 078bbefb0c45cb686da54e4c700bad31710589ef */

ZEND_BEGIN_ARG_INFO_EX(arginfo_class_Swoole_Lock___construct, 0, 0, 0)
ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, type, IS_LONG, 0, "SWOOLE_MUTEX")
Expand All @@ -22,6 +22,3 @@ ZEND_END_ARG_INFO()
#define arginfo_class_Swoole_Lock_trylock_read arginfo_class_Swoole_Lock_lock

#define arginfo_class_Swoole_Lock_unlock arginfo_class_Swoole_Lock_lock

ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_class_Swoole_Lock_destroy, 0, 0, IS_VOID, 0)
ZEND_END_ARG_INFO()
147 changes: 147 additions & 0 deletions ext-src/swoole_coroutine_lock.cc
Original file line number Diff line number Diff line change
@@ -0,0 +1,147 @@
/*
+----------------------------------------------------------------------+
| Swoole |
+----------------------------------------------------------------------+
| This source file is subject to version 2.0 of the Apache 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.apache.org/licenses/LICENSE-2.0.html |
| If you did not receive a copy of the Apache2.0 license and are unable|
| to obtain it through the world-wide-web, please send a note to |
| [email protected] so we can mail you a copy immediately. |
+----------------------------------------------------------------------+
| Author: Tianfeng Han <[email protected]> |
+----------------------------------------------------------------------+
*/

#include "php_swoole_private.h"
#include "swoole_memory.h"
#include "swoole_lock.h"

BEGIN_EXTERN_C()
#include "stubs/php_swoole_coroutine_lock_arginfo.h"
END_EXTERN_C()

using swoole::CoroutineLock;

static zend_class_entry *swoole_coroutine_lock_ce;
static zend_object_handlers swoole_coroutine_lock_handlers;

struct CoLockObject {
CoroutineLock *lock;
bool shared;
zend_object std;
};

static sw_inline CoLockObject *co_lock_fetch_object(zend_object *obj) {
return (CoLockObject *) ((char *) obj - swoole_coroutine_lock_handlers.offset);
}

static CoroutineLock *co_lock_get_ptr(zval *zobject) {
return co_lock_fetch_object(Z_OBJ_P(zobject))->lock;
}

static CoroutineLock *co_lock_get_and_check_ptr(zval *zobject) {
CoroutineLock *lock = co_lock_get_ptr(zobject);
if (UNEXPECTED(!lock)) {
swoole_fatal_error(SW_ERROR_WRONG_OPERATION, "must call constructor first");
}
return lock;
}

void co_lock_set_ptr(zval *zobject, CoroutineLock *ptr) {
co_lock_fetch_object(Z_OBJ_P(zobject))->lock = ptr;
}

static void co_lock_free_object(zend_object *object) {
CoLockObject *o = co_lock_fetch_object(object);
if (o->lock && !o->shared) {
delete o->lock;
}
zend_object_std_dtor(object);
}

static zend_object *co_lock_create_object(zend_class_entry *ce) {
CoLockObject *lock = (CoLockObject *) zend_object_alloc(sizeof(CoLockObject), ce);
zend_object_std_init(&lock->std, ce);
object_properties_init(&lock->std, ce);
lock->std.handlers = &swoole_coroutine_lock_handlers;
return &lock->std;
}

SW_EXTERN_C_BEGIN
static PHP_METHOD(swoole_coroutine_lock, __construct);
static PHP_METHOD(swoole_coroutine_lock, __destruct);
static PHP_METHOD(swoole_coroutine_lock, lock);
static PHP_METHOD(swoole_coroutine_lock, trylock);
static PHP_METHOD(swoole_coroutine_lock, unlock);
SW_EXTERN_C_END

// clang-format off
static const zend_function_entry swoole_coroutine_lock_methods[] =
{
PHP_ME(swoole_coroutine_lock, __construct, arginfo_class_Swoole_Coroutine_Lock___construct, ZEND_ACC_PUBLIC)
PHP_ME(swoole_coroutine_lock, __destruct, arginfo_class_Swoole_Coroutine_Lock___destruct, ZEND_ACC_PUBLIC)
PHP_ME(swoole_coroutine_lock, lock, arginfo_class_Swoole_Coroutine_Lock_lock, ZEND_ACC_PUBLIC)
PHP_ME(swoole_coroutine_lock, trylock, arginfo_class_Swoole_Coroutine_Lock_trylock, ZEND_ACC_PUBLIC)
PHP_ME(swoole_coroutine_lock, unlock, arginfo_class_Swoole_Coroutine_Lock_unlock, ZEND_ACC_PUBLIC)
PHP_FE_END
};
// clang-format on

void php_swoole_coroutine_lock_minit(int module_number) {
SW_INIT_CLASS_ENTRY(swoole_coroutine_lock, "Swoole\\Coroutine\\Lock", nullptr, swoole_coroutine_lock_methods);
SW_SET_CLASS_NOT_SERIALIZABLE(swoole_coroutine_lock);
SW_SET_CLASS_CLONEABLE(swoole_coroutine_lock, sw_zend_class_clone_deny);
SW_SET_CLASS_UNSET_PROPERTY_HANDLER(swoole_coroutine_lock, sw_zend_class_unset_property_deny);
SW_SET_CLASS_CUSTOM_OBJECT(
swoole_coroutine_lock, co_lock_create_object, co_lock_free_object, CoLockObject, std);
zend_declare_property_long(swoole_coroutine_lock_ce, ZEND_STRL("errCode"), 0, ZEND_ACC_PUBLIC);
}

static PHP_METHOD(swoole_coroutine_lock, __construct) {
CoroutineLock *lock = co_lock_get_ptr(ZEND_THIS);
if (lock != nullptr) {
zend_throw_error(NULL, "Constructor of %s can only be called once", SW_Z_OBJCE_NAME_VAL_P(ZEND_THIS));
RETURN_FALSE;
}

zend_bool shared = false;

ZEND_PARSE_PARAMETERS_START(0, 1)
Z_PARAM_OPTIONAL
Z_PARAM_BOOL(shared)
ZEND_PARSE_PARAMETERS_END_EX(RETURN_FALSE);

lock = new CoroutineLock(shared);
co_lock_set_ptr(ZEND_THIS, lock);
RETURN_TRUE;
}

static PHP_METHOD(swoole_coroutine_lock, __destruct) {}

static PHP_METHOD(swoole_coroutine_lock, lock) {
CoroutineLock *lock = co_lock_get_and_check_ptr(ZEND_THIS);
SW_LOCK_CHECK_RETURN(lock->lock());
}

static PHP_METHOD(swoole_coroutine_lock, unlock) {
CoroutineLock *lock = co_lock_get_and_check_ptr(ZEND_THIS);
SW_LOCK_CHECK_RETURN(lock->unlock());
}

static PHP_METHOD(swoole_coroutine_lock, trylock) {
CoroutineLock *lock = co_lock_get_and_check_ptr(ZEND_THIS);
SW_LOCK_CHECK_RETURN(lock->trylock());
}

static PHP_METHOD(swoole_coroutine_lock, trylock_read) {
CoroutineLock *lock = co_lock_get_and_check_ptr(ZEND_THIS);
SW_LOCK_CHECK_RETURN(lock->trylock_rd());
}

static PHP_METHOD(swoole_coroutine_lock, lock_read) {
CoroutineLock *lock = co_lock_get_and_check_ptr(ZEND_THIS);
SW_LOCK_CHECK_RETURN(lock->lock_rd());
}

16 changes: 0 additions & 16 deletions ext-src/swoole_lock.cc
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,6 @@ using swoole::SpinLock;
#ifdef HAVE_RWLOCK
using swoole::RWLock;
#endif
using swoole::CoroutineLock;

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

static void php_swoole_lock_free_object(zend_object *object) {
LockObject *o = php_swoole_lock_fetch_object(object);
if (o->lock) {
delete o->lock;
}
zend_object_std_dtor(object);
}

Expand All @@ -85,7 +81,6 @@ static PHP_METHOD(swoole_lock, trylock);
static PHP_METHOD(swoole_lock, lock_read);
static PHP_METHOD(swoole_lock, trylock_read);
static PHP_METHOD(swoole_lock, unlock);
static PHP_METHOD(swoole_lock, destroy);
SW_EXTERN_C_END

// clang-format off
Expand All @@ -99,7 +94,6 @@ static const zend_function_entry swoole_lock_methods[] =
PHP_ME(swoole_lock, lock_read, arginfo_class_Swoole_Lock_lock_read, ZEND_ACC_PUBLIC)
PHP_ME(swoole_lock, trylock_read, arginfo_class_Swoole_Lock_trylock_read, ZEND_ACC_PUBLIC)
PHP_ME(swoole_lock, unlock, arginfo_class_Swoole_Lock_unlock, ZEND_ACC_PUBLIC)
PHP_ME(swoole_lock, destroy, arginfo_class_Swoole_Lock_destroy, ZEND_ACC_PUBLIC)
PHP_FE_END
};
// clang-format on
Expand Down Expand Up @@ -128,7 +122,6 @@ void php_swoole_lock_minit(int module_number) {
#ifdef HAVE_SPINLOCK
SW_REGISTER_LONG_CONSTANT("SWOOLE_SPINLOCK", Lock::SPIN_LOCK);
#endif
SW_REGISTER_LONG_CONSTANT("SWOOLE_COROLOCK", Lock::COROUTINE_LOCK);
}

static PHP_METHOD(swoole_lock, __construct) {
Expand Down Expand Up @@ -160,9 +153,6 @@ static PHP_METHOD(swoole_lock, __construct) {
case Lock::MUTEX:
lock = new Mutex(Mutex::PROCESS_SHARED);
break;
case Lock::COROUTINE_LOCK:
lock = new CoroutineLock();
break;
default:
zend_throw_exception(swoole_exception_ce, "lock type[%d] is not support", type);
RETURN_FALSE;
Expand Down Expand Up @@ -219,9 +209,3 @@ static PHP_METHOD(swoole_lock, lock_read) {
Lock *lock = php_swoole_lock_get_and_check_ptr(ZEND_THIS);
SW_LOCK_CHECK_RETURN(lock->lock_rd());
}

static PHP_METHOD(swoole_lock, destroy) {
Lock *lock = php_swoole_lock_get_and_check_ptr(ZEND_THIS);
delete lock;
php_swoole_lock_set_ptr(ZEND_THIS, nullptr);
}
5 changes: 0 additions & 5 deletions ext-src/swoole_thread_lock.cc
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,6 @@ using swoole::SpinLock;
#ifdef HAVE_RWLOCK
using swoole::RWLock;
#endif
using swoole::CoroutineLock;

zend_class_entry *swoole_thread_lock_ce;
static zend_object_handlers swoole_thread_lock_handlers;
Expand All @@ -52,9 +51,6 @@ struct LockResource : public ThreadResource {
lock_ = new RWLock(0);
break;
#endif
case Lock::COROUTINE_LOCK:
lock_ = new CoroutineLock();
break;
case Lock::MUTEX:
default:
lock_ = new Mutex(0);
Expand Down Expand Up @@ -124,7 +120,6 @@ static PHP_METHOD(swoole_thread_lock, trylock);
static PHP_METHOD(swoole_thread_lock, lock_read);
static PHP_METHOD(swoole_thread_lock, trylock_read);
static PHP_METHOD(swoole_thread_lock, unlock);
static PHP_METHOD(swoole_thread_lock, destroy);
SW_EXTERN_C_END

// clang-format off
Expand Down
2 changes: 1 addition & 1 deletion include/swoole_lock.h
Original file line number Diff line number Diff line change
Expand Up @@ -115,7 +115,7 @@ class CoroutineLock : public Lock {
int lock_impl(bool blocking = true);

public:
CoroutineLock();
CoroutineLock(bool shared);
~CoroutineLock();
int lock_rd() override;
int lock() override;
Expand Down
15 changes: 12 additions & 3 deletions src/lock/coroutine_lock.cc
Original file line number Diff line number Diff line change
Expand Up @@ -26,14 +26,23 @@ using swoole::coroutine::System;
#include "swoole_lock.h"

namespace swoole {
CoroutineLock::CoroutineLock() : Lock() {
CoroutineLock::CoroutineLock(bool shared) : Lock() {
type_ = COROUTINE_LOCK;
value = (sw_atomic_t *) sw_mem_pool()->alloc(sizeof(sw_atomic_t));
shared_ = shared;
if (shared) {
value = (sw_atomic_t *) sw_mem_pool()->alloc(sizeof(sw_atomic_t));
} else {
value = new sw_atomic_t;
}
*value = 0;
}

CoroutineLock::~CoroutineLock() {
sw_mem_pool()->free((void *) value);
if (shared_) {
sw_mem_pool()->free((void *) value);
} else {
delete value;
}
value = nullptr;
}

Expand Down
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
--TEST--
swoole_lock: coroutine lock
swoole_coroutine_lock: lock
--FILE--
<?php
require __DIR__ . '/../include/bootstrap.php';

use Swoole\Lock;
use Swoole\Coroutine\Lock;
use Swoole\Runtime;
use Swoole\Http\Server;
use function Swoole\Coroutine\run;
Expand Down Expand Up @@ -53,9 +53,13 @@ $pm->parentFunc = function ($pid) use ($pm) {
};

$pm->childFunc = function () use ($pm) {
$lock = new Lock(SWOOLE_COROLOCK);
var_dump($lock->lock());
var_dump($lock->unlock());
swoole_async_set([
'log_file' => '/dev/null',
]);
$lock = new Lock(true);
Assert::false($lock->lock());
Assert::false($lock->unlock());
Assert::eq($lock->errCode, SWOOLE_ERROR_CO_OUT_OF_COROUTINE);
$serv = new Server('127.0.0.1', $pm->getFreePort());
$serv->set([
'log_file' => '/dev/null',
Expand Down Expand Up @@ -87,10 +91,6 @@ $pm->childFirst();
$pm->run();
?>
--EXPECTF--
%s
bool(false)
%s
bool(false)
array(1) {
["result"]=>
string(7) "value 3"
Expand Down
Loading
Loading