Skip to content

Commit

Permalink
refactor co lock
Browse files Browse the repository at this point in the history
  • Loading branch information
matyhtf committed Dec 27, 2024
1 parent 25837a8 commit e825bfd
Show file tree
Hide file tree
Showing 13 changed files with 238 additions and 38 deletions.
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()
146 changes: 146 additions & 0 deletions ext-src/swoole_coroutine_lock.cc
Original file line number Diff line number Diff line change
@@ -0,0 +1,146 @@
/*
+----------------------------------------------------------------------+
| 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);
}

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
Expand Up @@ -4,7 +4,7 @@ swoole_lock: coroutine lock
<?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(swoole_last_error(), SWOOLE_ERROR_OPERATION_NOT_SUPPORT);
$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

0 comments on commit e825bfd

Please sign in to comment.