From f3a3d9b0e47bf84538195e8137b967d71feaa4ee Mon Sep 17 00:00:00 2001 From: hantianfeng Date: Mon, 1 Jul 2024 16:52:49 +0800 Subject: [PATCH 01/11] Refactor thread resource --- examples/thread/nested_map.php | 21 ++ ext-src/php_swoole_thread.h | 89 ++++- .../php_swoole_thread_arraylist.stub.php | 2 +- .../php_swoole_thread_arraylist_arginfo.h | 5 +- .../stubs/php_swoole_thread_atomic.stub.php | 2 - .../stubs/php_swoole_thread_atomic_arginfo.h | 7 +- .../stubs/php_swoole_thread_barrier.stub.php | 1 - .../stubs/php_swoole_thread_barrier_arginfo.h | 4 +- ext-src/stubs/php_swoole_thread_lock.stub.php | 1 - .../stubs/php_swoole_thread_lock_arginfo.h | 5 +- ext-src/stubs/php_swoole_thread_map.stub.php | 2 +- ext-src/stubs/php_swoole_thread_map_arginfo.h | 4 +- .../stubs/php_swoole_thread_queue.stub.php | 1 - .../stubs/php_swoole_thread_queue_arginfo.h | 4 +- ext-src/swoole_channel_coro.cc | 2 +- ext-src/swoole_http_client_coro.cc | 2 +- ext-src/swoole_lock.cc | 4 +- ext-src/swoole_name_resolver.cc | 4 +- ext-src/swoole_process.cc | 4 +- ext-src/swoole_process_pool.cc | 4 +- ext-src/swoole_server.cc | 18 +- ext-src/swoole_socket_coro.cc | 2 +- ext-src/swoole_table.cc | 4 +- ext-src/swoole_thread.cc | 330 ++++++++---------- ext-src/swoole_thread_arraylist.cc | 80 ++--- ext-src/swoole_thread_atomic.cc | 159 +++++---- ext-src/swoole_thread_barrier.cc | 68 ++-- ext-src/swoole_thread_lock.cc | 72 ++-- ext-src/swoole_thread_map.cc | 89 +++-- ext-src/swoole_thread_queue.cc | 70 ++-- 30 files changed, 524 insertions(+), 536 deletions(-) create mode 100644 examples/thread/nested_map.php diff --git a/examples/thread/nested_map.php b/examples/thread/nested_map.php new file mode 100644 index 00000000000..daa0af5f9c2 --- /dev/null +++ b/examples/thread/nested_map.php @@ -0,0 +1,21 @@ + uniqid(), + 'b' => random_int(1000, 9999), +]; + +var_dump($map['map1']['key1']); +var_dump($map['list1'][0]); + +var_dump($map['list1']->toArray()); + +var_dump($map['map2']); diff --git a/ext-src/php_swoole_thread.h b/ext-src/php_swoole_thread.h index 3a568a4f275..1becd93ffc4 100644 --- a/ext-src/php_swoole_thread.h +++ b/ext-src/php_swoole_thread.h @@ -25,44 +25,73 @@ typedef uint32_t ThreadResourceId; struct ThreadResource; - -ThreadResourceId php_swoole_thread_resource_insert(ThreadResource *res); -bool php_swoole_thread_resource_free(ThreadResourceId resource_id, ThreadResource *res); -ThreadResource *php_swoole_thread_resource_fetch(ThreadResourceId resource_id); - -void php_swoole_thread_start(zend_string *file, zend_string *argv); -zend_string *php_swoole_thread_argv_serialize(zval *zdata); -bool php_swoole_thread_argv_unserialize(zend_string *data, zval *zv); +struct ZendArray; + +extern zend_class_entry *swoole_thread_arraylist_ce; +extern zend_class_entry *swoole_thread_atomic_ce; +extern zend_class_entry *swoole_thread_atomic_long_ce; +extern zend_class_entry *swoole_thread_barrier_ce; +extern zend_class_entry *swoole_thread_lock_ce; +extern zend_class_entry *swoole_thread_map_ce; +extern zend_class_entry *swoole_thread_queue_ce; + +void php_swoole_thread_start(zend_string *file, ZendArray *argv); +ZendArray *php_swoole_thread_argv_create(zval *zdata); zend_string *php_swoole_serialize(zval *zdata); bool php_swoole_unserialize(zend_string *data, zval *zv); -void php_swoole_thread_argv_clean(zval *zdata); void php_swoole_thread_bailout(void); -zval *php_swoole_thread_get_arguments(); +ThreadResource *php_swoole_thread_arraylist_cast(zval *zobject); +ThreadResource *php_swoole_thread_map_cast(zval *zobject); +ThreadResource *php_swoole_thread_queue_cast(zval *zobject); +ThreadResource *php_swoole_thread_lock_cast(zval *zobject); +ThreadResource *php_swoole_thread_atomic_cast(zval *zobject); +ThreadResource *php_swoole_thread_atomic_long_cast(zval *zobject); +ThreadResource *php_swoole_thread_barrier_cast(zval *zobject); + +void php_swoole_thread_arraylist_create(zval *return_value, ThreadResource *resource); +void php_swoole_thread_map_create(zval *return_value, ThreadResource *resource); +void php_swoole_thread_queue_create(zval *return_value, ThreadResource *resource); +void php_swoole_thread_lock_create(zval *return_value, ThreadResource *resource); +void php_swoole_thread_atomic_create(zval *return_value, ThreadResource *resource); +void php_swoole_thread_atomic_long_create(zval *return_value, ThreadResource *resource); +void php_swoole_thread_barrier_create(zval *return_value, ThreadResource *resource); #define EMSG_NO_RESOURCE "resource not found" #define ECODE_NO_RESOURCE -2 enum { + IS_ARRAYLIST = 80, + IS_QUEUE = 81, + IS_LOCK = 82, + IS_MAP = 83, + IS_BARRIER = 84, + IS_ATOMIC = 85, + IS_ATOMIC_LONG = 86, IS_CO_SOCKET = 97, IS_STREAM_SOCKET = 98, IS_SERIALIZED_OBJECT = 99, }; -struct ThreadResource { - uint32_t ref_count; +class ThreadResource { + sw_atomic_t ref_count; + public: ThreadResource() { ref_count = 1; } - uint32_t add_ref() { - return ++ref_count; + void add_ref() { + sw_atomic_add_fetch(&ref_count, 1); } - uint32_t del_ref() { - return --ref_count; + void del_ref() { + if (sw_atomic_sub_fetch(&ref_count, 1) == 0) { + delete this; + } } + + virtual ~ThreadResource() {} }; struct ArrayItem { @@ -77,6 +106,7 @@ struct ArrayItem { swSocketType type; } socket; zend_string *serialized_object; + ThreadResource *resource; } value; ArrayItem(zval *zvalue) { @@ -88,6 +118,10 @@ struct ArrayItem { key = zend_string_init(_key.val(), _key.len(), 1); } + void setKey(zend_string *_key) { + key = zend_string_init(ZSTR_VAL(_key), ZSTR_LEN(_key), 1); + } + void store(zval *zvalue); void fetch(zval *return_value); void release(); @@ -115,7 +149,7 @@ struct ZendArray : ThreadResource { zend_hash_init(&ht, 0, NULL, item_dtor, 1); } - ~ZendArray() { + ~ZendArray() override { zend_hash_destroy(&ht); } @@ -125,6 +159,25 @@ struct ZendArray : ThreadResource { lock_.unlock(); } + void append(zval *zvalue); + + void add(zend_string *skey, zval *zvalue) { + auto item = new ArrayItem(zvalue); + item->setKey(skey); + zend_hash_add_ptr(&ht, item->key, item); + } + + void add(zend::String &skey, zval *zvalue) { + auto item = new ArrayItem(zvalue); + item->setKey(skey); + zend_hash_add_ptr(&ht, item->key, item); + } + + void add(zend_long index, zval *zvalue) { + auto item = new ArrayItem(zvalue); + zend_hash_index_add_ptr(&ht, index, item); + } + bool index_exists(zend_long index) { return index < (zend_long) zend_hash_num_elements(&ht); } @@ -189,6 +242,7 @@ struct ZendArray : ThreadResource { } void keys(zval *return_value); + void toArray(zval *return_value); void intkey_offsetGet(zend_long index, zval *return_value) { lock_.lock_rd(); @@ -251,6 +305,7 @@ struct ZendArray : ThreadResource { static void incr_update(ArrayItem *item, zval *zvalue, zval *return_value); static ArrayItem *incr_create(zval *zvalue, zval *return_value); + static ZendArray *from(zend_array *ht); }; #define INIT_ARRAY_INCR_PARAMS \ diff --git a/ext-src/stubs/php_swoole_thread_arraylist.stub.php b/ext-src/stubs/php_swoole_thread_arraylist.stub.php index 29f7f3375d2..10c2e443d5c 100644 --- a/ext-src/stubs/php_swoole_thread_arraylist.stub.php +++ b/ext-src/stubs/php_swoole_thread_arraylist.stub.php @@ -10,6 +10,6 @@ public function count(): int {} public function incr(mixed $key, mixed $value = 1): mixed {} public function decr(mixed $key, mixed $value = 1): mixed {} public function clean(): void {} - public function __wakeup(): void {} + public function toArray(): array {} } } diff --git a/ext-src/stubs/php_swoole_thread_arraylist_arginfo.h b/ext-src/stubs/php_swoole_thread_arraylist_arginfo.h index fcdfb0ba1a9..6e2729c87e6 100644 --- a/ext-src/stubs/php_swoole_thread_arraylist_arginfo.h +++ b/ext-src/stubs/php_swoole_thread_arraylist_arginfo.h @@ -1,5 +1,5 @@ /* This is a generated file, edit the .stub.php file instead. - * Stub hash: 366fd5114ee7fab588f8c004cd08f600918d3394 */ + * Stub hash: 180fa4468e220b852fabc5320f2a463a219f7aa3 */ ZEND_BEGIN_ARG_INFO_EX(arginfo_class_Swoole_Thread_ArrayList___construct, 0, 0, 0) ZEND_END_ARG_INFO() @@ -34,4 +34,5 @@ ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_class_Swoole_Thread_ArrayList_clean, 0, 0, IS_VOID, 0) ZEND_END_ARG_INFO() -#define arginfo_class_Swoole_Thread_ArrayList___wakeup arginfo_class_Swoole_Thread_ArrayList_clean +ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_class_Swoole_Thread_ArrayList_toArray, 0, 0, IS_ARRAY, 0) +ZEND_END_ARG_INFO() diff --git a/ext-src/stubs/php_swoole_thread_atomic.stub.php b/ext-src/stubs/php_swoole_thread_atomic.stub.php index b9237e1cdcd..a60ac153229 100644 --- a/ext-src/stubs/php_swoole_thread_atomic.stub.php +++ b/ext-src/stubs/php_swoole_thread_atomic.stub.php @@ -9,7 +9,6 @@ public function set(int $value): void {} public function cmpset(int $cmp_value, int $new_value): bool {} public function wait(float $timeout = 1.0): bool {} public function wakeup(int $count = 1): bool {} - public function __wakeup(): void {} } } @@ -21,6 +20,5 @@ public function sub(int $sub_value = 1): int {} public function get(): int {} public function set(int $value): void {} public function cmpset(int $cmp_value, int $new_value): bool {} - public function __wakeup(): void {} } } diff --git a/ext-src/stubs/php_swoole_thread_atomic_arginfo.h b/ext-src/stubs/php_swoole_thread_atomic_arginfo.h index b12585d1d77..4b957f7e9a2 100644 --- a/ext-src/stubs/php_swoole_thread_atomic_arginfo.h +++ b/ext-src/stubs/php_swoole_thread_atomic_arginfo.h @@ -1,5 +1,5 @@ /* This is a generated file, edit the .stub.php file instead. - * Stub hash: c27562c58b557e8e211bbf52859e4e9818c35f55 */ + * Stub hash: 4b6cbceb50641f6204da9caed8c514a526c57ee8 */ ZEND_BEGIN_ARG_INFO_EX(arginfo_class_Swoole_Thread_Atomic___construct, 0, 0, 0) ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, value, IS_LONG, 0, "0") @@ -33,9 +33,6 @@ ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_class_Swoole_Thread_Atomic_wakeu ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, count, IS_LONG, 0, "1") ZEND_END_ARG_INFO() -ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_class_Swoole_Thread_Atomic___wakeup, 0, 0, IS_VOID, 0) -ZEND_END_ARG_INFO() - #define arginfo_class_Swoole_Thread_Atomic_Long___construct arginfo_class_Swoole_Thread_Atomic___construct #define arginfo_class_Swoole_Thread_Atomic_Long_add arginfo_class_Swoole_Thread_Atomic_add @@ -47,5 +44,3 @@ ZEND_END_ARG_INFO() #define arginfo_class_Swoole_Thread_Atomic_Long_set arginfo_class_Swoole_Thread_Atomic_set #define arginfo_class_Swoole_Thread_Atomic_Long_cmpset arginfo_class_Swoole_Thread_Atomic_cmpset - -#define arginfo_class_Swoole_Thread_Atomic_Long___wakeup arginfo_class_Swoole_Thread_Atomic___wakeup diff --git a/ext-src/stubs/php_swoole_thread_barrier.stub.php b/ext-src/stubs/php_swoole_thread_barrier.stub.php index 29281c63c03..233dea1d245 100644 --- a/ext-src/stubs/php_swoole_thread_barrier.stub.php +++ b/ext-src/stubs/php_swoole_thread_barrier.stub.php @@ -3,6 +3,5 @@ class Barrier { public function __construct(int $count) {} public function wait(): void {} - public function __wakeup(): void {} } } diff --git a/ext-src/stubs/php_swoole_thread_barrier_arginfo.h b/ext-src/stubs/php_swoole_thread_barrier_arginfo.h index 800c32aa849..19ed1ef6b10 100644 --- a/ext-src/stubs/php_swoole_thread_barrier_arginfo.h +++ b/ext-src/stubs/php_swoole_thread_barrier_arginfo.h @@ -1,5 +1,5 @@ /* This is a generated file, edit the .stub.php file instead. - * Stub hash: eac62993bfb3fbd87587a8e6997c16bca7dc5dbc */ + * Stub hash: 1fe9f55b0b9487e9cd469dcd215acee893254a04 */ ZEND_BEGIN_ARG_INFO_EX(arginfo_class_Swoole_Thread_Barrier___construct, 0, 0, 1) ZEND_ARG_TYPE_INFO(0, count, IS_LONG, 0) @@ -7,5 +7,3 @@ ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_class_Swoole_Thread_Barrier_wait, 0, 0, IS_VOID, 0) ZEND_END_ARG_INFO() - -#define arginfo_class_Swoole_Thread_Barrier___wakeup arginfo_class_Swoole_Thread_Barrier_wait diff --git a/ext-src/stubs/php_swoole_thread_lock.stub.php b/ext-src/stubs/php_swoole_thread_lock.stub.php index 30956f9a241..6dc08551375 100644 --- a/ext-src/stubs/php_swoole_thread_lock.stub.php +++ b/ext-src/stubs/php_swoole_thread_lock.stub.php @@ -9,6 +9,5 @@ public function trylock(): bool {} public function lock_read(): bool {} public function trylock_read(): bool {} public function unlock(): bool {} - public function __wakeup(): void {} } } diff --git a/ext-src/stubs/php_swoole_thread_lock_arginfo.h b/ext-src/stubs/php_swoole_thread_lock_arginfo.h index f039e70896b..85003d75c24 100644 --- a/ext-src/stubs/php_swoole_thread_lock_arginfo.h +++ b/ext-src/stubs/php_swoole_thread_lock_arginfo.h @@ -1,5 +1,5 @@ /* This is a generated file, edit the .stub.php file instead. - * Stub hash: e8d4c9f0d13a62fd6a0d67838b26cb4451f89ee9 */ + * Stub hash: 3c5cd43d34f7669ed8144417b6b36dbc43fb4392 */ ZEND_BEGIN_ARG_INFO_EX(arginfo_class_Swoole_Thread_Lock___construct, 0, 0, 0) ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, type, IS_LONG, 0, "SWOOLE_MUTEX") @@ -22,6 +22,3 @@ ZEND_END_ARG_INFO() #define arginfo_class_Swoole_Thread_Lock_trylock_read arginfo_class_Swoole_Thread_Lock_lock #define arginfo_class_Swoole_Thread_Lock_unlock arginfo_class_Swoole_Thread_Lock_lock - -ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_class_Swoole_Thread_Lock___wakeup, 0, 0, IS_VOID, 0) -ZEND_END_ARG_INFO() diff --git a/ext-src/stubs/php_swoole_thread_map.stub.php b/ext-src/stubs/php_swoole_thread_map.stub.php index c23621a4d48..b21e4a47f6c 100644 --- a/ext-src/stubs/php_swoole_thread_map.stub.php +++ b/ext-src/stubs/php_swoole_thread_map.stub.php @@ -13,6 +13,6 @@ public function decr(mixed $key, mixed $value = 1): mixed {} public function add(mixed $key, mixed $value): bool {} public function update(mixed $key, mixed $value): bool {} public function clean(): void {} - public function __wakeup(): void {} + public function toArray(): array {} } } diff --git a/ext-src/stubs/php_swoole_thread_map_arginfo.h b/ext-src/stubs/php_swoole_thread_map_arginfo.h index dc604135e4c..640ade4a1d9 100644 --- a/ext-src/stubs/php_swoole_thread_map_arginfo.h +++ b/ext-src/stubs/php_swoole_thread_map_arginfo.h @@ -1,5 +1,5 @@ /* This is a generated file, edit the .stub.php file instead. - * Stub hash: 44e8467dc5e0e3cc91e46840d4a1ae686ee6c0a6 */ + * Stub hash: e85b15919120073579b1d561326eb1c3e446860a */ ZEND_BEGIN_ARG_INFO_EX(arginfo_class_Swoole_Thread_Map___construct, 0, 0, 0) ZEND_END_ARG_INFO() @@ -44,4 +44,4 @@ ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_class_Swoole_Thread_Map_clean, 0, 0, IS_VOID, 0) ZEND_END_ARG_INFO() -#define arginfo_class_Swoole_Thread_Map___wakeup arginfo_class_Swoole_Thread_Map_clean +#define arginfo_class_Swoole_Thread_Map_toArray arginfo_class_Swoole_Thread_Map_keys diff --git a/ext-src/stubs/php_swoole_thread_queue.stub.php b/ext-src/stubs/php_swoole_thread_queue.stub.php index 7f2ed338ccf..a07dc08857b 100644 --- a/ext-src/stubs/php_swoole_thread_queue.stub.php +++ b/ext-src/stubs/php_swoole_thread_queue.stub.php @@ -6,6 +6,5 @@ public function push(mixed $value, int $notify_which = 0): void {} public function pop(float $wait = 0): mixed {} public function count(): int {} public function clean(): void {} - public function __wakeup(): void {} } } diff --git a/ext-src/stubs/php_swoole_thread_queue_arginfo.h b/ext-src/stubs/php_swoole_thread_queue_arginfo.h index a143149f8d2..b1b4ef32c0e 100644 --- a/ext-src/stubs/php_swoole_thread_queue_arginfo.h +++ b/ext-src/stubs/php_swoole_thread_queue_arginfo.h @@ -1,5 +1,5 @@ /* This is a generated file, edit the .stub.php file instead. - * Stub hash: c256829982b2a90c610e22862b13f0af86eaee6f */ + * Stub hash: 96a3f2b7103f36b83a3494d8b2f708a07a332b86 */ ZEND_BEGIN_ARG_INFO_EX(arginfo_class_Swoole_Thread_Queue___construct, 0, 0, 0) ZEND_END_ARG_INFO() @@ -18,5 +18,3 @@ ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_class_Swoole_Thread_Queue_clean, 0, 0, IS_VOID, 0) ZEND_END_ARG_INFO() - -#define arginfo_class_Swoole_Thread_Queue___wakeup arginfo_class_Swoole_Thread_Queue_clean diff --git a/ext-src/swoole_channel_coro.cc b/ext-src/swoole_channel_coro.cc index ec20ae7b7c9..a265ce45acc 100644 --- a/ext-src/swoole_channel_coro.cc +++ b/ext-src/swoole_channel_coro.cc @@ -68,7 +68,7 @@ static sw_inline ChannelObject *php_swoole_channel_coro_fetch_object(zend_object static sw_inline Channel *php_swoole_get_channel(zval *zobject) { Channel *chan = php_swoole_channel_coro_fetch_object(Z_OBJ_P(zobject))->chan; if (UNEXPECTED(!chan)) { - php_swoole_fatal_error(E_ERROR, "you must call Channel constructor first"); + swoole_fatal_error(SW_ERROR_WRONG_OPERATION, "must call constructor first"); } return chan; } diff --git a/ext-src/swoole_http_client_coro.cc b/ext-src/swoole_http_client_coro.cc index 4746b332bf6..8ea9ee85959 100644 --- a/ext-src/swoole_http_client_coro.cc +++ b/ext-src/swoole_http_client_coro.cc @@ -1638,7 +1638,7 @@ static sw_inline HttpClientObject *http_client_coro_fetch_object(zend_object *ob static sw_inline Client *http_client_coro_get_client(zval *zobject) { Client *phc = http_client_coro_fetch_object(Z_OBJ_P(zobject))->client; if (UNEXPECTED(!phc)) { - php_swoole_fatal_error(E_ERROR, "you must call Http Client constructor first"); + swoole_fatal_error(SW_ERROR_WRONG_OPERATION, "must call constructor first"); } return phc; } diff --git a/ext-src/swoole_lock.cc b/ext-src/swoole_lock.cc index 902dcf79535..36dc18f5ade 100644 --- a/ext-src/swoole_lock.cc +++ b/ext-src/swoole_lock.cc @@ -49,8 +49,8 @@ static Lock *php_swoole_lock_get_ptr(zval *zobject) { static Lock *php_swoole_lock_get_and_check_ptr(zval *zobject) { Lock *lock = php_swoole_lock_get_ptr(zobject); - if (!lock) { - php_swoole_fatal_error(E_ERROR, "must call constructor first"); + if (UNEXPECTED(!lock)) { + swoole_fatal_error(SW_ERROR_WRONG_OPERATION, "must call constructor first"); } return lock; } diff --git a/ext-src/swoole_name_resolver.cc b/ext-src/swoole_name_resolver.cc index 2a9e1584e2f..8c3b61ec727 100644 --- a/ext-src/swoole_name_resolver.cc +++ b/ext-src/swoole_name_resolver.cc @@ -44,8 +44,8 @@ static zend_always_inline ContextObject *swoole_name_resolver_context_get_object static zend_always_inline ContextObject *swoole_name_resolver_context_get_object_safe(zend_object *object) { NameResolver::Context *name_resolver_context = swoole_name_resolver_context_get_handle(object); - if (!name_resolver_context) { - php_swoole_fatal_error(E_ERROR, "must call name_resolver_context constructor first"); + if (UNEXPECTED(!name_resolver_context)) { + swoole_fatal_error(SW_ERROR_WRONG_OPERATION, "must call constructor first"); } return swoole_name_resolver_context_get_object(object); } diff --git a/ext-src/swoole_process.cc b/ext-src/swoole_process.cc index 667ffcc1cf8..7bfac0af358 100644 --- a/ext-src/swoole_process.cc +++ b/ext-src/swoole_process.cc @@ -51,8 +51,8 @@ Worker *php_swoole_process_get_worker(zval *zobject) { Worker *php_swoole_process_get_and_check_worker(zval *zobject) { Worker *worker = php_swoole_process_get_worker(zobject); - if (!worker) { - php_swoole_fatal_error(E_ERROR, "must call constructor first"); + if (UNEXPECTED(!worker)) { + swoole_fatal_error(SW_ERROR_WRONG_OPERATION, "must call constructor first"); } return worker; } diff --git a/ext-src/swoole_process_pool.cc b/ext-src/swoole_process_pool.cc index f14004f8ff1..3a79859c534 100644 --- a/ext-src/swoole_process_pool.cc +++ b/ext-src/swoole_process_pool.cc @@ -58,8 +58,8 @@ static sw_inline ProcessPool *process_pool_get_pool(zval *zobject) { static sw_inline ProcessPool *process_pool_get_and_check_pool(zval *zobject) { ProcessPool *pool = process_pool_get_pool(zobject); - if (!pool) { - php_swoole_fatal_error(E_ERROR, "you must call Process\\Pool constructor first"); + if (UNEXPECTED(!pool)) { + swoole_fatal_error(SW_ERROR_WRONG_OPERATION, "must call constructor first"); } return pool; } diff --git a/ext-src/swoole_server.cc b/ext-src/swoole_server.cc index 2d90a08b2f1..5bd57244c73 100644 --- a/ext-src/swoole_server.cc +++ b/ext-src/swoole_server.cc @@ -2642,23 +2642,23 @@ static PHP_METHOD(swoole_server, start) { #ifdef SW_THREAD zend_string *bootstrap = nullptr; - zend_string *thread_argv_serialized = nullptr; - zval thread_argv = {}; + ZendArray *thread_argv = nullptr; if (serv->is_thread_mode()) { zval *_bootstrap = zend::object_get(ZEND_THIS, ZEND_STRL("bootstrap")); bootstrap = zend_string_dup(Z_STR_P(_bootstrap), 1); if (!ZVAL_IS_NULL(&server_object->init_arguments)) { - call_user_function(NULL, NULL, &server_object->init_arguments, &thread_argv, 0, NULL); - thread_argv_serialized = php_swoole_thread_argv_serialize(&thread_argv); + zval _thread_argv; + call_user_function(NULL, NULL, &server_object->init_arguments, &_thread_argv, 0, NULL); + thread_argv = php_swoole_thread_argv_create(&_thread_argv); + zval_ptr_dtor(&_thread_argv); } - serv->worker_thread_start = [bootstrap, thread_argv_serialized](const WorkerFn &fn) { + serv->worker_thread_start = [bootstrap, thread_argv](const WorkerFn &fn) { worker_thread_fn = fn; zend_string *bootstrap_copy = zend_string_dup(bootstrap, 1); - zend_string *argv_copy = thread_argv_serialized ? zend_string_dup(thread_argv_serialized, 1) : nullptr; - php_swoole_thread_start(bootstrap_copy, argv_copy); + php_swoole_thread_start(bootstrap_copy, thread_argv); }; } #endif @@ -2674,10 +2674,6 @@ static PHP_METHOD(swoole_server, start) { if (bootstrap) { zend_string_release(bootstrap); } - if (thread_argv_serialized) { - zend_string_release(thread_argv_serialized); - } - zval_ptr_dtor(&thread_argv); #endif RETURN_TRUE; diff --git a/ext-src/swoole_socket_coro.cc b/ext-src/swoole_socket_coro.cc index 288051522f6..8fb21478809 100644 --- a/ext-src/swoole_socket_coro.cc +++ b/ext-src/swoole_socket_coro.cc @@ -136,7 +136,7 @@ static const zend_function_entry swoole_socket_coro_methods[] = #define swoole_get_socket_coro(_sock, _zobject) \ SocketObject *_sock = socket_coro_fetch_object(Z_OBJ_P(_zobject)); \ if (UNEXPECTED(!sock->socket)) { \ - php_swoole_fatal_error(E_ERROR, "you must call Socket constructor first"); \ + swoole_fatal_error(SW_ERROR_WRONG_OPERATION, "must call constructor first"); \ } \ if (UNEXPECTED(_sock->socket->is_closed())) { \ zend_update_property_long(swoole_socket_coro_ce, SW_Z8_OBJ_P(_zobject), ZEND_STRL("errCode"), EBADF); \ diff --git a/ext-src/swoole_table.cc b/ext-src/swoole_table.cc index 585faa63839..5211f514c35 100644 --- a/ext-src/swoole_table.cc +++ b/ext-src/swoole_table.cc @@ -91,8 +91,8 @@ static inline Table *php_swoole_table_get_ptr(zval *zobject) { static inline Table *php_swoole_table_get_and_check_ptr(zval *zobject) { Table *table = php_swoole_table_get_ptr(zobject); - if (!table) { - php_swoole_fatal_error(E_ERROR, "you must call Table constructor first"); + if (UNEXPECTED(!table)) { + swoole_fatal_error(SW_ERROR_WRONG_OPERATION, "must call constructor first"); } return table; } diff --git a/ext-src/swoole_thread.cc b/ext-src/swoole_thread.cc index b3730fce62a..2068f21c3cb 100644 --- a/ext-src/swoole_thread.cc +++ b/ext-src/swoole_thread.cc @@ -56,43 +56,12 @@ struct ThreadObject { }; static void php_swoole_thread_join(zend_object *object); -static void php_swoole_thread_create(INTERNAL_FUNCTION_PARAMETERS, zval *zobject); static int php_swoole_thread_stream_fileno(zval *zstream); static bool php_swoole_thread_stream_restore(zend_long sockfd, zval *return_value); static void php_swoole_thread_register_stdio_file_handles(bool no_close); static thread_local zval thread_argv; static thread_local JMP_BUF *thread_bailout = nullptr; -static zend_long thread_resource_id = 0; -static std::unordered_map thread_resources; - -ThreadResourceId php_swoole_thread_resource_insert(ThreadResource *res) { - std::unique_lock _lock(sw_thread_lock); - zend_long resource_id = ++thread_resource_id; - thread_resources[resource_id] = res; - return resource_id; -} - -ThreadResource *php_swoole_thread_resource_fetch(ThreadResourceId resource_id) { - ThreadResource *res = nullptr; - std::unique_lock _lock(sw_thread_lock); - auto iter = thread_resources.find(resource_id); - if (iter != thread_resources.end()) { - res = iter->second; - res->add_ref(); - } - return res; -} - -bool php_swoole_thread_resource_free(ThreadResourceId resource_id, ThreadResource *res) { - std::unique_lock _lock(sw_thread_lock); - if (res->del_ref() == 0) { - thread_resources.erase(resource_id); - return true; - } else { - return false; - } -} static sw_inline ThreadObject *php_swoole_thread_fetch_object(zend_object *obj) { return (ThreadObject *) ((char *) obj - swoole_thread_handlers.offset); @@ -125,7 +94,6 @@ static PHP_METHOD(swoole_thread, __construct); static PHP_METHOD(swoole_thread, join); static PHP_METHOD(swoole_thread, joinable); static PHP_METHOD(swoole_thread, detach); -static PHP_METHOD(swoole_thread, exec); static PHP_METHOD(swoole_thread, getArguments); static PHP_METHOD(swoole_thread, getId); static PHP_METHOD(swoole_thread, getTsrmInfo); @@ -146,7 +114,7 @@ static const zend_function_entry swoole_thread_methods[] = { void php_swoole_thread_minit(int module_number) { SW_INIT_CLASS_ENTRY(swoole_thread, "Swoole\\Thread", nullptr, swoole_thread_methods); - SW_SET_CLASS_NOT_SERIALIZABLE(swoole_thread); + swoole_thread_ce->ce_flags |= ZEND_ACC_FINAL | ZEND_ACC_NOT_SERIALIZABLE; SW_SET_CLASS_CLONEABLE(swoole_thread, sw_zend_class_clone_deny); SW_SET_CLASS_UNSET_PROPERTY_HANDLER(swoole_thread, sw_zend_class_unset_property_deny); SW_SET_CLASS_CUSTOM_OBJECT( @@ -168,7 +136,40 @@ void php_swoole_thread_minit(int module_number) { } static PHP_METHOD(swoole_thread, __construct) { - php_swoole_thread_create(INTERNAL_FUNCTION_PARAM_PASSTHRU, ZEND_THIS); + char *script_file; + size_t l_script_file; + zval *args; + int argc; + ZendArray *argv = nullptr; + + ZEND_PARSE_PARAMETERS_START(1, -1) + Z_PARAM_STRING(script_file, l_script_file) + Z_PARAM_VARIADIC('+', args, argc) + ZEND_PARSE_PARAMETERS_END(); + + if (l_script_file < 1) { + zend_throw_exception(swoole_exception_ce, "exec file name is empty", SW_ERROR_INVALID_PARAMS); + return; + } + + ThreadObject *to = php_swoole_thread_fetch_object(Z_OBJ_P(ZEND_THIS)); + zend_string *file = zend_string_init(script_file, l_script_file, 1); + + if (argc > 0) { + argv = new ZendArray(); + for (int i = 0; i < argc; i++) { + argv->append(&args[i]); + } + } + + try { + to->thread = new std::thread([file, argv]() { php_swoole_thread_start(file, argv); }); + } catch (const std::exception &e) { + zend_throw_exception(swoole_exception_ce, e.what(), SW_ERROR_SYSTEM_CALL_FAIL); + return; + } + zend_update_property_long( + swoole_thread_ce, SW_Z8_OBJ_P(ZEND_THIS), ZEND_STRL("id"), (zend_long) to->thread->native_handle()); } static PHP_METHOD(swoole_thread, join) { @@ -199,95 +200,28 @@ static PHP_METHOD(swoole_thread, detach) { RETURN_TRUE; } -zval *php_swoole_thread_get_arguments() { - if (!ZVAL_IS_ARRAY(&thread_argv)) { - array_init(&thread_argv); - } - return &thread_argv; -} - static PHP_METHOD(swoole_thread, getArguments) { - RETURN_ZVAL(php_swoole_thread_get_arguments(), 1, 0); + RETURN_ZVAL(&thread_argv, 1, 0); } static PHP_METHOD(swoole_thread, getId) { RETURN_LONG((zend_long) pthread_self()); } -zend_string *php_swoole_thread_argv_serialize(zval *zdata) { +ZendArray *php_swoole_thread_argv_create(zval *zdata) { if (!ZVAL_IS_ARRAY(zdata)) { return nullptr; } - zval zdata_copy; - array_init(&zdata_copy); - zend_hash_copy(Z_ARRVAL(zdata_copy), Z_ARRVAL_P(zdata), (copy_ctor_func_t) zval_add_ref); - + auto array = new ZendArray(); zval *elem; - ZEND_HASH_FOREACH_VAL(Z_ARRVAL(zdata_copy), elem) { + ZEND_HASH_FOREACH_VAL(Z_ARRVAL_P(zdata), elem) { ZVAL_DEREF(elem); - if (Z_TYPE_P(elem) == IS_RESOURCE) { - int sockfd = php_swoole_thread_stream_fileno(elem); - if (sockfd < 0) { - continue; - } - zval_ptr_dtor(elem); - object_init_ex(elem, swoole_thread_stream_ce); - zend_update_property_long(swoole_thread_stream_ce, SW_Z8_OBJ_P(elem), ZEND_STRL("fd"), sockfd); - } else if (Z_TYPE_P(elem) == IS_OBJECT && instanceof_function(Z_OBJCE_P(elem), swoole_socket_coro_ce)) { - zend_long domain = zend::object_get_long(elem, ZEND_STRL("domain")); - zend_long type = zend::object_get_long(elem, ZEND_STRL("type")); - zend_long protocol = zend::object_get_long(elem, ZEND_STRL("protocol")); - zend_long fd = zend::object_get_long(elem, ZEND_STRL("fd")); - int sockfd = dup(fd); - if (sockfd < 0) { - continue; - } - zval_ptr_dtor(elem); - object_init_ex(elem, swoole_thread_socket_ce); - zend_update_property_long(swoole_thread_socket_ce, SW_Z8_OBJ_P(elem), ZEND_STRL("fd"), sockfd); - zend_update_property_long(swoole_thread_socket_ce, SW_Z8_OBJ_P(elem), ZEND_STRL("domain"), domain); - zend_update_property_long(swoole_thread_socket_ce, SW_Z8_OBJ_P(elem), ZEND_STRL("type"), type); - zend_update_property_long(swoole_thread_socket_ce, SW_Z8_OBJ_P(elem), ZEND_STRL("protocol"), protocol); - } + array->append(elem); } ZEND_HASH_FOREACH_END(); - auto result = php_swoole_serialize(&zdata_copy); - zval_ptr_dtor(&zdata_copy); - return result; -} - -bool php_swoole_thread_argv_unserialize(zend_string *data, zval *zv) { - bool unserialized = php_swoole_unserialize(data, zv); - if (!unserialized) { - return false; - } - - zval *elem; - ZEND_HASH_FOREACH_VAL(Z_ARRVAL_P(zv), elem) { - ZVAL_DEREF(elem); - if (Z_TYPE_P(elem) != IS_OBJECT) { - continue; - } - if (instanceof_function(Z_OBJCE_P(elem), swoole_thread_stream_ce)) { - zend_long sockfd = zend::object_get_long(elem, ZEND_STRL("fd")); - zval_ptr_dtor(elem); - zval zstream; - php_swoole_thread_stream_restore(sockfd, &zstream); - ZVAL_COPY(elem, &zstream); - } else if (instanceof_function(Z_OBJCE_P(elem), swoole_thread_socket_ce)) { - zend_long fd = zend::object_get_long(elem, ZEND_STRL("fd")); - zend_long domain = zend::object_get_long(elem, ZEND_STRL("domain")); - zend_long type = zend::object_get_long(elem, ZEND_STRL("type")); - zend_long protocol = zend::object_get_long(elem, ZEND_STRL("protocol")); - auto sockobj = php_swoole_create_socket_from_fd(fd, domain, type, protocol); - zval_ptr_dtor(elem); - ZVAL_OBJ(elem, sockobj); - } - } - ZEND_HASH_FOREACH_END(); - return true; + return array; } zend_string *php_swoole_serialize(zval *zdata) { @@ -322,22 +256,6 @@ bool php_swoole_unserialize(zend_string *data, zval *zv) { return unserialized; } -void php_swoole_thread_argv_clean(zval *zdata) { - if (!ZVAL_IS_ARRAY(zdata)) { - return; - } - zval *elem; - ZEND_HASH_FOREACH_VAL(Z_ARRVAL_P(zdata), elem) { - ZVAL_DEREF(elem); - if (Z_TYPE_P(elem) == IS_OBJECT && (instanceof_function(Z_OBJCE_P(elem), swoole_thread_stream_ce) || - instanceof_function(Z_OBJCE_P(elem), swoole_thread_socket_ce))) { - zend_long sockfd = zend::object_get_long(elem, ZEND_STRL("fd")); - close(sockfd); - } - } - ZEND_HASH_FOREACH_END(); -} - void php_swoole_thread_rinit() { if (tsrm_is_main_thread()) { if (SG(request_info).path_translated) { @@ -346,7 +264,7 @@ void php_swoole_thread_rinit() { // Return reference zval *global_argv = zend_hash_find_ind(&EG(symbol_table), ZSTR_KNOWN(ZEND_STR_ARGV)); if (global_argv) { - request_info.argv_serialized = php_swoole_thread_argv_serialize(global_argv); + request_info.argv_serialized = php_swoole_serialize(global_argv); request_info.argc = SG(request_info).argc; } } @@ -405,49 +323,7 @@ static void php_swoole_thread_register_stdio_file_handles(bool no_close) { zend_register_constant(&ec); } -static void php_swoole_thread_create(INTERNAL_FUNCTION_PARAMETERS, zval *zobject) { - char *script_file; - size_t l_script_file; - zval *args; - int argc; - - ZEND_PARSE_PARAMETERS_START(1, -1) - Z_PARAM_STRING(script_file, l_script_file) - Z_PARAM_VARIADIC('+', args, argc) - ZEND_PARSE_PARAMETERS_END(); - - if (l_script_file < 1) { - zend_throw_exception(swoole_exception_ce, "exec file name is empty", SW_ERROR_INVALID_PARAMS); - return; - } - - ThreadObject *to = php_swoole_thread_fetch_object(Z_OBJ_P(zobject)); - zend_string *file = zend_string_init(script_file, l_script_file, 1); - - zval zargv; - array_init(&zargv); - for (int i = 0; i < argc; i++) { - zend::array_add(&zargv, &args[i]); - } - zend_string *argv = php_swoole_thread_argv_serialize(&zargv); - zval_dtor(&zargv); - - if (!argv) { - zend_string_release(file); - return; - } - - try { - to->thread = new std::thread([file, argv]() { php_swoole_thread_start(file, argv); }); - } catch (const std::exception &e) { - zend_throw_exception(swoole_exception_ce, e.what(), SW_ERROR_SYSTEM_CALL_FAIL); - return; - } - zend_update_property_long( - swoole_thread_ce, SW_Z8_OBJ_P(zobject), ZEND_STRL("id"), (zend_long) to->thread->native_handle()); -} - -void php_swoole_thread_start(zend_string *file, zend_string *argv_serialized) { +void php_swoole_thread_start(zend_string *file, ZendArray *argv) { ts_resource(0); #if defined(COMPILE_DL_SWOOLE) && defined(ZTS) ZEND_TSRMLS_CACHE_UPDATE(); @@ -482,24 +358,21 @@ void php_swoole_thread_start(zend_string *file, zend_string *argv_serialized) { zend_first_try { thread_bailout = EG(bailout); - if (argv_serialized == nullptr || ZSTR_LEN(argv_serialized) == 0) { - array_init(&thread_argv); - } else { - php_swoole_thread_argv_unserialize(argv_serialized, &thread_argv); - } if (request_info.argv_serialized) { - php_swoole_thread_argv_unserialize(request_info.argv_serialized, &global_argv); + php_swoole_unserialize(request_info.argv_serialized, &global_argv); ZVAL_LONG(&global_argc, request_info.argc); zend_hash_update(&EG(symbol_table), ZSTR_KNOWN(ZEND_STR_ARGV), &global_argv); zend_hash_update(&EG(symbol_table), ZSTR_KNOWN(ZEND_STR_ARGC), &global_argc); } + if (argv) { + argv->toArray(&thread_argv); + delete argv; + } php_swoole_thread_register_stdio_file_handles(true); php_execute_script(&file_handle); } zend_end_try(); - php_swoole_thread_argv_clean(&thread_argv); - php_swoole_thread_argv_clean(&global_argv); zend_destroy_file_handle(&file_handle); php_request_shutdown(NULL); @@ -507,9 +380,6 @@ void php_swoole_thread_start(zend_string *file, zend_string *argv_serialized) { _startup_error: zend_string_release(file); - if (argv_serialized) { - zend_string_release(argv_serialized); - } ts_free_thread(); swoole_thread_clean(); } @@ -544,11 +414,6 @@ static bool php_swoole_thread_stream_restore(zend_long sockfd, zval *return_valu return false; } -static PHP_METHOD(swoole_thread, exec) { - object_init_ex(return_value, swoole_thread_ce); - php_swoole_thread_create(INTERNAL_FUNCTION_PARAM_PASSTHRU, return_value); -} - static PHP_METHOD(swoole_thread, getTsrmInfo) { array_init(return_value); add_assoc_bool(return_value, "is_main_thread", tsrm_is_main_thread()); @@ -556,6 +421,14 @@ static PHP_METHOD(swoole_thread, getTsrmInfo) { add_assoc_string(return_value, "api_name", tsrm_api_name()); } +#define CAST_OBJ_TO_RESOURCE(_name, _type) \ + else if (instanceof_function(Z_OBJCE_P(zvalue), swoole_thread_##_name##_ce)) { \ + value.resource = php_swoole_thread_##_name##_cast(zvalue); \ + value.resource->add_ref(); \ + type = _type; \ + break; \ + } + void ArrayItem::store(zval *zvalue) { type = Z_TYPE_P(zvalue); switch (type) { @@ -582,6 +455,11 @@ void ArrayItem::store(zval *zvalue) { } } /* no break */ + case IS_ARRAY: { + type = zend_array_is_list(Z_ARRVAL_P(zvalue)) ? IS_ARRAYLIST : IS_MAP; + value.resource = ZendArray::from(Z_ARRVAL_P(zvalue)); + break; + } case IS_OBJECT: { if (instanceof_function(Z_OBJCE_P(zvalue), swoole_socket_coro_ce)) { swoole::coroutine::Socket *socket = php_swoole_get_socket(zvalue); @@ -599,6 +477,13 @@ void ArrayItem::store(zval *zvalue) { break; } } + CAST_OBJ_TO_RESOURCE(arraylist, IS_ARRAYLIST) + CAST_OBJ_TO_RESOURCE(map, IS_MAP) + CAST_OBJ_TO_RESOURCE(queue, IS_QUEUE) + CAST_OBJ_TO_RESOURCE(lock, IS_LOCK) + CAST_OBJ_TO_RESOURCE(atomic, IS_ATOMIC) + CAST_OBJ_TO_RESOURCE(atomic_long, IS_ATOMIC_LONG) + CAST_OBJ_TO_RESOURCE(barrier, IS_BARRIER) } /* no break */ default: { @@ -632,6 +517,34 @@ void ArrayItem::fetch(zval *return_value) { case IS_STRING: RETVAL_NEW_STR(zend_string_init(ZSTR_VAL(value.str), ZSTR_LEN(value.str), 0)); break; + case IS_ARRAYLIST: + value.resource->add_ref(); + php_swoole_thread_arraylist_create(return_value, value.resource); + break; + case IS_QUEUE: + value.resource->add_ref(); + php_swoole_thread_queue_create(return_value, value.resource); + break; + case IS_LOCK: + value.resource->add_ref(); + php_swoole_thread_lock_create(return_value, value.resource); + break; + case IS_MAP: + value.resource->add_ref(); + php_swoole_thread_map_create(return_value, value.resource); + break; + case IS_BARRIER: + value.resource->add_ref(); + php_swoole_thread_barrier_create(return_value, value.resource); + break; + case IS_ATOMIC: + value.resource->add_ref(); + php_swoole_thread_atomic_create(return_value, value.resource); + break; + case IS_ATOMIC_LONG: + value.resource->add_ref(); + php_swoole_thread_atomic_long_create(return_value, value.resource); + break; case IS_STREAM_SOCKET: php_swoole_thread_stream_restore(value.socket.fd, return_value); break; @@ -664,6 +577,9 @@ void ArrayItem::release() { } else if (type == IS_SERIALIZED_OBJECT) { zend_string_release(value.serialized_object); value.serialized_object = nullptr; + } else if (type >= IS_ARRAYLIST && type <= IS_ATOMIC_LONG) { + value.resource->del_ref(); + value.resource = nullptr; } } @@ -743,9 +659,7 @@ void ZendArray::strkey_add(zval *zkey, zval *zvalue, zval *return_value) { if (strkey_exists(skey)) { RETVAL_FALSE; } else { - auto item = new ArrayItem(zvalue); - item->setKey(skey); - zend_hash_update_ptr(&ht, item->key, item); + add(skey, zvalue); RETVAL_TRUE; } lock_.unlock(); @@ -757,8 +671,7 @@ void ZendArray::intkey_add(zval *zkey, zval *zvalue, zval *return_value) { if (intkey_exists(index)) { RETVAL_FALSE; } else { - auto item = new ArrayItem(zvalue); - zend_hash_index_update_ptr(&ht, index, item); + add(index, zvalue); RETVAL_TRUE; } lock_.unlock(); @@ -808,6 +721,10 @@ bool ZendArray::index_offsetSet(zval *zkey, zval *zvalue) { return success; } +void ZendArray::append(zval *zvalue) { + zend_hash_next_index_insert_ptr(&ht, new ArrayItem(zvalue)); +} + bool ZendArray::index_incr(zval *zkey, zval *zvalue, zval *return_value) { zend_long index = ZVAL_IS_NULL(zkey) ? -1 : zval_get_long(zkey); @@ -866,4 +783,41 @@ void ZendArray::keys(zval *return_value) { lock_.unlock(); } +void ZendArray::toArray(zval *return_value) { + lock_.lock_rd(); + zend_ulong elem_count = zend_hash_num_elements(&ht); + array_init_size(return_value, elem_count); + zend_string *key; + zend_ulong index; + void *tmp; + ZEND_HASH_FOREACH_KEY_PTR(&ht, index, key, tmp) { + zval value; + ArrayItem *item = (ArrayItem *) tmp; + item->fetch(&value); + if (key) { + zend_hash_add(Z_ARR_P(return_value), key, &value); + } else { + zend_hash_index_add(Z_ARR_P(return_value), index, &value); + } + } + ZEND_HASH_FOREACH_END(); + lock_.unlock(); +} + +ZendArray *ZendArray::from(zend_array *src) { + zend_string *key; + zend_ulong index; + zval *tmp; + ZendArray *result = new ZendArray(); + ZEND_HASH_FOREACH_KEY_VAL(src, index, key, tmp) { + if (key) { + result->add(key, tmp); + } else { + result->add(index, tmp); + } + } + ZEND_HASH_FOREACH_END(); + return result; +} + #endif diff --git a/ext-src/swoole_thread_arraylist.cc b/ext-src/swoole_thread_arraylist.cc index 3eb0b667dea..a31b53f874f 100644 --- a/ext-src/swoole_thread_arraylist.cc +++ b/ext-src/swoole_thread_arraylist.cc @@ -41,33 +41,23 @@ static PHP_METHOD(swoole_thread_arraylist, count); static PHP_METHOD(swoole_thread_arraylist, incr); static PHP_METHOD(swoole_thread_arraylist, decr); static PHP_METHOD(swoole_thread_arraylist, clean); -static PHP_METHOD(swoole_thread_arraylist, __wakeup); +static PHP_METHOD(swoole_thread_arraylist, toArray); SW_EXTERN_C_END -static sw_inline ThreadArrayListObject *thread_arraylist_fetch_object(zend_object *obj) { +static sw_inline ThreadArrayListObject *arraylist_fetch_object(zend_object *obj) { return (ThreadArrayListObject *) ((char *) obj - swoole_thread_arraylist_handlers.offset); } -static sw_inline zend_long thread_arraylist_get_resource_id(zend_object *obj) { - zval rv, *property = zend_read_property(swoole_thread_arraylist_ce, obj, ZEND_STRL("id"), 1, &rv); - return property ? zval_get_long(property) : 0; -} - -static sw_inline zend_long thread_arraylist_get_resource_id(zval *zobject) { - return thread_arraylist_get_resource_id(Z_OBJ_P(zobject)); -} - -static void thread_arraylist_free_object(zend_object *object) { - zend_long resource_id = thread_arraylist_get_resource_id(object); - ThreadArrayListObject *ao = thread_arraylist_fetch_object(object); - if (ao->list && php_swoole_thread_resource_free(resource_id, ao->list)) { - delete ao->list; +static void arraylist_free_object(zend_object *object) { + ThreadArrayListObject *ao = arraylist_fetch_object(object); + if (ao->list) { + ao->list->del_ref(); ao->list = nullptr; } zend_object_std_dtor(object); } -static zend_object *thread_arraylist_create_object(zend_class_entry *ce) { +static zend_object *arraylist_create_object(zend_class_entry *ce) { ThreadArrayListObject *ao = (ThreadArrayListObject *) zend_object_alloc(sizeof(ThreadArrayListObject), ce); zend_object_std_init(&ao->std, ce); object_properties_init(&ao->std, ce); @@ -75,14 +65,25 @@ static zend_object *thread_arraylist_create_object(zend_class_entry *ce) { return &ao->std; } -ThreadArrayListObject *thread_arraylist_fetch_object_check(zval *zobject) { - ThreadArrayListObject *ao = thread_arraylist_fetch_object(Z_OBJ_P(zobject)); +static ThreadArrayListObject *arraylist_fetch_object_check(zval *zobject) { + ThreadArrayListObject *ao = arraylist_fetch_object(Z_OBJ_P(zobject)); if (!ao->list) { - php_swoole_fatal_error(E_ERROR, "must call constructor first"); + swoole_fatal_error(SW_ERROR_WRONG_OPERATION, "must call constructor first"); } return ao; } +ThreadResource *php_swoole_thread_arraylist_cast(zval *zobject) { + return arraylist_fetch_object_check(zobject)->list; +} + +void php_swoole_thread_arraylist_create(zval *return_value, ThreadResource *resource) { + auto obj = arraylist_create_object(swoole_thread_arraylist_ce); + auto ao = (ThreadArrayListObject *) arraylist_fetch_object(obj); + ao->list = static_cast(resource); + ZVAL_OBJ(return_value, obj); +} + // clang-format off static const zend_function_entry swoole_thread_arraylist_methods[] = { PHP_ME(swoole_thread_arraylist, __construct, arginfo_class_Swoole_Thread_ArrayList___construct, ZEND_ACC_PUBLIC) @@ -94,18 +95,19 @@ static const zend_function_entry swoole_thread_arraylist_methods[] = { PHP_ME(swoole_thread_arraylist, decr, arginfo_class_Swoole_Thread_ArrayList_decr, ZEND_ACC_PUBLIC) PHP_ME(swoole_thread_arraylist, clean, arginfo_class_Swoole_Thread_ArrayList_clean, ZEND_ACC_PUBLIC) PHP_ME(swoole_thread_arraylist, count, arginfo_class_Swoole_Thread_ArrayList_count, ZEND_ACC_PUBLIC) - PHP_ME(swoole_thread_arraylist, __wakeup, arginfo_class_Swoole_Thread_ArrayList___wakeup, ZEND_ACC_PUBLIC) + PHP_ME(swoole_thread_arraylist, toArray, arginfo_class_Swoole_Thread_ArrayList_toArray, ZEND_ACC_PUBLIC) PHP_FE_END }; // clang-format on void php_swoole_thread_arraylist_minit(int module_number) { SW_INIT_CLASS_ENTRY(swoole_thread_arraylist, "Swoole\\Thread\\ArrayList", nullptr, swoole_thread_arraylist_methods); + swoole_thread_arraylist_ce->ce_flags |= ZEND_ACC_FINAL | ZEND_ACC_NOT_SERIALIZABLE; SW_SET_CLASS_CLONEABLE(swoole_thread_arraylist, sw_zend_class_clone_deny); SW_SET_CLASS_UNSET_PROPERTY_HANDLER(swoole_thread_arraylist, sw_zend_class_unset_property_deny); SW_SET_CLASS_CUSTOM_OBJECT(swoole_thread_arraylist, - thread_arraylist_create_object, - thread_arraylist_free_object, + arraylist_create_object, + arraylist_free_object, ThreadArrayListObject, std); @@ -116,10 +118,12 @@ void php_swoole_thread_arraylist_minit(int module_number) { static PHP_METHOD(swoole_thread_arraylist, __construct) { ZEND_PARSE_PARAMETERS_NONE(); - auto ao = thread_arraylist_fetch_object(Z_OBJ_P(ZEND_THIS)); + auto ao = arraylist_fetch_object(Z_OBJ_P(ZEND_THIS)); + if (ao->list != nullptr) { + zend_throw_error(NULL, "Constructor of %s can only be called once", SW_Z_OBJCE_NAME_VAL_P(ZEND_THIS)); + return; + } ao->list = new ZendArray(); - auto resource_id = php_swoole_thread_resource_insert(ao->list); - zend_update_property_long(swoole_thread_arraylist_ce, SW_Z8_OBJ_P(ZEND_THIS), ZEND_STRL("id"), resource_id); } static PHP_METHOD(swoole_thread_arraylist, offsetGet) { @@ -129,7 +133,7 @@ static PHP_METHOD(swoole_thread_arraylist, offsetGet) { Z_PARAM_ZVAL(zkey) ZEND_PARSE_PARAMETERS_END(); - auto ao = thread_arraylist_fetch_object_check(ZEND_THIS); + auto ao = arraylist_fetch_object_check(ZEND_THIS); if (!ao->list->index_offsetGet(zkey, return_value)) { zend_throw_exception(swoole_exception_ce, "out of range", -1); } @@ -142,7 +146,7 @@ static PHP_METHOD(swoole_thread_arraylist, offsetExists) { Z_PARAM_ZVAL(zkey) ZEND_PARSE_PARAMETERS_END(); - auto ao = thread_arraylist_fetch_object_check(ZEND_THIS); + auto ao = arraylist_fetch_object_check(ZEND_THIS); ao->list->index_offsetExists(zkey, return_value); } @@ -155,7 +159,7 @@ static PHP_METHOD(swoole_thread_arraylist, offsetSet) { Z_PARAM_ZVAL(zvalue) ZEND_PARSE_PARAMETERS_END(); - auto ao = thread_arraylist_fetch_object_check(ZEND_THIS); + auto ao = arraylist_fetch_object_check(ZEND_THIS); if (!ao->list->index_offsetSet(zkey, zvalue)) { zend_throw_exception(swoole_exception_ce, "out of range", -1); } @@ -163,7 +167,7 @@ static PHP_METHOD(swoole_thread_arraylist, offsetSet) { static PHP_METHOD(swoole_thread_arraylist, incr) { INIT_ARRAY_INCR_PARAMS - auto ao = thread_arraylist_fetch_object_check(ZEND_THIS); + auto ao = arraylist_fetch_object_check(ZEND_THIS); if (!ao->list->index_incr(zkey, zvalue, return_value)) { zend_throw_exception(swoole_exception_ce, "out of range", -1); } @@ -171,7 +175,7 @@ static PHP_METHOD(swoole_thread_arraylist, incr) { static PHP_METHOD(swoole_thread_arraylist, decr) { INIT_ARRAY_INCR_PARAMS - auto ao = thread_arraylist_fetch_object_check(ZEND_THIS); + auto ao = arraylist_fetch_object_check(ZEND_THIS); if (!ao->list->index_decr(zkey, zvalue, return_value)) { zend_throw_exception(swoole_exception_ce, "out of range", -1); } @@ -182,21 +186,17 @@ static PHP_METHOD(swoole_thread_arraylist, offsetUnset) { } static PHP_METHOD(swoole_thread_arraylist, count) { - auto ao = thread_arraylist_fetch_object_check(ZEND_THIS); + auto ao = arraylist_fetch_object_check(ZEND_THIS); ao->list->count(return_value); } static PHP_METHOD(swoole_thread_arraylist, clean) { - auto ao = thread_arraylist_fetch_object_check(ZEND_THIS); + auto ao = arraylist_fetch_object_check(ZEND_THIS); ao->list->clean(); } -static PHP_METHOD(swoole_thread_arraylist, __wakeup) { - auto mo = thread_arraylist_fetch_object(Z_OBJ_P(ZEND_THIS)); - zend_long resource_id = thread_arraylist_get_resource_id(ZEND_THIS); - mo->list = static_cast(php_swoole_thread_resource_fetch(resource_id)); - if (!mo->list) { - zend_throw_exception(swoole_exception_ce, EMSG_NO_RESOURCE, ECODE_NO_RESOURCE); - } +static PHP_METHOD(swoole_thread_arraylist, toArray) { + auto ao = arraylist_fetch_object_check(ZEND_THIS); + ao->list->toArray(return_value); } #endif diff --git a/ext-src/swoole_thread_atomic.cc b/ext-src/swoole_thread_atomic.cc index 8ef1266fe3a..081f6a29a12 100644 --- a/ext-src/swoole_thread_atomic.cc +++ b/ext-src/swoole_thread_atomic.cc @@ -32,37 +32,38 @@ static zend_object_handlers swoole_thread_atomic_long_handlers; struct AtomicResource : public ThreadResource { sw_atomic_t value; + + AtomicResource(zend_long _value) : ThreadResource() { + value = _value; + } + + ~AtomicResource() override { } }; struct AtomicObject { - AtomicResource *res; + AtomicResource *atomic; zend_object std; }; -static sw_inline AtomicObject *php_swoole_thread_atomic_fetch_object(zend_object *obj) { +static sw_inline AtomicObject *atomic_fetch_object(zend_object *obj) { return (AtomicObject *) ((char *) obj - swoole_thread_atomic_handlers.offset); } -static sw_atomic_t *php_swoole_thread_atomic_get_ptr(zval *zobject) { - return &php_swoole_thread_atomic_fetch_object(Z_OBJ_P(zobject))->res->value; +static sw_atomic_t *atomic_get_ptr(zval *zobject) { + return &atomic_fetch_object(Z_OBJ_P(zobject))->atomic->value; } -static void php_swoole_thread_atomic_free_object(zend_object *object) { - AtomicObject *o = php_swoole_thread_atomic_fetch_object(object); - zend_long resource_id = zend::object_get_long(object, ZEND_STRL("id")); - if (o->res && php_swoole_thread_resource_free(resource_id, o->res)) { - delete o->res; - o->res = nullptr; +static void atomic_free_object(zend_object *object) { + AtomicObject *o = atomic_fetch_object(object); + if (o->atomic) { + o->atomic->del_ref(); + o->atomic = nullptr; } zend_object_std_dtor(object); } -static zend_object *php_swoole_thread_atomic_create_object(zend_class_entry *ce) { +static zend_object *atomic_create_object(zend_class_entry *ce) { AtomicObject *atomic = (AtomicObject *) zend_object_alloc(sizeof(AtomicObject), ce); - if (atomic == nullptr) { - zend_throw_exception(swoole_exception_ce, "global memory allocation failure", SW_ERROR_MALLOC_FAIL); - } - zend_object_std_init(&atomic->std, ce); object_properties_init(&atomic->std, ce); atomic->std.handlers = &swoole_thread_atomic_handlers; @@ -72,32 +73,37 @@ static zend_object *php_swoole_thread_atomic_create_object(zend_class_entry *ce) struct AtomicLongResource : public ThreadResource { sw_atomic_long_t value; + + AtomicLongResource(zend_long _value) : ThreadResource() { + value = _value; + } + + ~AtomicLongResource() override { } }; struct AtomicLongObject { - AtomicLongResource *res; + AtomicLongResource *atomic; zend_object std; }; -static sw_inline AtomicLongObject *php_swoole_thread_atomic_long_fetch_object(zend_object *obj) { +static sw_inline AtomicLongObject *atomic_long_fetch_object(zend_object *obj) { return (AtomicLongObject *) ((char *) obj - swoole_thread_atomic_long_handlers.offset); } -static sw_atomic_long_t *php_swoole_thread_atomic_long_get_ptr(zval *zobject) { - return &php_swoole_thread_atomic_long_fetch_object(Z_OBJ_P(zobject))->res->value; +static sw_atomic_long_t *atomic_long_get_ptr(zval *zobject) { + return &atomic_long_fetch_object(Z_OBJ_P(zobject))->atomic->value; } -static void php_swoole_thread_atomic_long_free_object(zend_object *object) { - AtomicLongObject *o = php_swoole_thread_atomic_long_fetch_object(object); - zend_long resource_id = zend::object_get_long(object, ZEND_STRL("id")); - if (o->res && php_swoole_thread_resource_free(resource_id, o->res)) { - delete o->res; - o->res = nullptr; +static void atomic_long_free_object(zend_object *object) { + AtomicLongObject *o = atomic_long_fetch_object(object); + if (o->atomic) { + o->atomic->del_ref(); + o->atomic = nullptr; } zend_object_std_dtor(object); } -static zend_object *php_swoole_thread_atomic_long_create_object(zend_class_entry *ce) { +static zend_object *atomic_long_create_object(zend_class_entry *ce) { AtomicLongObject *atomic_long = (AtomicLongObject *) zend_object_alloc(sizeof(AtomicLongObject), ce); zend_object_std_init(&atomic_long->std, ce); object_properties_init(&atomic_long->std, ce); @@ -105,6 +111,28 @@ static zend_object *php_swoole_thread_atomic_long_create_object(zend_class_entry return &atomic_long->std; } +ThreadResource *php_swoole_thread_atomic_atomic_cast(zval *zobject) { + return atomic_fetch_object(Z_OBJ_P(zobject))->atomic; +} + +ThreadResource *php_swoole_thread_atomic_atomic_long_cast(zval *zobject) { + return atomic_long_fetch_object(Z_OBJ_P(zobject))->atomic; +} + +void php_swoole_thread_atomic_create(zval *return_value, ThreadResource *resource) { + auto obj = atomic_create_object(swoole_thread_atomic_ce); + auto ao = (AtomicObject *) atomic_fetch_object(obj); + ao->atomic = static_cast(resource); + ZVAL_OBJ(return_value, obj); +} + +void php_swoole_thread_atomic_long_create(zval *return_value, ThreadResource *resource) { + auto obj = atomic_long_create_object(swoole_thread_atomic_long_ce); + auto ao = (AtomicLongObject *) atomic_long_fetch_object(obj); + ao->atomic = static_cast(resource); + ZVAL_OBJ(return_value, obj); +} + SW_EXTERN_C_BEGIN static PHP_METHOD(swoole_thread_atomic, __construct); static PHP_METHOD(swoole_thread_atomic, add); @@ -114,7 +142,6 @@ static PHP_METHOD(swoole_thread_atomic, set); static PHP_METHOD(swoole_thread_atomic, cmpset); static PHP_METHOD(swoole_thread_atomic, wait); static PHP_METHOD(swoole_thread_atomic, wakeup); -static PHP_METHOD(swoole_thread_atomic, __wakeup); static PHP_METHOD(swoole_thread_atomic_long, __construct); static PHP_METHOD(swoole_thread_atomic_long, add); @@ -122,7 +149,6 @@ static PHP_METHOD(swoole_thread_atomic_long, sub); static PHP_METHOD(swoole_thread_atomic_long, get); static PHP_METHOD(swoole_thread_atomic_long, set); static PHP_METHOD(swoole_thread_atomic_long, cmpset); -static PHP_METHOD(swoole_thread_atomic_long, __wakeup); SW_EXTERN_C_END // clang-format off @@ -136,7 +162,6 @@ static const zend_function_entry swoole_thread_atomic_methods[] = PHP_ME(swoole_thread_atomic, wait, arginfo_class_Swoole_Thread_Atomic_wait, ZEND_ACC_PUBLIC) PHP_ME(swoole_thread_atomic, wakeup, arginfo_class_Swoole_Thread_Atomic_wakeup, ZEND_ACC_PUBLIC) PHP_ME(swoole_thread_atomic, cmpset, arginfo_class_Swoole_Thread_Atomic_cmpset, ZEND_ACC_PUBLIC) - PHP_ME(swoole_thread_atomic, __wakeup, arginfo_class_Swoole_Thread_Atomic___wakeup, ZEND_ACC_PUBLIC) PHP_FE_END }; @@ -148,36 +173,35 @@ static const zend_function_entry swoole_thread_atomic_long_methods[] = PHP_ME(swoole_thread_atomic_long, get, arginfo_class_Swoole_Thread_Atomic_Long_get, ZEND_ACC_PUBLIC) PHP_ME(swoole_thread_atomic_long, set, arginfo_class_Swoole_Thread_Atomic_Long_set, ZEND_ACC_PUBLIC) PHP_ME(swoole_thread_atomic_long, cmpset, arginfo_class_Swoole_Thread_Atomic_Long_cmpset, ZEND_ACC_PUBLIC) - PHP_ME(swoole_thread_atomic_long, __wakeup, arginfo_class_Swoole_Thread_Atomic_Long___wakeup, ZEND_ACC_PUBLIC) PHP_FE_END }; // clang-format on void php_swoole_thread_atomic_minit(int module_number) { SW_INIT_CLASS_ENTRY(swoole_thread_atomic, "Swoole\\Thread\\Atomic", nullptr, swoole_thread_atomic_methods); - zend_declare_property_long(swoole_thread_atomic_ce, ZEND_STRL("id"), 0, ZEND_ACC_PUBLIC); + swoole_thread_atomic_ce->ce_flags |= ZEND_ACC_FINAL | ZEND_ACC_NOT_SERIALIZABLE; SW_SET_CLASS_CLONEABLE(swoole_thread_atomic, sw_zend_class_clone_deny); SW_SET_CLASS_UNSET_PROPERTY_HANDLER(swoole_thread_atomic, sw_zend_class_unset_property_deny); SW_SET_CLASS_CUSTOM_OBJECT(swoole_thread_atomic, - php_swoole_thread_atomic_create_object, - php_swoole_thread_atomic_free_object, + atomic_create_object, + atomic_free_object, AtomicObject, std); SW_INIT_CLASS_ENTRY( swoole_thread_atomic_long, "Swoole\\Thread\\Atomic\\Long", nullptr, swoole_thread_atomic_long_methods); - zend_declare_property_long(swoole_thread_atomic_long_ce, ZEND_STRL("id"), 0, ZEND_ACC_PUBLIC); + swoole_thread_atomic_long_ce->ce_flags |= ZEND_ACC_FINAL | ZEND_ACC_NOT_SERIALIZABLE; SW_SET_CLASS_CLONEABLE(swoole_thread_atomic_long, sw_zend_class_clone_deny); SW_SET_CLASS_UNSET_PROPERTY_HANDLER(swoole_thread_atomic_long, sw_zend_class_unset_property_deny); SW_SET_CLASS_CUSTOM_OBJECT(swoole_thread_atomic_long, - php_swoole_thread_atomic_long_create_object, - php_swoole_thread_atomic_long_free_object, + atomic_long_create_object, + atomic_long_free_object, AtomicLongObject, std); } PHP_METHOD(swoole_thread_atomic, __construct) { - auto o = php_swoole_thread_atomic_fetch_object(Z_OBJ_P(ZEND_THIS)); + auto o = atomic_fetch_object(Z_OBJ_P(ZEND_THIS)); zend_long value = 0; ZEND_PARSE_PARAMETERS_START_EX(ZEND_PARSE_PARAMS_THROW, 0, 1) @@ -185,18 +209,15 @@ PHP_METHOD(swoole_thread_atomic, __construct) { Z_PARAM_LONG(value) ZEND_PARSE_PARAMETERS_END_EX(RETURN_FALSE); - if (o->res) { + if (o->atomic) { zend_throw_error(NULL, "Constructor of %s can only be called once", SW_Z_OBJCE_NAME_VAL_P(ZEND_THIS)); - RETURN_FALSE; + return; } - o->res = new AtomicResource(); - auto resource_id = php_swoole_thread_resource_insert(o->res); - zend_update_property_long(swoole_thread_atomic_ce, SW_Z8_OBJ_P(ZEND_THIS), ZEND_STRL("id"), resource_id); - o->res->value = value; + o->atomic = new AtomicResource(value); } PHP_METHOD(swoole_thread_atomic, add) { - sw_atomic_t *atomic = php_swoole_thread_atomic_get_ptr(ZEND_THIS); + sw_atomic_t *atomic = atomic_get_ptr(ZEND_THIS); zend_long add_value = 1; ZEND_PARSE_PARAMETERS_START(0, 1) @@ -208,7 +229,7 @@ PHP_METHOD(swoole_thread_atomic, add) { } PHP_METHOD(swoole_thread_atomic, sub) { - sw_atomic_t *atomic = php_swoole_thread_atomic_get_ptr(ZEND_THIS); + sw_atomic_t *atomic = atomic_get_ptr(ZEND_THIS); zend_long sub_value = 1; ZEND_PARSE_PARAMETERS_START(0, 1) @@ -220,12 +241,12 @@ PHP_METHOD(swoole_thread_atomic, sub) { } PHP_METHOD(swoole_thread_atomic, get) { - sw_atomic_t *atomic = php_swoole_thread_atomic_get_ptr(ZEND_THIS); + sw_atomic_t *atomic = atomic_get_ptr(ZEND_THIS); RETURN_LONG(*atomic); } PHP_METHOD(swoole_thread_atomic, set) { - sw_atomic_t *atomic = php_swoole_thread_atomic_get_ptr(ZEND_THIS); + sw_atomic_t *atomic = atomic_get_ptr(ZEND_THIS); zend_long set_value; ZEND_PARSE_PARAMETERS_START(1, 1) @@ -236,7 +257,7 @@ PHP_METHOD(swoole_thread_atomic, set) { } PHP_METHOD(swoole_thread_atomic, cmpset) { - sw_atomic_t *atomic = php_swoole_thread_atomic_get_ptr(ZEND_THIS); + sw_atomic_t *atomic = atomic_get_ptr(ZEND_THIS); zend_long cmp_value, set_value; ZEND_PARSE_PARAMETERS_START(2, 2) @@ -248,7 +269,7 @@ PHP_METHOD(swoole_thread_atomic, cmpset) { } PHP_METHOD(swoole_thread_atomic, wait) { - sw_atomic_t *atomic = php_swoole_thread_atomic_get_ptr(ZEND_THIS); + sw_atomic_t *atomic = atomic_get_ptr(ZEND_THIS); double timeout = 1.0; ZEND_PARSE_PARAMETERS_START(0, 1) @@ -260,7 +281,7 @@ PHP_METHOD(swoole_thread_atomic, wait) { } PHP_METHOD(swoole_thread_atomic, wakeup) { - sw_atomic_t *atomic = php_swoole_thread_atomic_get_ptr(ZEND_THIS); + sw_atomic_t *atomic = atomic_get_ptr(ZEND_THIS); zend_long n = 1; ZEND_PARSE_PARAMETERS_START(0, 1) @@ -271,18 +292,8 @@ PHP_METHOD(swoole_thread_atomic, wakeup) { SW_CHECK_RETURN(sw_atomic_futex_wakeup(atomic, (int) n)); } -static PHP_METHOD(swoole_thread_atomic, __wakeup) { - auto o = php_swoole_thread_atomic_fetch_object(Z_OBJ_P(ZEND_THIS)); - zend_long resource_id = zend::object_get_long(ZEND_THIS, ZEND_STRL("id")); - o->res = static_cast(php_swoole_thread_resource_fetch(resource_id)); - if (!o->res) { - zend_throw_exception(swoole_exception_ce, EMSG_NO_RESOURCE, ECODE_NO_RESOURCE); - return; - } -} - PHP_METHOD(swoole_thread_atomic_long, __construct) { - auto o = php_swoole_thread_atomic_long_fetch_object(Z_OBJ_P(ZEND_THIS)); + auto o = atomic_long_fetch_object(Z_OBJ_P(ZEND_THIS)); zend_long value = 0; ZEND_PARSE_PARAMETERS_START(0, 1) @@ -290,18 +301,15 @@ PHP_METHOD(swoole_thread_atomic_long, __construct) { Z_PARAM_LONG(value) ZEND_PARSE_PARAMETERS_END_EX(RETURN_FALSE); - if (o->res) { + if (o->atomic) { zend_throw_error(NULL, "Constructor of %s can only be called once", SW_Z_OBJCE_NAME_VAL_P(ZEND_THIS)); RETURN_FALSE; } - o->res = new AtomicLongResource(); - auto resource_id = php_swoole_thread_resource_insert(o->res); - zend_update_property_long(swoole_thread_atomic_ce, SW_Z8_OBJ_P(ZEND_THIS), ZEND_STRL("id"), resource_id); - o->res->value = value; + o->atomic = new AtomicLongResource(value); } PHP_METHOD(swoole_thread_atomic_long, add) { - sw_atomic_long_t *atomic_long = php_swoole_thread_atomic_long_get_ptr(ZEND_THIS); + sw_atomic_long_t *atomic_long = atomic_long_get_ptr(ZEND_THIS); zend_long add_value = 1; ZEND_PARSE_PARAMETERS_START(0, 1) @@ -313,7 +321,7 @@ PHP_METHOD(swoole_thread_atomic_long, add) { } PHP_METHOD(swoole_thread_atomic_long, sub) { - sw_atomic_long_t *atomic_long = php_swoole_thread_atomic_long_get_ptr(ZEND_THIS); + sw_atomic_long_t *atomic_long = atomic_long_get_ptr(ZEND_THIS); zend_long sub_value = 1; ZEND_PARSE_PARAMETERS_START(0, 1) @@ -325,12 +333,12 @@ PHP_METHOD(swoole_thread_atomic_long, sub) { } PHP_METHOD(swoole_thread_atomic_long, get) { - sw_atomic_long_t *atomic_long = php_swoole_thread_atomic_long_get_ptr(ZEND_THIS); + sw_atomic_long_t *atomic_long = atomic_long_get_ptr(ZEND_THIS); RETURN_LONG(*atomic_long); } PHP_METHOD(swoole_thread_atomic_long, set) { - sw_atomic_long_t *atomic_long = php_swoole_thread_atomic_long_get_ptr(ZEND_THIS); + sw_atomic_long_t *atomic_long = atomic_long_get_ptr(ZEND_THIS); zend_long set_value; ZEND_PARSE_PARAMETERS_START(1, 1) @@ -341,7 +349,7 @@ PHP_METHOD(swoole_thread_atomic_long, set) { } PHP_METHOD(swoole_thread_atomic_long, cmpset) { - sw_atomic_long_t *atomic_long = php_swoole_thread_atomic_long_get_ptr(ZEND_THIS); + sw_atomic_long_t *atomic_long = atomic_long_get_ptr(ZEND_THIS); zend_long cmp_value, set_value; ZEND_PARSE_PARAMETERS_START(2, 2) @@ -352,13 +360,4 @@ PHP_METHOD(swoole_thread_atomic_long, cmpset) { RETURN_BOOL(sw_atomic_cmp_set(atomic_long, (sw_atomic_long_t) cmp_value, (sw_atomic_long_t) set_value)); } -static PHP_METHOD(swoole_thread_atomic_long, __wakeup) { - auto o = php_swoole_thread_atomic_long_fetch_object(Z_OBJ_P(ZEND_THIS)); - zend_long resource_id = zend::object_get_long(ZEND_THIS, ZEND_STRL("id")); - o->res = static_cast(php_swoole_thread_resource_fetch(resource_id)); - if (!o->res) { - zend_throw_exception(swoole_exception_ce, EMSG_NO_RESOURCE, ECODE_NO_RESOURCE); - return; - } -} #endif diff --git a/ext-src/swoole_thread_barrier.cc b/ext-src/swoole_thread_barrier.cc index 05d193225ed..9bf3539bf59 100644 --- a/ext-src/swoole_thread_barrier.cc +++ b/ext-src/swoole_thread_barrier.cc @@ -27,7 +27,7 @@ END_EXTERN_C() using swoole::Barrier; -static zend_class_entry *swoole_thread_barrier_ce; +zend_class_entry *swoole_thread_barrier_ce; static zend_object_handlers swoole_thread_barrier_handlers; struct BarrierResource : public ThreadResource { @@ -38,7 +38,7 @@ struct BarrierResource : public ThreadResource { void wait() { barrier_.wait(); } - ~BarrierResource() { + ~BarrierResource() override { barrier_.destroy(); } }; @@ -48,33 +48,32 @@ struct BarrierObject { zend_object std; }; -static sw_inline BarrierObject *php_swoole_thread_barrier_fetch_object(zend_object *obj) { +static sw_inline BarrierObject *barrier_fetch_object(zend_object *obj) { return (BarrierObject *) ((char *) obj - swoole_thread_barrier_handlers.offset); } -static BarrierResource *php_swoole_thread_barrier_get_ptr(zval *zobject) { - return php_swoole_thread_barrier_fetch_object(Z_OBJ_P(zobject))->barrier; +static BarrierResource *barrier_get_ptr(zval *zobject) { + return barrier_fetch_object(Z_OBJ_P(zobject))->barrier; } -static BarrierResource *php_swoole_thread_barrier_get_and_check_ptr(zval *zobject) { - BarrierResource *barrier = php_swoole_thread_barrier_get_ptr(zobject); - if (!barrier) { - php_swoole_fatal_error(E_ERROR, "must call constructor first"); +static BarrierResource *barrier_get_and_check_ptr(zval *zobject) { + BarrierResource *barrier = barrier_get_ptr(zobject); + if (UNEXPECTED(!barrier)) { + swoole_fatal_error(SW_ERROR_WRONG_OPERATION, "must call constructor first"); } return barrier; } -static void php_swoole_thread_barrier_free_object(zend_object *object) { - BarrierObject *bo = php_swoole_thread_barrier_fetch_object(object); - zend_long resource_id = zend::object_get_long(object, ZEND_STRL("id")); - if (bo->barrier && php_swoole_thread_resource_free(resource_id, bo->barrier)) { - delete bo->barrier; +static void barrier_free_object(zend_object *object) { + BarrierObject *bo = barrier_fetch_object(object); + if (bo->barrier) { + bo->barrier->del_ref(); bo->barrier = nullptr; } zend_object_std_dtor(object); } -static zend_object *php_swoole_thread_barrier_create_object(zend_class_entry *ce) { +static zend_object *barrier_create_object(zend_class_entry *ce) { BarrierObject *bo = (BarrierObject *) zend_object_alloc(sizeof(BarrierObject), ce); zend_object_std_init(&bo->std, ce); object_properties_init(&bo->std, ce); @@ -82,10 +81,20 @@ static zend_object *php_swoole_thread_barrier_create_object(zend_class_entry *ce return &bo->std; } +ThreadResource *php_swoole_thread_barrier_cast(zval *zobject) { + return barrier_fetch_object(Z_OBJ_P(zobject))->barrier; +} + +void php_swoole_thread_barrier_create(zval *return_value, ThreadResource *resource) { + auto obj = barrier_create_object(swoole_thread_barrier_ce); + auto bo = (BarrierObject *) barrier_fetch_object(obj); + bo->barrier = static_cast(resource); + ZVAL_OBJ(return_value, obj); +} + SW_EXTERN_C_BEGIN static PHP_METHOD(swoole_thread_barrier, __construct); static PHP_METHOD(swoole_thread_barrier, wait); -static PHP_METHOD(swoole_thread_barrier, __wakeup); SW_EXTERN_C_END // clang-format off @@ -93,28 +102,27 @@ static const zend_function_entry swoole_thread_barrier_methods[] = { PHP_ME(swoole_thread_barrier, __construct, arginfo_class_Swoole_Thread_Barrier___construct, ZEND_ACC_PUBLIC) PHP_ME(swoole_thread_barrier, wait, arginfo_class_Swoole_Thread_Barrier_wait, ZEND_ACC_PUBLIC) - PHP_ME(swoole_thread_barrier, __wakeup, arginfo_class_Swoole_Thread_Barrier___wakeup, ZEND_ACC_PUBLIC) PHP_FE_END }; // clang-format on void php_swoole_thread_barrier_minit(int module_number) { SW_INIT_CLASS_ENTRY(swoole_thread_barrier, "Swoole\\Thread\\Barrier", nullptr, swoole_thread_barrier_methods); - zend_declare_property_long(swoole_thread_barrier_ce, ZEND_STRL("id"), 0, ZEND_ACC_PUBLIC); + swoole_thread_barrier_ce->ce_flags |= ZEND_ACC_FINAL | ZEND_ACC_NOT_SERIALIZABLE; SW_SET_CLASS_CLONEABLE(swoole_thread_barrier, sw_zend_class_clone_deny); SW_SET_CLASS_UNSET_PROPERTY_HANDLER(swoole_thread_barrier, sw_zend_class_unset_property_deny); SW_SET_CLASS_CUSTOM_OBJECT(swoole_thread_barrier, - php_swoole_thread_barrier_create_object, - php_swoole_thread_barrier_free_object, + barrier_create_object, + barrier_free_object, BarrierObject, std); } static PHP_METHOD(swoole_thread_barrier, __construct) { - auto bo = php_swoole_thread_barrier_fetch_object(Z_OBJ_P(ZEND_THIS)); + auto bo = barrier_fetch_object(Z_OBJ_P(ZEND_THIS)); if (bo->barrier != nullptr) { zend_throw_error(NULL, "Constructor of %s can only be called once", SW_Z_OBJCE_NAME_VAL_P(ZEND_THIS)); - RETURN_FALSE; + return; } zend_long count; @@ -125,29 +133,17 @@ static PHP_METHOD(swoole_thread_barrier, __construct) { if (count < 2) { zend_throw_exception( swoole_exception_ce, "The parameter $count must be greater than 1", SW_ERROR_INVALID_PARAMS); - RETURN_FALSE; + return; } bo->barrier = new BarrierResource(count); - auto resource_id = php_swoole_thread_resource_insert(bo->barrier); - zend_update_property_long(swoole_thread_barrier_ce, SW_Z8_OBJ_P(ZEND_THIS), ZEND_STRL("id"), resource_id); - RETURN_TRUE; } static PHP_METHOD(swoole_thread_barrier, wait) { - BarrierResource *barrier = php_swoole_thread_barrier_get_and_check_ptr(ZEND_THIS); + BarrierResource *barrier = barrier_get_and_check_ptr(ZEND_THIS); if (barrier) { barrier->wait(); } } -static PHP_METHOD(swoole_thread_barrier, __wakeup) { - auto bo = php_swoole_thread_barrier_fetch_object(Z_OBJ_P(ZEND_THIS)); - zend_long resource_id = zend::object_get_long(ZEND_THIS, ZEND_STRL("id")); - bo->barrier = static_cast(php_swoole_thread_resource_fetch(resource_id)); - if (!bo->barrier) { - zend_throw_exception(swoole_exception_ce, EMSG_NO_RESOURCE, ECODE_NO_RESOURCE); - return; - } -} #endif diff --git a/ext-src/swoole_thread_lock.cc b/ext-src/swoole_thread_lock.cc index 7ced5d50023..df6aa88e717 100644 --- a/ext-src/swoole_thread_lock.cc +++ b/ext-src/swoole_thread_lock.cc @@ -34,7 +34,7 @@ using swoole::SpinLock; using swoole::RWLock; #endif -static zend_class_entry *swoole_thread_lock_ce; +zend_class_entry *swoole_thread_lock_ce; static zend_object_handlers swoole_thread_lock_handlers; struct LockResource : public ThreadResource { @@ -57,7 +57,7 @@ struct LockResource : public ThreadResource { break; } } - ~LockResource() { + ~LockResource() override { delete lock_; } }; @@ -67,33 +67,32 @@ struct LockObject { zend_object std; }; -static sw_inline LockObject *php_swoole_thread_lock_fetch_object(zend_object *obj) { +static sw_inline LockObject *lock_fetch_object(zend_object *obj) { return (LockObject *) ((char *) obj - swoole_thread_lock_handlers.offset); } -static Lock *php_swoole_thread_lock_get_ptr(zval *zobject) { - return php_swoole_thread_lock_fetch_object(Z_OBJ_P(zobject))->lock->lock_; +static Lock *lock_get_ptr(zval *zobject) { + return lock_fetch_object(Z_OBJ_P(zobject))->lock->lock_; } -static Lock *php_swoole_thread_lock_get_and_check_ptr(zval *zobject) { - Lock *lock = php_swoole_thread_lock_get_ptr(zobject); +static Lock *lock_get_and_check_ptr(zval *zobject) { + Lock *lock = lock_get_ptr(zobject); if (!lock) { php_swoole_fatal_error(E_ERROR, "must call constructor first"); } return lock; } -static void php_swoole_thread_lock_free_object(zend_object *object) { - LockObject *o = php_swoole_thread_lock_fetch_object(object); - zend_long resource_id = zend::object_get_long(object, ZEND_STRL("id")); - if (o->lock && php_swoole_thread_resource_free(resource_id, o->lock)) { - delete o->lock; +static void lock_free_object(zend_object *object) { + LockObject *o = lock_fetch_object(object); + if (o->lock) { + o->lock->del_ref(); o->lock = nullptr; } zend_object_std_dtor(object); } -static zend_object *php_swoole_thread_lock_create_object(zend_class_entry *ce) { +static zend_object *lock_create_object(zend_class_entry *ce) { LockObject *lock = (LockObject *) zend_object_alloc(sizeof(LockObject), ce); zend_object_std_init(&lock->std, ce); object_properties_init(&lock->std, ce); @@ -101,6 +100,17 @@ static zend_object *php_swoole_thread_lock_create_object(zend_class_entry *ce) { return &lock->std; } +ThreadResource *php_swoole_thread_lock_cast(zval *zobject) { + return lock_fetch_object(Z_OBJ_P(zobject))->lock; +} + +void php_swoole_thread_lock_create(zval *return_value, ThreadResource *resource) { + auto obj = lock_create_object(swoole_thread_lock_ce); + auto lo = (LockObject *) lock_fetch_object(obj); + lo->lock = static_cast(resource); + ZVAL_OBJ(return_value, obj); +} + SW_EXTERN_C_BEGIN static PHP_METHOD(swoole_thread_lock, __construct); static PHP_METHOD(swoole_thread_lock, __destruct); @@ -111,7 +121,6 @@ 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); -static PHP_METHOD(swoole_thread_lock, __wakeup); SW_EXTERN_C_END // clang-format off @@ -125,18 +134,17 @@ static const zend_function_entry swoole_thread_lock_methods[] = PHP_ME(swoole_thread_lock, lock_read, arginfo_class_Swoole_Thread_Lock_lock_read, ZEND_ACC_PUBLIC) PHP_ME(swoole_thread_lock, trylock_read, arginfo_class_Swoole_Thread_Lock_trylock_read, ZEND_ACC_PUBLIC) PHP_ME(swoole_thread_lock, unlock, arginfo_class_Swoole_Thread_Lock_unlock, ZEND_ACC_PUBLIC) - PHP_ME(swoole_thread_lock, __wakeup, arginfo_class_Swoole_Thread_Lock___wakeup, ZEND_ACC_PUBLIC) PHP_FE_END }; // clang-format on void php_swoole_thread_lock_minit(int module_number) { SW_INIT_CLASS_ENTRY(swoole_thread_lock, "Swoole\\Thread\\Lock", nullptr, swoole_thread_lock_methods); - zend_declare_property_long(swoole_thread_lock_ce, ZEND_STRL("id"), 0, ZEND_ACC_PUBLIC); + swoole_thread_lock_ce->ce_flags |= ZEND_ACC_FINAL | ZEND_ACC_NOT_SERIALIZABLE; SW_SET_CLASS_CLONEABLE(swoole_thread_lock, sw_zend_class_clone_deny); SW_SET_CLASS_UNSET_PROPERTY_HANDLER(swoole_thread_lock, sw_zend_class_unset_property_deny); SW_SET_CLASS_CUSTOM_OBJECT( - swoole_thread_lock, php_swoole_thread_lock_create_object, php_swoole_thread_lock_free_object, LockObject, std); + swoole_thread_lock, lock_create_object, lock_free_object, LockObject, std); zend_declare_class_constant_long(swoole_thread_lock_ce, ZEND_STRL("MUTEX"), Lock::MUTEX); #ifdef HAVE_RWLOCK @@ -146,13 +154,10 @@ void php_swoole_thread_lock_minit(int module_number) { zend_declare_class_constant_long(swoole_thread_lock_ce, ZEND_STRL("SPINLOCK"), Lock::SPIN_LOCK); #endif zend_declare_property_long(swoole_thread_lock_ce, ZEND_STRL("errCode"), 0, ZEND_ACC_PUBLIC); -#ifdef SW_THREAD - zend_declare_property_long(swoole_thread_lock_ce, ZEND_STRL("id"), 0, ZEND_ACC_PUBLIC | ZEND_ACC_READONLY); -#endif } static PHP_METHOD(swoole_thread_lock, __construct) { - auto o = php_swoole_thread_lock_fetch_object(Z_OBJ_P(ZEND_THIS)); + auto o = lock_fetch_object(Z_OBJ_P(ZEND_THIS)); if (o->lock != nullptr) { zend_throw_error(NULL, "Constructor of %s can only be called once", SW_Z_OBJCE_NAME_VAL_P(ZEND_THIS)); RETURN_FALSE; @@ -166,15 +171,12 @@ static PHP_METHOD(swoole_thread_lock, __construct) { ZEND_PARSE_PARAMETERS_END(); o->lock = new LockResource(type); - auto resource_id = php_swoole_thread_resource_insert(o->lock); - zend_update_property_long(swoole_thread_lock_ce, SW_Z8_OBJ_P(ZEND_THIS), ZEND_STRL("id"), resource_id); - RETURN_TRUE; } static PHP_METHOD(swoole_thread_lock, __destruct) {} static PHP_METHOD(swoole_thread_lock, lock) { - Lock *lock = php_swoole_thread_lock_get_and_check_ptr(ZEND_THIS); + Lock *lock = lock_get_and_check_ptr(ZEND_THIS); SW_LOCK_CHECK_RETURN(lock->lock()); } @@ -184,7 +186,7 @@ static PHP_METHOD(swoole_thread_lock, lockwait) { if (zend_parse_parameters(ZEND_NUM_ARGS(), "d", &timeout) == FAILURE) { RETURN_FALSE; } - Lock *lock = php_swoole_thread_lock_get_and_check_ptr(ZEND_THIS); + Lock *lock = lock_get_and_check_ptr(ZEND_THIS); if (lock->get_type() != Lock::MUTEX) { zend_throw_exception(swoole_exception_ce, "only mutex supports lockwait", -2); RETURN_FALSE; @@ -198,33 +200,23 @@ static PHP_METHOD(swoole_thread_lock, lockwait) { } static PHP_METHOD(swoole_thread_lock, unlock) { - Lock *lock = php_swoole_thread_lock_get_and_check_ptr(ZEND_THIS); + Lock *lock = lock_get_and_check_ptr(ZEND_THIS); SW_LOCK_CHECK_RETURN(lock->unlock()); } static PHP_METHOD(swoole_thread_lock, trylock) { - Lock *lock = php_swoole_thread_lock_get_and_check_ptr(ZEND_THIS); + Lock *lock = lock_get_and_check_ptr(ZEND_THIS); SW_LOCK_CHECK_RETURN(lock->trylock()); } static PHP_METHOD(swoole_thread_lock, trylock_read) { - Lock *lock = php_swoole_thread_lock_get_and_check_ptr(ZEND_THIS); + Lock *lock = lock_get_and_check_ptr(ZEND_THIS); SW_LOCK_CHECK_RETURN(lock->trylock_rd()); } static PHP_METHOD(swoole_thread_lock, lock_read) { - Lock *lock = php_swoole_thread_lock_get_and_check_ptr(ZEND_THIS); + Lock *lock = lock_get_and_check_ptr(ZEND_THIS); SW_LOCK_CHECK_RETURN(lock->lock_rd()); } -static PHP_METHOD(swoole_thread_lock, __wakeup) { - auto o = php_swoole_thread_lock_fetch_object(Z_OBJ_P(ZEND_THIS)); - zend_long resource_id = zend::object_get_long(ZEND_THIS, ZEND_STRL("id")); - o->lock = static_cast(php_swoole_thread_resource_fetch(resource_id)); - if (!o->lock) { - zend_throw_exception(swoole_exception_ce, EMSG_NO_RESOURCE, ECODE_NO_RESOURCE); - return; - } -} - #endif diff --git a/ext-src/swoole_thread_map.cc b/ext-src/swoole_thread_map.cc index ff1858d21bb..b454a569a9d 100644 --- a/ext-src/swoole_thread_map.cc +++ b/ext-src/swoole_thread_map.cc @@ -31,30 +31,20 @@ struct ThreadMapObject { zend_object std; }; -static sw_inline ThreadMapObject *thread_map_fetch_object(zend_object *obj) { +static sw_inline ThreadMapObject *map_fetch_object(zend_object *obj) { return (ThreadMapObject *) ((char *) obj - swoole_thread_map_handlers.offset); } -static sw_inline zend_long thread_map_get_resource_id(zend_object *obj) { - zval rv, *property = zend_read_property(swoole_thread_map_ce, obj, ZEND_STRL("id"), 1, &rv); - return property ? zval_get_long(property) : 0; -} - -static sw_inline zend_long thread_map_get_resource_id(zval *zobject) { - return thread_map_get_resource_id(Z_OBJ_P(zobject)); -} - -static void thread_map_free_object(zend_object *object) { - zend_long resource_id = thread_map_get_resource_id(object); - ThreadMapObject *mo = thread_map_fetch_object(object); - if (mo->map && php_swoole_thread_resource_free(resource_id, mo->map)) { - delete mo->map; +static void map_free_object(zend_object *object) { + ThreadMapObject *mo = map_fetch_object(object); + if (mo->map) { + mo->map->del_ref(); mo->map = nullptr; } zend_object_std_dtor(object); } -static zend_object *thread_map_create_object(zend_class_entry *ce) { +static zend_object *map_create_object(zend_class_entry *ce) { ThreadMapObject *mo = (ThreadMapObject *) zend_object_alloc(sizeof(ThreadMapObject), ce); zend_object_std_init(&mo->std, ce); object_properties_init(&mo->std, ce); @@ -62,14 +52,25 @@ static zend_object *thread_map_create_object(zend_class_entry *ce) { return &mo->std; } -ThreadMapObject *thread_map_fetch_object_check(zval *zobject) { - ThreadMapObject *map = thread_map_fetch_object(Z_OBJ_P(zobject)); +static ThreadMapObject *map_fetch_object_check(zval *zobject) { + ThreadMapObject *map = map_fetch_object(Z_OBJ_P(zobject)); if (!map->map) { php_swoole_fatal_error(E_ERROR, "must call constructor first"); } return map; } +ThreadResource *php_swoole_thread_map_cast(zval *zobject) { + return map_fetch_object(Z_OBJ_P(zobject))->map; +} + +void php_swoole_thread_map_create(zval *return_value, ThreadResource *resource) { + auto obj = map_create_object(swoole_thread_map_ce); + auto mo = (ThreadMapObject *) map_fetch_object(obj); + mo->map = static_cast(resource); + ZVAL_OBJ(return_value, obj); +} + SW_EXTERN_C_BEGIN static PHP_METHOD(swoole_thread_map, __construct); static PHP_METHOD(swoole_thread_map, offsetGet); @@ -83,7 +84,7 @@ static PHP_METHOD(swoole_thread_map, decr); static PHP_METHOD(swoole_thread_map, add); static PHP_METHOD(swoole_thread_map, update); static PHP_METHOD(swoole_thread_map, clean); -static PHP_METHOD(swoole_thread_map, __wakeup); +static PHP_METHOD(swoole_thread_map, toArray); SW_EXTERN_C_END // clang-format off @@ -100,27 +101,29 @@ static const zend_function_entry swoole_thread_map_methods[] = { PHP_ME(swoole_thread_map, update, arginfo_class_Swoole_Thread_Map_update, ZEND_ACC_PUBLIC) PHP_ME(swoole_thread_map, clean, arginfo_class_Swoole_Thread_Map_clean, ZEND_ACC_PUBLIC) PHP_ME(swoole_thread_map, keys, arginfo_class_Swoole_Thread_Map_keys, ZEND_ACC_PUBLIC) - PHP_ME(swoole_thread_map, __wakeup, arginfo_class_Swoole_Thread_Map___wakeup, ZEND_ACC_PUBLIC) + PHP_ME(swoole_thread_map, toArray, arginfo_class_Swoole_Thread_Map_toArray, ZEND_ACC_PUBLIC) PHP_FE_END }; // clang-format on void php_swoole_thread_map_minit(int module_number) { SW_INIT_CLASS_ENTRY(swoole_thread_map, "Swoole\\Thread\\Map", nullptr, swoole_thread_map_methods); + swoole_thread_map_ce->ce_flags |= ZEND_ACC_FINAL | ZEND_ACC_NOT_SERIALIZABLE; SW_SET_CLASS_CLONEABLE(swoole_thread_map, sw_zend_class_clone_deny); SW_SET_CLASS_UNSET_PROPERTY_HANDLER(swoole_thread_map, sw_zend_class_unset_property_deny); SW_SET_CLASS_CUSTOM_OBJECT( - swoole_thread_map, thread_map_create_object, thread_map_free_object, ThreadMapObject, std); + swoole_thread_map, map_create_object, map_free_object, ThreadMapObject, std); zend_class_implements(swoole_thread_map_ce, 2, zend_ce_arrayaccess, zend_ce_countable); - zend_declare_property_long(swoole_thread_map_ce, ZEND_STRL("id"), 0, ZEND_ACC_PUBLIC); } static PHP_METHOD(swoole_thread_map, __construct) { - auto mo = thread_map_fetch_object(Z_OBJ_P(ZEND_THIS)); + auto mo = map_fetch_object(Z_OBJ_P(ZEND_THIS)); + if (mo->map != nullptr) { + zend_throw_error(NULL, "Constructor of %s can only be called once", SW_Z_OBJCE_NAME_VAL_P(ZEND_THIS)); + return; + } mo->map = new ZendArray(); - auto resource_id = php_swoole_thread_resource_insert(mo->map); - zend_update_property_long(swoole_thread_map_ce, SW_Z8_OBJ_P(ZEND_THIS), ZEND_STRL("id"), resource_id); } #define ZEND_ARRAY_CALL_METHOD(array, method, zkey, ...) \ @@ -137,7 +140,7 @@ static PHP_METHOD(swoole_thread_map, offsetGet) { Z_PARAM_ZVAL(zkey) ZEND_PARSE_PARAMETERS_END(); - auto mo = thread_map_fetch_object_check(ZEND_THIS); + auto mo = map_fetch_object_check(ZEND_THIS); ZEND_ARRAY_CALL_METHOD(mo->map, offsetGet, zkey, return_value); } @@ -148,7 +151,7 @@ static PHP_METHOD(swoole_thread_map, offsetExists) { Z_PARAM_ZVAL(zkey) ZEND_PARSE_PARAMETERS_END(); - auto mo = thread_map_fetch_object_check(ZEND_THIS); + auto mo = map_fetch_object_check(ZEND_THIS); ZEND_ARRAY_CALL_METHOD(mo->map, offsetExists, zkey, return_value); } @@ -161,19 +164,19 @@ static PHP_METHOD(swoole_thread_map, offsetSet) { Z_PARAM_ZVAL(zvalue) ZEND_PARSE_PARAMETERS_END(); - auto mo = thread_map_fetch_object_check(ZEND_THIS); + auto mo = map_fetch_object_check(ZEND_THIS); ZEND_ARRAY_CALL_METHOD(mo->map, offsetSet, zkey, zvalue); } static PHP_METHOD(swoole_thread_map, incr) { INIT_ARRAY_INCR_PARAMS - auto mo = thread_map_fetch_object_check(ZEND_THIS); + auto mo = map_fetch_object_check(ZEND_THIS); ZEND_ARRAY_CALL_METHOD(mo->map, incr, zkey, zvalue, return_value); } static PHP_METHOD(swoole_thread_map, decr) { INIT_ARRAY_INCR_PARAMS - auto mo = thread_map_fetch_object_check(ZEND_THIS); + auto mo = map_fetch_object_check(ZEND_THIS); ZEND_ARRAY_CALL_METHOD(mo->map, decr, zkey, zvalue, return_value); } @@ -186,7 +189,7 @@ static PHP_METHOD(swoole_thread_map, add) { Z_PARAM_ZVAL(zvalue) ZEND_PARSE_PARAMETERS_END(); - auto mo = thread_map_fetch_object_check(ZEND_THIS); + auto mo = map_fetch_object_check(ZEND_THIS); ZEND_ARRAY_CALL_METHOD(mo->map, add, zkey, zvalue, return_value); } @@ -199,7 +202,7 @@ static PHP_METHOD(swoole_thread_map, update) { Z_PARAM_ZVAL(zvalue) ZEND_PARSE_PARAMETERS_END(); - auto mo = thread_map_fetch_object_check(ZEND_THIS); + auto mo = map_fetch_object_check(ZEND_THIS); ZEND_ARRAY_CALL_METHOD(mo->map, update, zkey, zvalue, return_value); } @@ -210,32 +213,28 @@ static PHP_METHOD(swoole_thread_map, offsetUnset) { Z_PARAM_ZVAL(zkey) ZEND_PARSE_PARAMETERS_END(); - auto mo = thread_map_fetch_object_check(ZEND_THIS); + auto mo = map_fetch_object_check(ZEND_THIS); ZEND_ARRAY_CALL_METHOD(mo->map, offsetUnset, zkey); } static PHP_METHOD(swoole_thread_map, count) { - auto mo = thread_map_fetch_object_check(ZEND_THIS); + auto mo = map_fetch_object_check(ZEND_THIS); mo->map->count(return_value); } static PHP_METHOD(swoole_thread_map, keys) { - auto mo = thread_map_fetch_object_check(ZEND_THIS); + auto mo = map_fetch_object_check(ZEND_THIS); mo->map->keys(return_value); } -static PHP_METHOD(swoole_thread_map, clean) { - auto mo = thread_map_fetch_object_check(ZEND_THIS); - mo->map->clean(); +static PHP_METHOD(swoole_thread_map, toArray) { + auto mo = map_fetch_object_check(ZEND_THIS); + mo->map->toArray(return_value); } -static PHP_METHOD(swoole_thread_map, __wakeup) { - auto mo = thread_map_fetch_object(Z_OBJ_P(ZEND_THIS)); - zend_long resource_id = thread_map_get_resource_id(ZEND_THIS); - mo->map = static_cast(php_swoole_thread_resource_fetch(resource_id)); - if (!mo->map) { - zend_throw_exception(swoole_exception_ce, EMSG_NO_RESOURCE, ECODE_NO_RESOURCE); - } +static PHP_METHOD(swoole_thread_map, clean) { + auto mo = map_fetch_object_check(ZEND_THIS); + mo->map->clean(); } #endif diff --git a/ext-src/swoole_thread_queue.cc b/ext-src/swoole_thread_queue.cc index daa5c68a97c..f2baa099696 100644 --- a/ext-src/swoole_thread_queue.cc +++ b/ext-src/swoole_thread_queue.cc @@ -39,7 +39,7 @@ struct Queue : ThreadResource { Queue() : ThreadResource(), queue() {} - ~Queue() { + ~Queue() override { clean(); } @@ -122,30 +122,20 @@ struct ThreadQueueObject { zend_object std; }; -static sw_inline ThreadQueueObject *thread_queue_fetch_object(zend_object *obj) { +static sw_inline ThreadQueueObject *queue_fetch_object(zend_object *obj) { return (ThreadQueueObject *) ((char *) obj - swoole_thread_queue_handlers.offset); } -static sw_inline zend_long thread_queue_get_resource_id(zend_object *obj) { - zval rv, *property = zend_read_property(swoole_thread_queue_ce, obj, ZEND_STRL("id"), 1, &rv); - return property ? zval_get_long(property) : 0; -} - -static sw_inline zend_long thread_queue_get_resource_id(zval *zobject) { - return thread_queue_get_resource_id(Z_OBJ_P(zobject)); -} - -static void thread_queue_free_object(zend_object *object) { - zend_long resource_id = thread_queue_get_resource_id(object); - ThreadQueueObject *qo = thread_queue_fetch_object(object); - if (qo->queue && php_swoole_thread_resource_free(resource_id, qo->queue)) { - delete qo->queue; +static void queue_free_object(zend_object *object) { + ThreadQueueObject *qo = queue_fetch_object(object); + if (qo->queue) { + qo->queue->del_ref(); qo->queue = nullptr; } zend_object_std_dtor(object); } -static zend_object *thread_queue_create_object(zend_class_entry *ce) { +static zend_object *queue_create_object(zend_class_entry *ce) { ThreadQueueObject *qo = (ThreadQueueObject *) zend_object_alloc(sizeof(ThreadQueueObject), ce); zend_object_std_init(&qo->std, ce); object_properties_init(&qo->std, ce); @@ -153,21 +143,31 @@ static zend_object *thread_queue_create_object(zend_class_entry *ce) { return &qo->std; } -ThreadQueueObject *thread_queue_fetch_object_check(zval *zobject) { - ThreadQueueObject *qo = thread_queue_fetch_object(Z_OBJ_P(zobject)); +ThreadQueueObject *queue_fetch_object_check(zval *zobject) { + ThreadQueueObject *qo = queue_fetch_object(Z_OBJ_P(zobject)); if (!qo->queue) { php_swoole_fatal_error(E_ERROR, "must call constructor first"); } return qo; } +ThreadResource *php_swoole_thread_queue_cast(zval *zobject) { + return queue_fetch_object(Z_OBJ_P(zobject))->queue; +} + +void php_swoole_thread_queue_create(zval *return_value, ThreadResource *resource) { + auto obj = queue_create_object(swoole_thread_queue_ce); + auto qo = (ThreadQueueObject *) queue_fetch_object(obj); + qo->queue = static_cast(resource); + ZVAL_OBJ(return_value, obj); +} + SW_EXTERN_C_BEGIN static PHP_METHOD(swoole_thread_queue, __construct); static PHP_METHOD(swoole_thread_queue, push); static PHP_METHOD(swoole_thread_queue, pop); static PHP_METHOD(swoole_thread_queue, count); static PHP_METHOD(swoole_thread_queue, clean); -static PHP_METHOD(swoole_thread_queue, __wakeup); SW_EXTERN_C_END // clang-format off @@ -177,30 +177,31 @@ static const zend_function_entry swoole_thread_queue_methods[] = { PHP_ME(swoole_thread_queue, pop, arginfo_class_Swoole_Thread_Queue_pop, ZEND_ACC_PUBLIC) PHP_ME(swoole_thread_queue, clean, arginfo_class_Swoole_Thread_Queue_clean, ZEND_ACC_PUBLIC) PHP_ME(swoole_thread_queue, count, arginfo_class_Swoole_Thread_Queue_count, ZEND_ACC_PUBLIC) - PHP_ME(swoole_thread_queue, __wakeup, arginfo_class_Swoole_Thread_Queue___wakeup, ZEND_ACC_PUBLIC) PHP_FE_END }; // clang-format on void php_swoole_thread_queue_minit(int module_number) { SW_INIT_CLASS_ENTRY(swoole_thread_queue, "Swoole\\Thread\\Queue", nullptr, swoole_thread_queue_methods); + swoole_thread_queue_ce->ce_flags |= ZEND_ACC_FINAL | ZEND_ACC_NOT_SERIALIZABLE; SW_SET_CLASS_CLONEABLE(swoole_thread_queue, sw_zend_class_clone_deny); SW_SET_CLASS_UNSET_PROPERTY_HANDLER(swoole_thread_queue, sw_zend_class_unset_property_deny); SW_SET_CLASS_CUSTOM_OBJECT( - swoole_thread_queue, thread_queue_create_object, thread_queue_free_object, ThreadQueueObject, std); + swoole_thread_queue, queue_create_object, queue_free_object, ThreadQueueObject, std); zend_class_implements(swoole_thread_queue_ce, 1, zend_ce_countable); - zend_declare_property_long(swoole_thread_queue_ce, ZEND_STRL("id"), 0, ZEND_ACC_PUBLIC | ZEND_ACC_READONLY); zend_declare_class_constant_long(swoole_thread_queue_ce, ZEND_STRL("NOTIFY_ONE"), Queue::NOTIFY_ONE); zend_declare_class_constant_long(swoole_thread_queue_ce, ZEND_STRL("NOTIFY_ALL"), Queue::NOTIFY_ALL); } static PHP_METHOD(swoole_thread_queue, __construct) { - auto qo = thread_queue_fetch_object(Z_OBJ_P(ZEND_THIS)); + auto qo = queue_fetch_object(Z_OBJ_P(ZEND_THIS)); + if (qo->queue != nullptr) { + zend_throw_error(NULL, "Constructor of %s can only be called once", SW_Z_OBJCE_NAME_VAL_P(ZEND_THIS)); + return; + } qo->queue = new Queue(); - auto resource_id = php_swoole_thread_resource_insert(qo->queue); - zend_update_property_long(swoole_thread_queue_ce, SW_Z8_OBJ_P(ZEND_THIS), ZEND_STRL("id"), resource_id); } static PHP_METHOD(swoole_thread_queue, push) { @@ -213,7 +214,7 @@ static PHP_METHOD(swoole_thread_queue, push) { Z_PARAM_LONG(notify_which) ZEND_PARSE_PARAMETERS_END(); - auto qo = thread_queue_fetch_object_check(ZEND_THIS); + auto qo = queue_fetch_object_check(ZEND_THIS); if (notify_which > 0) { qo->queue->push_notify(zvalue, notify_which == Queue::NOTIFY_ALL); } else { @@ -229,7 +230,7 @@ static PHP_METHOD(swoole_thread_queue, pop) { Z_PARAM_DOUBLE(timeout) ZEND_PARSE_PARAMETERS_END(); - auto qo = thread_queue_fetch_object_check(ZEND_THIS); + auto qo = queue_fetch_object_check(ZEND_THIS); if (timeout == 0) { qo->queue->pop(return_value); } else { @@ -238,22 +239,13 @@ static PHP_METHOD(swoole_thread_queue, pop) { } static PHP_METHOD(swoole_thread_queue, count) { - auto qo = thread_queue_fetch_object_check(ZEND_THIS); + auto qo = queue_fetch_object_check(ZEND_THIS); qo->queue->count(return_value); } static PHP_METHOD(swoole_thread_queue, clean) { - auto qo = thread_queue_fetch_object_check(ZEND_THIS); + auto qo = queue_fetch_object_check(ZEND_THIS); qo->queue->clean(); } -static PHP_METHOD(swoole_thread_queue, __wakeup) { - auto qo = thread_queue_fetch_object(Z_OBJ_P(ZEND_THIS)); - zend_long resource_id = thread_queue_get_resource_id(ZEND_THIS); - qo->queue = static_cast(php_swoole_thread_resource_fetch(resource_id)); - if (!qo->queue) { - zend_throw_exception(swoole_exception_ce, EMSG_NO_RESOURCE, ECODE_NO_RESOURCE); - } -} - #endif From a61d959fc8a0151453af39c980d672d8c27e0dbe Mon Sep 17 00:00:00 2001 From: hantianfeng Date: Mon, 1 Jul 2024 17:43:53 +0800 Subject: [PATCH 02/11] fix --- ext-src/swoole_thread_atomic.cc | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/ext-src/swoole_thread_atomic.cc b/ext-src/swoole_thread_atomic.cc index 081f6a29a12..5d5dce07d73 100644 --- a/ext-src/swoole_thread_atomic.cc +++ b/ext-src/swoole_thread_atomic.cc @@ -111,11 +111,11 @@ static zend_object *atomic_long_create_object(zend_class_entry *ce) { return &atomic_long->std; } -ThreadResource *php_swoole_thread_atomic_atomic_cast(zval *zobject) { +ThreadResource *php_swoole_thread_atomic_cast(zval *zobject) { return atomic_fetch_object(Z_OBJ_P(zobject))->atomic; } -ThreadResource *php_swoole_thread_atomic_atomic_long_cast(zval *zobject) { +ThreadResource *php_swoole_thread_atomic_long_cast(zval *zobject) { return atomic_long_fetch_object(Z_OBJ_P(zobject))->atomic; } From ab91af687a66abf1a924fd6c67674719ee592dc8 Mon Sep 17 00:00:00 2001 From: hantianfeng Date: Mon, 1 Jul 2024 18:42:01 +0800 Subject: [PATCH 03/11] fix, optimize code, refactor arraylist/map ctor: Allow array as ctor method parameter --- ext-src/php_swoole_thread.h | 1 - .../php_swoole_thread_arraylist.stub.php | 2 +- .../php_swoole_thread_arraylist_arginfo.h | 3 +- ext-src/stubs/php_swoole_thread_map.stub.php | 2 +- ext-src/stubs/php_swoole_thread_map_arginfo.h | 3 +- ext-src/swoole_server.cc | 8 ++- ext-src/swoole_thread.cc | 53 ++++--------------- ext-src/swoole_thread_arraylist.cc | 17 +++++- ext-src/swoole_thread_map.cc | 13 ++++- tests/swoole_thread/arraylist.phpt | 43 +++++++++++++++ tests/swoole_thread/map.phpt | 36 +++++++++++++ 11 files changed, 130 insertions(+), 51 deletions(-) create mode 100644 tests/swoole_thread/arraylist.phpt create mode 100644 tests/swoole_thread/map.phpt diff --git a/ext-src/php_swoole_thread.h b/ext-src/php_swoole_thread.h index 1becd93ffc4..17acf2f7520 100644 --- a/ext-src/php_swoole_thread.h +++ b/ext-src/php_swoole_thread.h @@ -36,7 +36,6 @@ extern zend_class_entry *swoole_thread_map_ce; extern zend_class_entry *swoole_thread_queue_ce; void php_swoole_thread_start(zend_string *file, ZendArray *argv); -ZendArray *php_swoole_thread_argv_create(zval *zdata); zend_string *php_swoole_serialize(zval *zdata); bool php_swoole_unserialize(zend_string *data, zval *zv); void php_swoole_thread_bailout(void); diff --git a/ext-src/stubs/php_swoole_thread_arraylist.stub.php b/ext-src/stubs/php_swoole_thread_arraylist.stub.php index 10c2e443d5c..ad44d417850 100644 --- a/ext-src/stubs/php_swoole_thread_arraylist.stub.php +++ b/ext-src/stubs/php_swoole_thread_arraylist.stub.php @@ -1,7 +1,7 @@ init_arguments)) { zval _thread_argv; call_user_function(NULL, NULL, &server_object->init_arguments, &_thread_argv, 0, NULL); - thread_argv = php_swoole_thread_argv_create(&_thread_argv); + if (ZVAL_IS_ARRAY(&_thread_argv)) { + thread_argv = ZendArray::from(Z_ARRVAL(_thread_argv)); + } zval_ptr_dtor(&_thread_argv); } serv->worker_thread_start = [bootstrap, thread_argv](const WorkerFn &fn) { worker_thread_fn = fn; zend_string *bootstrap_copy = zend_string_dup(bootstrap, 1); + thread_argv->add_ref(); php_swoole_thread_start(bootstrap_copy, thread_argv); }; } @@ -2674,6 +2677,9 @@ static PHP_METHOD(swoole_server, start) { if (bootstrap) { zend_string_release(bootstrap); } + if (thread_argv) { + thread_argv->del_ref(); + } #endif RETURN_TRUE; diff --git a/ext-src/swoole_thread.cc b/ext-src/swoole_thread.cc index 2068f21c3cb..4e683576624 100644 --- a/ext-src/swoole_thread.cc +++ b/ext-src/swoole_thread.cc @@ -34,12 +34,6 @@ END_EXTERN_C() zend_class_entry *swoole_thread_ce; static zend_object_handlers swoole_thread_handlers; -zend_class_entry *swoole_thread_stream_ce; -static zend_object_handlers swoole_thread_stream_handlers; - -zend_class_entry *swoole_thread_socket_ce; -static zend_object_handlers swoole_thread_socket_handlers; - static struct { char *path_translated; zend_string *argv_serialized; @@ -63,16 +57,16 @@ static void php_swoole_thread_register_stdio_file_handles(bool no_close); static thread_local zval thread_argv; static thread_local JMP_BUF *thread_bailout = nullptr; -static sw_inline ThreadObject *php_swoole_thread_fetch_object(zend_object *obj) { +static sw_inline ThreadObject *thread_fetch_object(zend_object *obj) { return (ThreadObject *) ((char *) obj - swoole_thread_handlers.offset); } -static void php_swoole_thread_free_object(zend_object *object) { +static void thread_free_object(zend_object *object) { php_swoole_thread_join(object); zend_object_std_dtor(object); } -static zend_object *php_swoole_thread_create_object(zend_class_entry *ce) { +static zend_object *thread_create_object(zend_class_entry *ce) { ThreadObject *to = (ThreadObject *) zend_object_alloc(sizeof(ThreadObject), ce); zend_object_std_init(&to->std, ce); object_properties_init(&to->std, ce); @@ -81,7 +75,7 @@ static zend_object *php_swoole_thread_create_object(zend_class_entry *ce) { } static void php_swoole_thread_join(zend_object *object) { - ThreadObject *to = php_swoole_thread_fetch_object(object); + ThreadObject *to = thread_fetch_object(object); if (to->thread && to->thread->joinable()) { to->thread->join(); delete to->thread; @@ -118,21 +112,11 @@ void php_swoole_thread_minit(int module_number) { SW_SET_CLASS_CLONEABLE(swoole_thread, sw_zend_class_clone_deny); SW_SET_CLASS_UNSET_PROPERTY_HANDLER(swoole_thread, sw_zend_class_unset_property_deny); SW_SET_CLASS_CUSTOM_OBJECT( - swoole_thread, php_swoole_thread_create_object, php_swoole_thread_free_object, ThreadObject, std); + swoole_thread, thread_create_object, thread_free_object, ThreadObject, std); zend_declare_property_long(swoole_thread_ce, ZEND_STRL("id"), 0, ZEND_ACC_PUBLIC | ZEND_ACC_READONLY); zend_declare_class_constant_long( swoole_thread_ce, ZEND_STRL("HARDWARE_CONCURRENCY"), std::thread::hardware_concurrency()); - - // only used for thread argument forwarding - SW_INIT_CLASS_ENTRY_DATA_OBJECT(swoole_thread_stream, "Swoole\\Thread\\Stream"); - zend_declare_property_long(swoole_thread_stream_ce, ZEND_STRL("fd"), 0, ZEND_ACC_PUBLIC | ZEND_ACC_READONLY); - - SW_INIT_CLASS_ENTRY_DATA_OBJECT(swoole_thread_socket, "Swoole\\Thread\\Socket"); - zend_declare_property_long(swoole_thread_socket_ce, ZEND_STRL("fd"), 0, ZEND_ACC_PUBLIC | ZEND_ACC_READONLY); - zend_declare_property_long(swoole_thread_socket_ce, ZEND_STRL("domain"), 0, ZEND_ACC_PUBLIC | ZEND_ACC_READONLY); - zend_declare_property_long(swoole_thread_socket_ce, ZEND_STRL("type"), 0, ZEND_ACC_PUBLIC | ZEND_ACC_READONLY); - zend_declare_property_long(swoole_thread_socket_ce, ZEND_STRL("protocol"), 0, ZEND_ACC_PUBLIC | ZEND_ACC_READONLY); } static PHP_METHOD(swoole_thread, __construct) { @@ -152,7 +136,7 @@ static PHP_METHOD(swoole_thread, __construct) { return; } - ThreadObject *to = php_swoole_thread_fetch_object(Z_OBJ_P(ZEND_THIS)); + ThreadObject *to = thread_fetch_object(Z_OBJ_P(ZEND_THIS)); zend_string *file = zend_string_init(script_file, l_script_file, 1); if (argc > 0) { @@ -173,7 +157,7 @@ static PHP_METHOD(swoole_thread, __construct) { } static PHP_METHOD(swoole_thread, join) { - ThreadObject *to = php_swoole_thread_fetch_object(Z_OBJ_P(ZEND_THIS)); + ThreadObject *to = thread_fetch_object(Z_OBJ_P(ZEND_THIS)); if (!to || !to->thread || !to->thread->joinable()) { RETURN_FALSE; } @@ -182,7 +166,7 @@ static PHP_METHOD(swoole_thread, join) { } static PHP_METHOD(swoole_thread, joinable) { - ThreadObject *to = php_swoole_thread_fetch_object(Z_OBJ_P(ZEND_THIS)); + ThreadObject *to = thread_fetch_object(Z_OBJ_P(ZEND_THIS)); if (to == nullptr || !to->thread) { RETURN_FALSE; } @@ -190,7 +174,7 @@ static PHP_METHOD(swoole_thread, joinable) { } static PHP_METHOD(swoole_thread, detach) { - ThreadObject *to = php_swoole_thread_fetch_object(Z_OBJ_P(ZEND_THIS)); + ThreadObject *to = thread_fetch_object(Z_OBJ_P(ZEND_THIS)); if (to == nullptr || !to->thread) { RETURN_FALSE; } @@ -208,22 +192,6 @@ static PHP_METHOD(swoole_thread, getId) { RETURN_LONG((zend_long) pthread_self()); } -ZendArray *php_swoole_thread_argv_create(zval *zdata) { - if (!ZVAL_IS_ARRAY(zdata)) { - return nullptr; - } - - auto array = new ZendArray(); - zval *elem; - ZEND_HASH_FOREACH_VAL(Z_ARRVAL_P(zdata), elem) { - ZVAL_DEREF(elem); - array->append(elem); - } - ZEND_HASH_FOREACH_END(); - - return array; -} - zend_string *php_swoole_serialize(zval *zdata) { php_serialize_data_t var_hash; smart_str serialized_data = {0}; @@ -366,7 +334,7 @@ void php_swoole_thread_start(zend_string *file, ZendArray *argv) { } if (argv) { argv->toArray(&thread_argv); - delete argv; + argv->del_ref(); } php_swoole_thread_register_stdio_file_handles(true); php_execute_script(&file_handle); @@ -810,6 +778,7 @@ ZendArray *ZendArray::from(zend_array *src) { zval *tmp; ZendArray *result = new ZendArray(); ZEND_HASH_FOREACH_KEY_VAL(src, index, key, tmp) { + ZVAL_DEREF(tmp); if (key) { result->add(key, tmp); } else { diff --git a/ext-src/swoole_thread_arraylist.cc b/ext-src/swoole_thread_arraylist.cc index a31b53f874f..7858a81a515 100644 --- a/ext-src/swoole_thread_arraylist.cc +++ b/ext-src/swoole_thread_arraylist.cc @@ -116,14 +116,27 @@ void php_swoole_thread_arraylist_minit(int module_number) { } static PHP_METHOD(swoole_thread_arraylist, __construct) { - ZEND_PARSE_PARAMETERS_NONE(); + zend_array *array = nullptr; + ZEND_PARSE_PARAMETERS_START(0, 1) + Z_PARAM_OPTIONAL + Z_PARAM_ARRAY_HT_OR_NULL(array) + ZEND_PARSE_PARAMETERS_END(); auto ao = arraylist_fetch_object(Z_OBJ_P(ZEND_THIS)); if (ao->list != nullptr) { zend_throw_error(NULL, "Constructor of %s can only be called once", SW_Z_OBJCE_NAME_VAL_P(ZEND_THIS)); return; } - ao->list = new ZendArray(); + + if (array) { + if (!zend_array_is_list(array)) { + zend_throw_error(NULL, "the parameter $array must be an array of type list"); + return; + } + ao->list = ZendArray::from(array); + } else { + ao->list = new ZendArray(); + } } static PHP_METHOD(swoole_thread_arraylist, offsetGet) { diff --git a/ext-src/swoole_thread_map.cc b/ext-src/swoole_thread_map.cc index b454a569a9d..58350cc4173 100644 --- a/ext-src/swoole_thread_map.cc +++ b/ext-src/swoole_thread_map.cc @@ -118,12 +118,23 @@ void php_swoole_thread_map_minit(int module_number) { } static PHP_METHOD(swoole_thread_map, __construct) { + zend_array *array = nullptr; + ZEND_PARSE_PARAMETERS_START(0, 1) + Z_PARAM_OPTIONAL + Z_PARAM_ARRAY_HT_OR_NULL(array) + ZEND_PARSE_PARAMETERS_END(); + auto mo = map_fetch_object(Z_OBJ_P(ZEND_THIS)); if (mo->map != nullptr) { zend_throw_error(NULL, "Constructor of %s can only be called once", SW_Z_OBJCE_NAME_VAL_P(ZEND_THIS)); return; } - mo->map = new ZendArray(); + + if (array) { + mo->map = ZendArray::from(array); + } else { + mo->map = new ZendArray(); + } } #define ZEND_ARRAY_CALL_METHOD(array, method, zkey, ...) \ diff --git a/tests/swoole_thread/arraylist.phpt b/tests/swoole_thread/arraylist.phpt new file mode 100644 index 00000000000..2e9cd5967d3 --- /dev/null +++ b/tests/swoole_thread/arraylist.phpt @@ -0,0 +1,43 @@ +--TEST-- +swoole_thread: arraylist +--SKIPIF-- + +--FILE-- +toArray(), $array); + +for ($i = 0; $i < count($array); $i++) { + Assert::eq($l[$i], $array[$i]); +} + +$array2 = [ + 'key' => 'value', + 'hello' => 'world', +]; +$l[] = $array2; + +Assert::eq($l[4]->toArray(), $array2); + +try { + $l2 = new ArrayList($array2); + echo "never here\n"; +} catch (Throwable $e) { + Assert::contains($e->getMessage(), 'must be an array of type list'); +} +?> +--EXPECTF-- diff --git a/tests/swoole_thread/map.phpt b/tests/swoole_thread/map.phpt new file mode 100644 index 00000000000..063f5210431 --- /dev/null +++ b/tests/swoole_thread/map.phpt @@ -0,0 +1,36 @@ +--TEST-- +swoole_thread: map +--SKIPIF-- + +--FILE-- + random_int(1, 999999999999999999), + 'b' => random_bytes(128), + 'c' => uniqid(), + 'd' => time(), +]; + +$m = new Map($array); +Assert::eq($m->toArray(), $array); + +foreach ($array as $k => $v) { + Assert::eq($m[$k], $array[$k]); +} + +$array2 = [ + 'key' => 'value', + 'hello' => 'world', +]; +$m['map'] = $array2; + +Assert::eq($m['map']->toArray(), $array2); +?> +--EXPECTF-- From c19214ab18a60d52d84220576ebdcfee463f5530 Mon Sep 17 00:00:00 2001 From: hantianfeng Date: Tue, 2 Jul 2024 10:37:58 +0800 Subject: [PATCH 04/11] fix tests --- tests/swoole_channel_coro/no_ctor.phpt | 18 ++++++++------ .../channel_construct_check.phpt | 24 ++++++++++--------- .../swoole_global/socket_construct_check.phpt | 21 ++++++++-------- .../connect_twice.phpt | 9 +++---- 4 files changed, 40 insertions(+), 32 deletions(-) diff --git a/tests/swoole_channel_coro/no_ctor.phpt b/tests/swoole_channel_coro/no_ctor.phpt index 1e497c6a4c9..1404f9065da 100644 --- a/tests/swoole_channel_coro/no_ctor.phpt +++ b/tests/swoole_channel_coro/no_ctor.phpt @@ -6,17 +6,21 @@ swoole_channel_coro: no ctor pop(); +$pm = ProcessManager::exec(function () { + go(function () { + $chan = new MyChan(100); + $chan->pop(); + }); }); +Assert::contains($pm->getChildOutput(), "must call constructor first"); ?> ---EXPECTF-- -Fatal error: Swoole\Coroutine\Channel::pop(): you must call Channel constructor first in %s on line %d +--EXPECT-- diff --git a/tests/swoole_global/channel_construct_check.phpt b/tests/swoole_global/channel_construct_check.phpt index c33fd6461d2..a796002c3a9 100644 --- a/tests/swoole_global/channel_construct_check.phpt +++ b/tests/swoole_global/channel_construct_check.phpt @@ -5,16 +5,18 @@ swoole_global: socket construct check --FILE-- push('123'); + +$pm = ProcessManager::exec(function () { + go(function () { + $chan = new class () extends Co\Channel { + public function __construct($size = 1) + { + // parent::__construct($size); // without parent call + } + }; + $chan->push('123'); + }); }); +Assert::contains($pm->getChildOutput(), "must call constructor first"); ?> ---EXPECTF-- -Fatal error: Swoole\Coroutine\Channel::push(): you must call Channel constructor first in %s on line %d +--EXPECT-- diff --git a/tests/swoole_global/socket_construct_check.phpt b/tests/swoole_global/socket_construct_check.phpt index b9c97b54c41..1a18346ffed 100644 --- a/tests/swoole_global/socket_construct_check.phpt +++ b/tests/swoole_global/socket_construct_check.phpt @@ -5,16 +5,17 @@ swoole_global: socket construct check --FILE-- connect('127.0.0.1', 12345); +$pm = ProcessManager::exec(function () { + go(function () { + $socket = new class (1, 2, 3) extends Co\Socket { + public function __construct($domain, $type, $protocol) + { + // parent::__construct($domain, $type, $protocol); // without parent call + } + }; + $socket->connect('127.0.0.1', 12345); + }); }); +Assert::contains($pm->getChildOutput(), "must call constructor first"); ?> --EXPECTF-- -Fatal error: Swoole\Coroutine\Socket::connect(): you must call Socket constructor first in %s on line %d diff --git a/tests/swoole_http2_client_coro/connect_twice.phpt b/tests/swoole_http2_client_coro/connect_twice.phpt index 798ca5f724b..d9455da54fb 100644 --- a/tests/swoole_http2_client_coro/connect_twice.phpt +++ b/tests/swoole_http2_client_coro/connect_twice.phpt @@ -6,6 +6,7 @@ swoole_http2_client_coro: connect twice connect(); - $req = new \Swoole\Http2\Request(); + $req = new Request(); $req->method = 'GET'; $req->path = '/io?io=' . str_repeat('xxx', 1000); $client->send($req); $chan->push(true); $resp = $client->recv(); - Assert::eq($resp->statusCode, 200); - Assert::contains($resp->data, '知乎'); + Assert::eq($resp->statusCode, 302); + Assert::contains($resp->data, '302 Found'); $chan->pop(); }); go(function () use ($client, $chan) { Assert::eq($client->connect(), false); - $req = new \Swoole\Http2\Request(); + $req = new Request(); $req->method = 'GET'; $req->path = '/io?io=xxx'; $client->send($req); From d468afe76ea45dd97898a45d862878552057be94 Mon Sep 17 00:00:00 2001 From: hantianfeng Date: Wed, 3 Jul 2024 14:19:35 +0800 Subject: [PATCH 05/11] Prohibit constructing objects on the stack --- ext-src/php_swoole_thread.h | 1 + 1 file changed, 1 insertion(+) diff --git a/ext-src/php_swoole_thread.h b/ext-src/php_swoole_thread.h index 17acf2f7520..7a137e856f6 100644 --- a/ext-src/php_swoole_thread.h +++ b/ext-src/php_swoole_thread.h @@ -90,6 +90,7 @@ class ThreadResource { } } + protected: virtual ~ThreadResource() {} }; From 483f2b26a867c101cb6180a4acbaa46d8520b749 Mon Sep 17 00:00:00 2001 From: hantianfeng Date: Wed, 3 Jul 2024 14:19:45 +0800 Subject: [PATCH 06/11] Fix tests --- tests/include/api/curl_multi.php | 4 ++-- tests/swoole_curl/ssl/version.phpt | 4 ++-- tests/swoole_http_client_coro/http_proxy.phpt | 4 ++-- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/tests/include/api/curl_multi.php b/tests/include/api/curl_multi.php index 30126dba6e0..bbe7d29c387 100644 --- a/tests/include/api/curl_multi.php +++ b/tests/include/api/curl_multi.php @@ -14,7 +14,7 @@ function swoole_test_curl_multi_ex($mh, $options = []) { curl_setopt($ch1, CURLOPT_HEADER, 0); curl_setopt($ch1, CURLOPT_RETURNTRANSFER, 1); - curl_setopt($ch2, CURLOPT_URL, "https://www.zhihu.com/"); + curl_setopt($ch2, CURLOPT_URL, "https://www.taobao.com/"); curl_setopt($ch2, CURLOPT_HEADER, 0); curl_setopt($ch2, CURLOPT_RETURNTRANSFER, 1); @@ -61,7 +61,7 @@ function swoole_test_curl_multi_ex($mh, $options = []) { Assert::eq($info3, false); Assert::contains(curl_multi_getcontent($ch1), 'baidu.com'); - Assert::contains(curl_multi_getcontent($ch2), 'zhihu'); + Assert::contains(curl_multi_getcontent($ch2), 'taobao.com'); curl_multi_remove_handle($mh, $ch1); curl_multi_remove_handle($mh, $ch2); diff --git a/tests/swoole_curl/ssl/version.phpt b/tests/swoole_curl/ssl/version.phpt index 5647a6a0bb3..fdeb18c6e31 100644 --- a/tests/swoole_curl/ssl/version.phpt +++ b/tests/swoole_curl/ssl/version.phpt @@ -16,10 +16,10 @@ $cm->run(function ($host) { curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, FALSE); curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 2); curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); - curl_setopt($ch, CURLOPT_URL, "https://www.qq.com/"); + curl_setopt($ch, CURLOPT_URL, "https://www.baidu.com/"); $result = curl_exec($ch); Assert::assert($result); - Assert::contains($result, 'tencent'); + Assert::contains($result, '百度'); curl_close($ch); }, false); diff --git a/tests/swoole_http_client_coro/http_proxy.phpt b/tests/swoole_http_client_coro/http_proxy.phpt index 21158bd5fc3..af8d9c39619 100644 --- a/tests/swoole_http_client_coro/http_proxy.phpt +++ b/tests/swoole_http_client_coro/http_proxy.phpt @@ -10,7 +10,7 @@ skip_if_offline(); setHeaders(['Host' => $domain]); // without host header it can also work well $cli->set([ @@ -20,7 +20,7 @@ go(function () { ]); $result = $cli->get('/'); Assert::assert($result); - Assert::assert(stripos($cli->body, 'tencent') !== false); + Assert::assert(stripos($cli->body, '百度') !== false); echo "DONE\n"; }); ?> From be6c2cc3b689d012c9961bae3266defd8976a729 Mon Sep 17 00:00:00 2001 From: hantianfeng Date: Wed, 3 Jul 2024 16:43:11 +0800 Subject: [PATCH 07/11] optimize code, fix tests --- ext-src/php_swoole_cxx.h | 4 + ext-src/php_swoole_thread.h | 8 ++ ext-src/swoole_thread.cc | 92 +++++++++++-------- tests/include/api/curl_multi.php | 4 +- .../connect_twice.phpt | 4 +- 5 files changed, 71 insertions(+), 41 deletions(-) diff --git a/ext-src/php_swoole_cxx.h b/ext-src/php_swoole_cxx.h index f0ce177322f..4947cbdb031 100644 --- a/ext-src/php_swoole_cxx.h +++ b/ext-src/php_swoole_cxx.h @@ -670,6 +670,10 @@ static inline void object_set(zval *obj, const char *name, size_t l_name, const zend_update_property_string(Z_OBJCE_P(obj), Z_OBJ_P(obj), name, l_name, value); } +static inline void object_set(zval *obj, const char *name, size_t l_name, zend_long value) { + zend_update_property_long(Z_OBJCE_P(obj), Z_OBJ_P(obj), name, l_name, value); +} + static inline zval *object_get(zval *obj, const char *name, size_t l_name) { static zval rv; return zend_read_property(Z_OBJCE_P(obj), Z_OBJ_P(obj), name, l_name, 1, &rv); diff --git a/ext-src/php_swoole_thread.h b/ext-src/php_swoole_thread.h index 7a137e856f6..bd00a424788 100644 --- a/ext-src/php_swoole_thread.h +++ b/ext-src/php_swoole_thread.h @@ -27,6 +27,8 @@ typedef uint32_t ThreadResourceId; struct ThreadResource; struct ZendArray; +extern zend_class_entry *swoole_thread_ce; +extern zend_class_entry *swoole_thread_error_ce; extern zend_class_entry *swoole_thread_arraylist_ce; extern zend_class_entry *swoole_thread_atomic_ce; extern zend_class_entry *swoole_thread_atomic_long_ce; @@ -56,6 +58,12 @@ void php_swoole_thread_atomic_create(zval *return_value, ThreadResource *resourc void php_swoole_thread_atomic_long_create(zval *return_value, ThreadResource *resource); void php_swoole_thread_barrier_create(zval *return_value, ThreadResource *resource); +int php_swoole_thread_stream_cast(zval *zstream); +void php_swoole_thread_stream_create(zval *return_value, zend_long sockfd); + +int php_swoole_thread_co_socket_cast(zval *zstream, swSocketType *type); +void php_swoole_thread_co_socket_create(zval *return_value, zend_long sockfd, swSocketType type); + #define EMSG_NO_RESOURCE "resource not found" #define ECODE_NO_RESOURCE -2 diff --git a/ext-src/swoole_thread.cc b/ext-src/swoole_thread.cc index 4e683576624..7468083184e 100644 --- a/ext-src/swoole_thread.cc +++ b/ext-src/swoole_thread.cc @@ -31,8 +31,8 @@ BEGIN_EXTERN_C() #include "stubs/php_swoole_thread_arginfo.h" END_EXTERN_C() -zend_class_entry *swoole_thread_ce; static zend_object_handlers swoole_thread_handlers; +static zend_object_handlers swoole_thread_error_handlers; static struct { char *path_translated; @@ -50,8 +50,6 @@ struct ThreadObject { }; static void php_swoole_thread_join(zend_object *object); -static int php_swoole_thread_stream_fileno(zval *zstream); -static bool php_swoole_thread_stream_restore(zend_long sockfd, zval *return_value); static void php_swoole_thread_register_stdio_file_handles(bool no_close); static thread_local zval thread_argv; @@ -117,6 +115,9 @@ void php_swoole_thread_minit(int module_number) { zend_declare_property_long(swoole_thread_ce, ZEND_STRL("id"), 0, ZEND_ACC_PUBLIC | ZEND_ACC_READONLY); zend_declare_class_constant_long( swoole_thread_ce, ZEND_STRL("HARDWARE_CONCURRENCY"), std::thread::hardware_concurrency()); + + SW_INIT_CLASS_ENTRY_DATA_OBJECT(swoole_thread_error, "Swoole\\Thread\\Error"); + zend_declare_property_long(swoole_thread_error_ce, ZEND_STRL("code"), 0, ZEND_ACC_PUBLIC | ZEND_ACC_READONLY); } static PHP_METHOD(swoole_thread, __construct) { @@ -359,7 +360,7 @@ void php_swoole_thread_bailout(void) { } } -static int php_swoole_thread_stream_fileno(zval *zstream) { +int php_swoole_thread_stream_cast(zval *zstream) { php_stream *stream; int sockfd; int cast_flags = PHP_STREAM_AS_FD_FOR_SELECT | PHP_STREAM_CAST_INTERNAL; @@ -371,15 +372,49 @@ static int php_swoole_thread_stream_fileno(zval *zstream) { return -1; } -static bool php_swoole_thread_stream_restore(zend_long sockfd, zval *return_value) { +int php_swoole_thread_co_socket_cast(zval *zvalue, swSocketType *type) { + swoole::coroutine::Socket *socket = php_swoole_get_socket(zvalue); + if (!socket) { + return -1; + } + int sockfd = socket->get_fd(); + if (sockfd < 0) { + return -1; + } + int newfd = dup(sockfd); + if (newfd < 0) { + return -1; + } + *type = socket->get_type(); + return newfd; +} + +void php_swoole_thread_stream_create(zval *return_value, zend_long sockfd) { std::string path = "php://fd/" + std::to_string(sockfd); // The file descriptor will be duplicated once here php_stream *stream = php_stream_open_wrapper_ex(path.c_str(), "", 0, NULL, NULL); if (stream) { php_stream_to_zval(stream, return_value); - return true; + } else { + object_init_ex(return_value, swoole_thread_error_ce); + zend::object_set(return_value, ZEND_STRL("code"), errno); + } +} + +void php_swoole_thread_co_socket_create(zval *return_value, zend_long sockfd, swSocketType type) { + int newfd = dup(sockfd); + if (newfd < 0) { + object_init_ex(return_value, swoole_thread_error_ce); + zend::object_set(return_value, ZEND_STRL("code"), errno); + return; + } + zend_object *sockobj = php_swoole_create_socket_from_fd(newfd, type); + if (sockobj) { + ZVAL_OBJ(return_value, sockobj); + } else { + // never here + abort(); } - return false; } static PHP_METHOD(swoole_thread, getTsrmInfo) { @@ -415,14 +450,13 @@ void ArrayItem::store(zval *zvalue) { case IS_NULL: break; case IS_RESOURCE: { - int sock_fd = php_swoole_thread_stream_fileno(zvalue); - if (sock_fd != -1) { - value.socket.fd = sock_fd; - type = IS_STREAM_SOCKET; - break; + value.socket.fd = php_swoole_thread_stream_cast(zvalue); + type = IS_STREAM_SOCKET; + if (value.socket.fd == -1) { + zend_throw_exception(swoole_exception_ce, "failed to convert to socket fd", errno); } + break; } - /* no break */ case IS_ARRAY: { type = zend_array_is_list(Z_ARRVAL_P(zvalue)) ? IS_ARRAYLIST : IS_MAP; value.resource = ZendArray::from(Z_ARRVAL_P(zvalue)); @@ -430,20 +464,12 @@ void ArrayItem::store(zval *zvalue) { } case IS_OBJECT: { if (instanceof_function(Z_OBJCE_P(zvalue), swoole_socket_coro_ce)) { - swoole::coroutine::Socket *socket = php_swoole_get_socket(zvalue); - if (socket) { - int sockfd = socket->get_fd(); - if (sockfd < 0) { - break; - } - value.socket.fd = dup(sockfd); - if (value.socket.fd < 0) { - break; - } - value.socket.type = socket->get_type(); - type = IS_CO_SOCKET; - break; + value.socket.fd = php_swoole_thread_co_socket_cast(zvalue, &value.socket.type); + type = IS_CO_SOCKET; + if (value.socket.fd == -1) { + zend_throw_exception(swoole_exception_ce, "failed to convert to socket fd", errno); } + break; } CAST_OBJ_TO_RESOURCE(arraylist, IS_ARRAYLIST) CAST_OBJ_TO_RESOURCE(map, IS_MAP) @@ -514,19 +540,11 @@ void ArrayItem::fetch(zval *return_value) { php_swoole_thread_atomic_long_create(return_value, value.resource); break; case IS_STREAM_SOCKET: - php_swoole_thread_stream_restore(value.socket.fd, return_value); + php_swoole_thread_stream_create(return_value, value.socket.fd); break; - case IS_CO_SOCKET: { - int sockfd = dup(value.socket.fd); - if (sockfd < 0) { - break; - } - zend_object *sockobj = php_swoole_create_socket_from_fd(sockfd, value.socket.type); - if (sockobj) { - ZVAL_OBJ(return_value, sockobj); - } + case IS_CO_SOCKET: + php_swoole_thread_co_socket_create(return_value, value.socket.fd, value.socket.type); break; - } case IS_SERIALIZED_OBJECT: php_swoole_unserialize(value.serialized_object, return_value); break; diff --git a/tests/include/api/curl_multi.php b/tests/include/api/curl_multi.php index bbe7d29c387..30d457e8d8c 100644 --- a/tests/include/api/curl_multi.php +++ b/tests/include/api/curl_multi.php @@ -14,7 +14,7 @@ function swoole_test_curl_multi_ex($mh, $options = []) { curl_setopt($ch1, CURLOPT_HEADER, 0); curl_setopt($ch1, CURLOPT_RETURNTRANSFER, 1); - curl_setopt($ch2, CURLOPT_URL, "https://www.taobao.com/"); + curl_setopt($ch2, CURLOPT_URL, "https://www.gov.cn/"); curl_setopt($ch2, CURLOPT_HEADER, 0); curl_setopt($ch2, CURLOPT_RETURNTRANSFER, 1); @@ -61,7 +61,7 @@ function swoole_test_curl_multi_ex($mh, $options = []) { Assert::eq($info3, false); Assert::contains(curl_multi_getcontent($ch1), 'baidu.com'); - Assert::contains(curl_multi_getcontent($ch2), 'taobao.com'); + Assert::contains(curl_multi_getcontent($ch2), '中国政府网'); curl_multi_remove_handle($mh, $ch1); curl_multi_remove_handle($mh, $ch2); diff --git a/tests/swoole_http2_client_coro/connect_twice.phpt b/tests/swoole_http2_client_coro/connect_twice.phpt index d9455da54fb..56fc140fd93 100644 --- a/tests/swoole_http2_client_coro/connect_twice.phpt +++ b/tests/swoole_http2_client_coro/connect_twice.phpt @@ -21,8 +21,8 @@ run(function () { $client->send($req); $chan->push(true); $resp = $client->recv(); - Assert::eq($resp->statusCode, 302); - Assert::contains($resp->data, '302 Found'); + Assert::eq($resp->statusCode, 200); + Assert::contains($resp->data, '知乎'); $chan->pop(); }); go(function () use ($client, $chan) { From 24ee7fb60f1642e2ed56df180a8e5c71e490f310 Mon Sep 17 00:00:00 2001 From: hantianfeng Date: Wed, 3 Jul 2024 17:11:23 +0800 Subject: [PATCH 08/11] fix tests --- ext-src/swoole_thread.cc | 3 +++ 1 file changed, 3 insertions(+) diff --git a/ext-src/swoole_thread.cc b/ext-src/swoole_thread.cc index 7468083184e..524bb479c20 100644 --- a/ext-src/swoole_thread.cc +++ b/ext-src/swoole_thread.cc @@ -31,7 +31,10 @@ BEGIN_EXTERN_C() #include "stubs/php_swoole_thread_arginfo.h" END_EXTERN_C() +zend_class_entry *swoole_thread_ce; static zend_object_handlers swoole_thread_handlers; + +zend_class_entry *swoole_thread_error_ce; static zend_object_handlers swoole_thread_error_handlers; static struct { From c0160e38d3b7c207ce3ff5df65aebe753ad1b4f8 Mon Sep 17 00:00:00 2001 From: hantianfeng Date: Wed, 3 Jul 2024 17:22:28 +0800 Subject: [PATCH 09/11] Added Map::values() --- ext-src/php_swoole_thread.h | 1 + ext-src/stubs/php_swoole_thread_map.stub.php | 1 + ext-src/stubs/php_swoole_thread_map_arginfo.h | 4 +++- ext-src/swoole_thread.cc | 15 +++++++++++++++ ext-src/swoole_thread_map.cc | 7 +++++++ tests/swoole_thread/map.phpt | 1 + 6 files changed, 28 insertions(+), 1 deletion(-) diff --git a/ext-src/php_swoole_thread.h b/ext-src/php_swoole_thread.h index bd00a424788..aee0ddd02d2 100644 --- a/ext-src/php_swoole_thread.h +++ b/ext-src/php_swoole_thread.h @@ -250,6 +250,7 @@ struct ZendArray : ThreadResource { } void keys(zval *return_value); + void values(zval *return_value); void toArray(zval *return_value); void intkey_offsetGet(zend_long index, zval *return_value) { diff --git a/ext-src/stubs/php_swoole_thread_map.stub.php b/ext-src/stubs/php_swoole_thread_map.stub.php index b4aa3f562ee..a73215d6659 100644 --- a/ext-src/stubs/php_swoole_thread_map.stub.php +++ b/ext-src/stubs/php_swoole_thread_map.stub.php @@ -8,6 +8,7 @@ public function offsetSet(mixed $key, mixed $value): void {} public function offsetUnset(mixed $key): void {} public function count(): int {} public function keys(): array {} + public function values(): array {} public function incr(mixed $key, mixed $value = 1): mixed {} public function decr(mixed $key, mixed $value = 1): mixed {} public function add(mixed $key, mixed $value): bool {} diff --git a/ext-src/stubs/php_swoole_thread_map_arginfo.h b/ext-src/stubs/php_swoole_thread_map_arginfo.h index 6a5a80050c1..dd449cd9939 100644 --- a/ext-src/stubs/php_swoole_thread_map_arginfo.h +++ b/ext-src/stubs/php_swoole_thread_map_arginfo.h @@ -1,5 +1,5 @@ /* This is a generated file, edit the .stub.php file instead. - * Stub hash: 7001a2953b9babe6ed51b8beed9e8ada7e390429 */ + * Stub hash: 40e24b68b9e9d7f7192a8f91e4b31b3020e9faca */ ZEND_BEGIN_ARG_INFO_EX(arginfo_class_Swoole_Thread_Map___construct, 0, 0, 0) ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, array, IS_ARRAY, 1, "null") @@ -28,6 +28,8 @@ ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_class_Swoole_Thread_Map_keys, 0, 0, IS_ARRAY, 0) ZEND_END_ARG_INFO() +#define arginfo_class_Swoole_Thread_Map_values arginfo_class_Swoole_Thread_Map_keys + ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_class_Swoole_Thread_Map_incr, 0, 1, IS_MIXED, 0) ZEND_ARG_TYPE_INFO(0, key, IS_MIXED, 0) ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, value, IS_MIXED, 0, "1") diff --git a/ext-src/swoole_thread.cc b/ext-src/swoole_thread.cc index 524bb479c20..656a927999d 100644 --- a/ext-src/swoole_thread.cc +++ b/ext-src/swoole_thread.cc @@ -772,6 +772,21 @@ void ZendArray::keys(zval *return_value) { lock_.unlock(); } +void ZendArray::values(zval *return_value) { + lock_.lock_rd(); + zend_ulong elem_count = zend_hash_num_elements(&ht); + array_init_size(return_value, elem_count); + void *tmp; + ZEND_HASH_FOREACH_PTR(&ht, tmp) { + zval value; + ArrayItem *item = (ArrayItem *) tmp; + item->fetch(&value); + zend_hash_next_index_insert_new(Z_ARR_P(return_value), &value); + } + ZEND_HASH_FOREACH_END(); + lock_.unlock(); +} + void ZendArray::toArray(zval *return_value) { lock_.lock_rd(); zend_ulong elem_count = zend_hash_num_elements(&ht); diff --git a/ext-src/swoole_thread_map.cc b/ext-src/swoole_thread_map.cc index 58350cc4173..28458739c50 100644 --- a/ext-src/swoole_thread_map.cc +++ b/ext-src/swoole_thread_map.cc @@ -79,6 +79,7 @@ static PHP_METHOD(swoole_thread_map, offsetSet); static PHP_METHOD(swoole_thread_map, offsetUnset); static PHP_METHOD(swoole_thread_map, count); static PHP_METHOD(swoole_thread_map, keys); +static PHP_METHOD(swoole_thread_map, values); static PHP_METHOD(swoole_thread_map, incr); static PHP_METHOD(swoole_thread_map, decr); static PHP_METHOD(swoole_thread_map, add); @@ -101,6 +102,7 @@ static const zend_function_entry swoole_thread_map_methods[] = { PHP_ME(swoole_thread_map, update, arginfo_class_Swoole_Thread_Map_update, ZEND_ACC_PUBLIC) PHP_ME(swoole_thread_map, clean, arginfo_class_Swoole_Thread_Map_clean, ZEND_ACC_PUBLIC) PHP_ME(swoole_thread_map, keys, arginfo_class_Swoole_Thread_Map_keys, ZEND_ACC_PUBLIC) + PHP_ME(swoole_thread_map, values, arginfo_class_Swoole_Thread_Map_values, ZEND_ACC_PUBLIC) PHP_ME(swoole_thread_map, toArray, arginfo_class_Swoole_Thread_Map_toArray, ZEND_ACC_PUBLIC) PHP_FE_END }; @@ -238,6 +240,11 @@ static PHP_METHOD(swoole_thread_map, keys) { mo->map->keys(return_value); } +static PHP_METHOD(swoole_thread_map, values) { + auto mo = map_fetch_object_check(ZEND_THIS); + mo->map->values(return_value); +} + static PHP_METHOD(swoole_thread_map, toArray) { auto mo = map_fetch_object_check(ZEND_THIS); mo->map->toArray(return_value); diff --git a/tests/swoole_thread/map.phpt b/tests/swoole_thread/map.phpt index 063f5210431..101bf05f8ae 100644 --- a/tests/swoole_thread/map.phpt +++ b/tests/swoole_thread/map.phpt @@ -32,5 +32,6 @@ $array2 = [ $m['map'] = $array2; Assert::eq($m['map']->toArray(), $array2); +Assert::eq($m['map']->values(), array_values($array2)); ?> --EXPECTF-- From d1f93df84d9fbfe5b55d677cd568d316258403a4 Mon Sep 17 00:00:00 2001 From: hantianfeng Date: Wed, 3 Jul 2024 18:27:50 +0800 Subject: [PATCH 10/11] Change the return value type of Thread:: getArguments() to return null in the main thread --- ext-src/stubs/php_swoole_thread.stub.php | 2 +- ext-src/stubs/php_swoole_thread_arginfo.h | 7 ++++--- ext-src/swoole_thread.cc | 6 ++++-- tests/swoole_thread/empty_args.phpt | 17 +++++++++++++++++ 4 files changed, 26 insertions(+), 6 deletions(-) create mode 100644 tests/swoole_thread/empty_args.phpt diff --git a/ext-src/stubs/php_swoole_thread.stub.php b/ext-src/stubs/php_swoole_thread.stub.php index a6617fb67b6..88df2d46c40 100644 --- a/ext-src/stubs/php_swoole_thread.stub.php +++ b/ext-src/stubs/php_swoole_thread.stub.php @@ -8,7 +8,7 @@ public function join(): bool {} public function joinable(): bool {} public function detach(): bool {} - public static function getArguments(): array {} + public static function getArguments(): ?array {} public static function getId(): int {} public static function getTsrmInfo(): array {} } diff --git a/ext-src/stubs/php_swoole_thread_arginfo.h b/ext-src/stubs/php_swoole_thread_arginfo.h index 02f0a7c4a0f..12e7e6d3262 100644 --- a/ext-src/stubs/php_swoole_thread_arginfo.h +++ b/ext-src/stubs/php_swoole_thread_arginfo.h @@ -1,5 +1,5 @@ /* This is a generated file, edit the .stub.php file instead. - * Stub hash: 234aeadaab2ab31facf1909f0e3027e433f2a88f */ + * Stub hash: 261ac9fd29d4f2f37118ff3b96428a0b2f85223a */ ZEND_BEGIN_ARG_INFO_EX(arginfo_class_Swoole_Thread___construct, 0, 0, 1) ZEND_ARG_TYPE_INFO(0, script_file, IS_STRING, 0) @@ -13,10 +13,11 @@ ZEND_END_ARG_INFO() #define arginfo_class_Swoole_Thread_detach arginfo_class_Swoole_Thread_join -ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_class_Swoole_Thread_getArguments, 0, 0, IS_ARRAY, 0) +ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_class_Swoole_Thread_getArguments, 0, 0, IS_ARRAY, 1) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_class_Swoole_Thread_getId, 0, 0, IS_LONG, 0) ZEND_END_ARG_INFO() -#define arginfo_class_Swoole_Thread_getTsrmInfo arginfo_class_Swoole_Thread_getArguments +ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_class_Swoole_Thread_getTsrmInfo, 0, 0, IS_ARRAY, 0) +ZEND_END_ARG_INFO() diff --git a/ext-src/swoole_thread.cc b/ext-src/swoole_thread.cc index 656a927999d..1cd9d51ef01 100644 --- a/ext-src/swoole_thread.cc +++ b/ext-src/swoole_thread.cc @@ -55,7 +55,7 @@ struct ThreadObject { static void php_swoole_thread_join(zend_object *object); static void php_swoole_thread_register_stdio_file_handles(bool no_close); -static thread_local zval thread_argv; +static thread_local zval thread_argv = {}; static thread_local JMP_BUF *thread_bailout = nullptr; static sw_inline ThreadObject *thread_fetch_object(zend_object *obj) { @@ -189,7 +189,9 @@ static PHP_METHOD(swoole_thread, detach) { } static PHP_METHOD(swoole_thread, getArguments) { - RETURN_ZVAL(&thread_argv, 1, 0); + if (Z_TYPE(thread_argv) == IS_ARRAY) { + RETURN_ZVAL(&thread_argv, 1, 0); + } } static PHP_METHOD(swoole_thread, getId) { diff --git a/tests/swoole_thread/empty_args.phpt b/tests/swoole_thread/empty_args.phpt new file mode 100644 index 00000000000..8733dbfc040 --- /dev/null +++ b/tests/swoole_thread/empty_args.phpt @@ -0,0 +1,17 @@ +--TEST-- +swoole_thread: info +--SKIPIF-- + +--FILE-- + +--EXPECTF-- From de7e217eced40067a4c5ab389017b0fd4263de80 Mon Sep 17 00:00:00 2001 From: hantianfeng Date: Thu, 4 Jul 2024 10:41:44 +0800 Subject: [PATCH 11/11] Fix tests --- tests/swoole_http2_client_coro/connect_twice.phpt | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/tests/swoole_http2_client_coro/connect_twice.phpt b/tests/swoole_http2_client_coro/connect_twice.phpt index 56fc140fd93..88ff09e8a2f 100644 --- a/tests/swoole_http2_client_coro/connect_twice.phpt +++ b/tests/swoole_http2_client_coro/connect_twice.phpt @@ -6,30 +6,33 @@ swoole_http2_client_coro: connect twice connect(); $req = new Request(); + $uuid = uniqid(); $req->method = 'GET'; - $req->path = '/io?io=' . str_repeat('xxx', 1000); + $req->path = '/base64/' . base64_encode($uuid); $client->send($req); $chan->push(true); $resp = $client->recv(); Assert::eq($resp->statusCode, 200); - Assert::contains($resp->data, '知乎'); + Assert::eq($resp->data, $uuid); $chan->pop(); }); go(function () use ($client, $chan) { Assert::eq($client->connect(), false); + $uuid = uniqid(); $req = new Request(); $req->method = 'GET'; - $req->path = '/io?io=xxx'; + $req->path = '/base64/' . base64_encode($uuid); $client->send($req); $chan->push(true); Assert::eq($client->recv(), false);