diff --git a/test_thread.php b/test_thread.php index 0ec3fd1..50dd96a 100644 --- a/test_thread.php +++ b/test_thread.php @@ -58,7 +58,6 @@ function main() $t->addr_of($i), null, function (CData $arg) { - echo '---> '; $arrPaintings = [ "The Last Supper", "Mona Lisa", "Potato Eaters", "Cypresses", "Starry Night", "Water Lilies" diff --git a/zend/StandardModule.php b/zend/StandardModule.php index b99a281..752e3c7 100644 --- a/zend/StandardModule.php +++ b/zend/StandardModule.php @@ -156,7 +156,7 @@ abstract class StandardModule extends ZendModule protected bool $restart_sapi = true; - protected bool $module_destructor_linked = false; + protected bool $destructor_linked = false; protected static $global_module; @@ -171,7 +171,7 @@ abstract class StandardModule extends ZendModule final public function destructor_set(): void { - $this->module_destructor_linked = true; + $this->destructor_linked = true; } final public function is_sapi(): bool @@ -215,7 +215,7 @@ final public function module_destructor(): void $this->global_rsrc = null; } - if (!$this->module_destructor_linked) + if (!$this->destructor_linked) static::clear_module(); } } diff --git a/zend/Threading.php b/zend/Threading.php index 2f26ac6..d723cd7 100644 --- a/zend/Threading.php +++ b/zend/Threading.php @@ -114,49 +114,18 @@ function tsrmls_deactivate(): void \tsrmls_cache_define(); } } - /* -static void php_thread_executor_globals_reinit(zend_executor_globals *dest, - zend_executor_globals *src) -{ - dest->current_module = src->current_module; -} -*/ - - /* -static void php_thread_compiler_globals_reinit(zend_compiler_globals *dest, - zend_compiler_globals *src) -{ - zend_hash_clean(dest->function_table); - zend_hash_copy(dest->function_table, src->function_table, - (copy_ctor_func_t)function_add_ref, NULL, - sizeof(zend_function)); - zend_hash_clean(dest->class_table); - zend_hash_copy(dest->class_table, src->class_table, - (copy_ctor_func_t)zend_class_add_ref, NULL, - sizeof(zend_class_entry*)); -} -*/ - function thread_startup($runtime) //: Thread + + function thread_startup(Thread $runtime): Thread { \ze_ffi()->ts_resource_ex(0, null); + \tsrmls_cache_update(); if (\IS_WINDOWS) { - \tsrmls_cache_update(); \zend_pg('com_initialized', 0); } - \zend_pg('in_error_log', 0); - - \ze_ffi()->php_output_activate(); - - \zend_pg('modules_activated', 0); - \zend_pg('header_is_being_sent', 0); - \zend_pg('connection_status', 0); - \zend_pg('in_user_include', 0); - - //\ze_ffi()->php_request_startup(); - - // \zend_sg('server_context', $runtime()->parent->server); + \zend_sg('server_context', $runtime()->parent->server); + $runtime()->child->interrupt = \ffi_ptr(\zend_eg('vm_interrupt')); \zend_pg('expose_php', 0); \zend_pg('auto_globals_jit', 1); @@ -165,63 +134,49 @@ function thread_startup($runtime) //: Thread else \zend_pg('enable_dl', 1); + \standard_activate($runtime->get_module()); + \zend_pg('during_request_startup', 0); \zend_sg('sapi_started', 0); \zend_sg('headers_sent', 1); \zend_sg('request_info')->no_headers = 1; - // \ze_ffi()->tsrm_mutex_unlock($this->module_mutex); - // return $runtime; + return $runtime; } - function thread_shutdown() + function thread_shutdown(Thread $runtime) { - /* Flush all output buffers */ - \ze_ffi()->php_output_end_all(); - - /* Shutdown output layer (send the set HTTP headers, cleanup output handlers, etc.) */ - \ze_ffi()->php_output_deactivate(); + \ze_ffi()->php_output_shutdown(); - /* SAPI related shutdown (free stuff) */ - \ze_ffi()->sapi_deactivate(); + \standard_deactivate($runtime->get_module()); - // \ze_ffi()->php_request_shutdown(null); - //\zend_sg('server_context', NULL); - - \ze_ffi()->sapi_shutdown(); \ze_ffi()->ts_free_thread(); + + \ts_ffi()->pthread_exit(\ffi_null()); } function thread_func(CData $arg) { + if (!\function_exists('zend_preloader')) + include_once 'preload.php'; + /** @var Thread|PThread */ $thread = \thread_startup(\zval_native_cast('zval*', $arg)); - do { - /* - if (!$thread instanceof PThread) { - $status = $thread->wait(); - if ($status != \ZE::SUCCESS) { - break; - } - }*/ - - while (!$thread->empty()) { + if (!$thread instanceof PThread) { + $status = $thread->wait(); + while ($status === \ZE::SUCCESS && !$thread->empty()) { $thread->execute(); } - // pthread_mutex_lock($thread->counter_mutex); - // $thread->num_threads_working--; - // if (!$thread>num_threads_working) { - // pthread_cond_signal($thread->counter_all_idle); - // } - // pthread_mutex_unlock($thread->counter_mutex); - } while (true); + } else { + $thread->execute(); + } $exception = \zend_eg('exception'); if (\is_cdata($exception)) \ze_ffi()->zend_exception_error($exception, \E_ERROR); - \thread_shutdown(); + \thread_shutdown($thread); return NULL; } diff --git a/zend/Types/PThread.php b/zend/Types/PThread.php index a79f246..45f798b 100644 --- a/zend/Types/PThread.php +++ b/zend/Types/PThread.php @@ -4,8 +4,6 @@ namespace ZE; -use FFI\CData; -use ZE\Zval; use ZE\Thread; if (\PHP_ZTS && !\class_exists('PThread')) { diff --git a/zend/Types/Thread.php b/zend/Types/Thread.php index af2825b..b3c9e4c 100644 --- a/zend/Types/Thread.php +++ b/zend/Types/Thread.php @@ -21,7 +21,12 @@ class Thread /** @var \zend_thread_t */ private ?\CStruct $thread = null; - private ?\ThreadsModule $manager = null; + private ?\ThreadsModule $module = null; + + final public function get_module(): ?\ThreadsModule + { + return $this->module; + } final public function add(callable $routine, ...$arguments) { @@ -96,12 +101,12 @@ public function __destruct() \ffi_free_if($this->server_context); $this->thread = null; - $this->manager = null; + $this->module = null; } public function __construct(\ThreadsModule $module) { - $this->manager = $module; + $this->module = $module; $this->worker_mutex = \ze_ffi()->tsrm_mutex_alloc(); $this->worker = new \SplQueue(); $this->thread = \c_typedef('zend_threads_t'); @@ -152,15 +157,73 @@ public function empty(): bool } public function join() - { + {/* + php_parallel_monitor_lock(runtime->monitor); + + if (php_parallel_monitor_check(runtime->monitor, PHP_PARALLEL_CLOSED)) { + php_parallel_exception_ex( + php_parallel_runtime_error_closed_ce, + "Runtime closed" + ); + php_parallel_monitor_unlock(runtime->monitor); + return; + } + + if (kill) { + php_parallel_monitor_set(runtime->monitor, PHP_PARALLEL_KILLED); + + zend_atomic_bool_store(runtime->child . interrupt, true); + } else { + php_parallel_monitor_set(runtime->monitor, PHP_PARALLEL_CLOSE); + } + + php_parallel_monitor_wait_locked(runtime->monitor, PHP_PARALLEL_DONE); + + php_parallel_monitor_unlock(runtime->monitor); + + php_parallel_monitor_set(runtime->monitor, PHP_PARALLEL_CLOSED); + + pthread_join(runtime->thread, NULL);*/ } public function wait() { + /*int32_t changed = FAILURE; + int rc = SUCCESS; + + if (pthread_mutex_lock(&monitor->mutex) != SUCCESS) { + return FAILURE; + } + + while (!(changed = (monitor->state & state))) { + + if ((rc = pthread_cond_wait( + &monitor->condition, &monitor->mutex)) != SUCCESS) { + pthread_mutex_unlock(&monitor->mutex); + + return FAILURE; + } + } + + monitor->state ^= changed; + + if (pthread_mutex_unlock(&monitor->mutex) != SUCCESS) { + return FAILURE; + } + + return changed;*/ } public function start() { + /*pthread_mutex_lock(&monitor->mutex); + + monitor->state |= state; + + pthread_cond_signal( + &monitor->condition); + + pthread_mutex_unlock(&monitor->mutex);*/ } } }