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--