Skip to content

Commit

Permalink
fix, optimize code, refactor arraylist/map ctor: Allow array as ctor …
Browse files Browse the repository at this point in the history
…method parameter
  • Loading branch information
matyhtf committed Jul 1, 2024
1 parent a61d959 commit ab91af6
Show file tree
Hide file tree
Showing 11 changed files with 130 additions and 51 deletions.
1 change: 0 additions & 1 deletion ext-src/php_swoole_thread.h
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down
2 changes: 1 addition & 1 deletion ext-src/stubs/php_swoole_thread_arraylist.stub.php
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
<?php
namespace Swoole\Thread {
class ArrayList implements ArrayAccess, Countable {
public function __construct() {}
public function __construct(?array $array = null) {}
public function offsetGet(mixed $key): mixed {}
public function offsetExists(mixed $key): bool {}
public function offsetSet(mixed $key, mixed $value): void {}
Expand Down
3 changes: 2 additions & 1 deletion ext-src/stubs/php_swoole_thread_arraylist_arginfo.h
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
/* This is a generated file, edit the .stub.php file instead.
* Stub hash: 180fa4468e220b852fabc5320f2a463a219f7aa3 */
* Stub hash: 70c2427e37953ac2ceefe4c972cbd8b9845b43ab */

ZEND_BEGIN_ARG_INFO_EX(arginfo_class_Swoole_Thread_ArrayList___construct, 0, 0, 0)
ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, array, IS_ARRAY, 1, "null")
ZEND_END_ARG_INFO()

ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_class_Swoole_Thread_ArrayList_offsetGet, 0, 1, IS_MIXED, 0)
Expand Down
2 changes: 1 addition & 1 deletion ext-src/stubs/php_swoole_thread_map.stub.php
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
<?php
namespace Swoole\Thread {
class Map implements ArrayAccess, Countable {
public function __construct() {}
public function __construct(?array $array = null) {}
public function offsetGet(mixed $key): mixed {}
public function offsetExists(mixed $key): bool {}
public function offsetSet(mixed $key, mixed $value): void {}
Expand Down
3 changes: 2 additions & 1 deletion ext-src/stubs/php_swoole_thread_map_arginfo.h
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
/* This is a generated file, edit the .stub.php file instead.
* Stub hash: e85b15919120073579b1d561326eb1c3e446860a */
* Stub hash: 7001a2953b9babe6ed51b8beed9e8ada7e390429 */

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")
ZEND_END_ARG_INFO()

ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_class_Swoole_Thread_Map_offsetGet, 0, 1, IS_MIXED, 0)
Expand Down
8 changes: 7 additions & 1 deletion ext-src/swoole_server.cc
Original file line number Diff line number Diff line change
Expand Up @@ -2651,13 +2651,16 @@ static PHP_METHOD(swoole_server, start) {
if (!ZVAL_IS_NULL(&server_object->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);
};
}
Expand All @@ -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;
Expand Down
53 changes: 11 additions & 42 deletions ext-src/swoole_thread.cc
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -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);
Expand All @@ -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;
Expand Down Expand Up @@ -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) {
Expand All @@ -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) {
Expand All @@ -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;
}
Expand All @@ -182,15 +166,15 @@ 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;
}
RETURN_BOOL(to->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;
}
Expand All @@ -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};
Expand Down Expand Up @@ -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);
Expand Down Expand Up @@ -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 {
Expand Down
17 changes: 15 additions & 2 deletions ext-src/swoole_thread_arraylist.cc
Original file line number Diff line number Diff line change
Expand Up @@ -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) {
Expand Down
13 changes: 12 additions & 1 deletion ext-src/swoole_thread_map.cc
Original file line number Diff line number Diff line change
Expand Up @@ -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, ...) \
Expand Down
43 changes: 43 additions & 0 deletions tests/swoole_thread/arraylist.phpt
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
--TEST--
swoole_thread: arraylist
--SKIPIF--
<?php
require __DIR__ . '/../include/skipif.inc';
skip_if_nts();
?>
--FILE--
<?php
require __DIR__ . '/../include/bootstrap.php';

use Swoole\Thread\ArrayList;

$array = [
random_int(1, 999999999999999999),
random_bytes(128),
uniqid(),
time(),
];

$l = new ArrayList($array);
Assert::eq($l->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--
36 changes: 36 additions & 0 deletions tests/swoole_thread/map.phpt
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
--TEST--
swoole_thread: map
--SKIPIF--
<?php
require __DIR__ . '/../include/skipif.inc';
skip_if_nts();
?>
--FILE--
<?php
require __DIR__ . '/../include/bootstrap.php';

use Swoole\Thread\Map;

$array = [
'a' => 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--

0 comments on commit ab91af6

Please sign in to comment.