Skip to content

Commit

Permalink
staging/rework move PThread functions into classes
Browse files Browse the repository at this point in the history
  • Loading branch information
TheTechsTech committed Mar 11, 2023
1 parent 3243387 commit f84843f
Show file tree
Hide file tree
Showing 4 changed files with 126 additions and 76 deletions.
65 changes: 3 additions & 62 deletions test_thread.php
Original file line number Diff line number Diff line change
Expand Up @@ -52,34 +52,8 @@ function main()

printf("[Array Index: %d] Starting the child thread..\n", $index[$i]);

$pthread[$i] = \c_typedef('php_thread', 'ts');
$pthread[$i]()->function = function (CData $arg) {
if (!\function_exists('zend_preloader'))
include_once 'preload.php';

/** @var Thread|PThread */
$thread = \thread_startup(\zval_native_cast('zval*', $arg));

if (!$thread instanceof PThread) {
$status = $thread->wait();
while ($status === \ZE::SUCCESS && !$thread->empty()) {
$thread->execute();
}
} else {
$thread->execute();
}

$exception = \zend_eg('exception');
if (\is_cdata($exception))
\ze_ffi()->zend_exception_error($exception, \E_ERROR);

\thread_shutdown($thread);

return NULL;
};

$thread[$i] = \thread_init();
$thread[$i]->add(function (int $index) {
$pthread[$i] = \pthread_init();
$status = $pthread[$i]->create(function (int $index) {
$arrPaintings = [
"The Last Supper", "Mona Lisa", "Potato Eaters",
"Cypresses", "Starry Night", "Water Lilies"
Expand All @@ -96,39 +70,6 @@ function main()
return 0;
}, $index[$i]);

$thread[$i]->set_thread($pthread[$i]()->thread);
$pthread[$i]()->arg = \ffi_void(\zval_constructor($thread[$i])());

$status = ts_ffi()->pthread_create(
$pthread[$i]->addr('thread'),
null,
function (CData $arg) {
if (!\function_exists('zend_preloader'))
include_once 'preload.php';

/** @var Thread|PThread */
$thread = \thread_startup(\zval_native_cast('zval*', $arg));

if (!$thread instanceof PThread) {
$status = $thread->wait();
while ($status === \ZE::SUCCESS && !$thread->empty()) {
$thread->execute();
}
} else {
$thread->execute();
}

$exception = \zend_eg('exception');
if (\is_cdata($exception))
\ze_ffi()->zend_exception_error($exception, \E_ERROR);

\thread_shutdown($thread);

return NULL;
},
$pthread[$i]()->arg
);

if ($status != 0) {
fprintf(STDERR, "pthread_create() failed [status: %d]\n", $status);
return 0;
Expand All @@ -137,7 +78,7 @@ function (CData $arg) {

for ($i = 0; $i < MAX_THREADS; $i++) {
printf("[Array Index: %d] Waiting for the child thread..\n", $index[$i]);
$status = $thread[$i]->join();
$status = $pthread[$i]->join();
if ($status != 0) {
fprintf(STDERR, "pthread_join() failed [status: %d]\n", $status);
}
Expand Down
7 changes: 5 additions & 2 deletions zend/Threading.php
Original file line number Diff line number Diff line change
Expand Up @@ -53,14 +53,17 @@ function threads_activate(): \ThreadsModule
return $module;
}

function thread_init(): Thread
function thread_init(PThread $instance = null): Thread
{
$module = \threads_get_module();
if (\is_null($module)) {
$module = \threads_activate();
}

return new Thread($module);
if (\is_null($instance))
$instance = new PThread($module);

return new Thread($module, $instance);
}

function pthread_init(): PThread
Expand Down
117 changes: 114 additions & 3 deletions zend/Types/PThread.php
Original file line number Diff line number Diff line change
Expand Up @@ -13,29 +13,140 @@
final class PThread
{
/** @var \php_thread */
private ?\CStruct $thread = null;
private ?\CStruct $php_thread = null;

private ?Closure $func = null;
private ?\ThreadsModule $module = null;
private array $fcall_info = [];

public function get_module(): ?\ThreadsModule
{
return $this->module;
}

public function get_func(): ?\Closure
{
return $this->func;
}

public function get_id(): ?CData
{
return $this->__invoke()->thread;
}

public function get_ptr(): CData
{
return $this->php_thread->addr('thread');
}

public function get_args(): CData
{
return $this->php_thread->__invoke()->arg;
}

public function set_args($data = null): void
{
$this->php_thread->__invoke()->arg = \ffi_void(\zval_constructor($data)());
}

public function __invoke(): ?CData
{
return $this->thread->__invoke();
return $this->php_thread->__invoke();
}

public function __destruct()
{
$this->func = null;
$this->php_thread = null;
$this->module = null;
$this->fcall_info = [];
}

public function __construct(\ThreadsModule $module)
{
$this->module = $module;
$this->thread = \c_typedef('php_thread', 'ts');
$this->func = function (CData $arg) {
if (!\function_exists('zend_preloader'))
include_once 'preload.php';

/** @var Thread|PThread */
$thread = \thread_startup(\zval_native_cast('zval*', $arg));

if ($thread instanceof PThread) {
$thread->execute();
} else {
$status = $thread->wait();
while ($status === \ZE::SUCCESS && !$thread->empty()) {
$thread->execute();
}
}

$exception = \zend_eg('exception');
if (\is_cdata($exception))
\ze_ffi()->zend_exception_error($exception, \E_ERROR);

\thread_shutdown($thread);

return NULL;
};

$this->php_thread = \c_typedef('php_thread', 'ts');
}

public function execute()
{
/** @var \CStruct|CData|CData|\TValue */
[$thread, $fci, $fcc, $value] = $this->fcall_info;
$worker = $thread();
$ret = \zval_blank();
if (\ze_ffi()->zend_fcall_info_call($fci, $fcc, $ret(), $worker->args) === 0) {
\ze_ffi()->zend_release_fcall_info_cache($fcc);
$value->set(\zval_native($ret), $this->worker_mutex);
} else {
\ze_ffi()->zend_error(\E_WARNING, "Failed to execute routine!");
}

\ffi_free_if($fci, $fcc);
}

protected function add(callable $routine, ...$arguments)
{
$callable = \zval_constructor($routine);
if (!\is_null($arguments))
$args = \zval_constructor($arguments);
else
$args = null;

$worker = \c_typedef('zend_thread_t');
$thread = $worker();
$thread->args = $args instanceof Zval ? $args() : $args;
$thread->fci->param_count = 0;
$thread->fci->params = NULL;
$fci = \FFI::addr($thread->fci);
$fcc = \FFI::addr($thread->fcc);
if (\ze_ffi()->zend_fcall_info_init($callable(), 0, $fci, $fcc, null, null) === 0) {
$value = new \TValue;
$this->fcall_info = [$worker, $fci, $fcc, $value];
} else {
\ze_ffi()->zend_error(\E_WARNING, "Failed to add routine!");
}
}

public function create(callable $routine, ...$args)
{
$this->add($routine, ...$args);
$this->set_args($this);
return \ts_ffi()->pthread_create(
$this->get_ptr(),
null,
$this->get_func(),
$this->get_args()
);
}

public function join()
{
return \ts_ffi()->pthread_join($this->get_ptr()[0], NULL);
}
}
}
13 changes: 4 additions & 9 deletions zend/Types/Thread.php
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,7 @@ class Thread
/** @var \CStruct|CData|CData|\TValue|<> */
private ?\SplQueue $worker = null;

/** @var \pthread_t_ptr */
private ?CData $worker_id = null;
private ?PThread $pthread = null;

/** @var \MUTEX_T */
private ?CData $worker_mutex = null;
Expand All @@ -31,11 +30,6 @@ final public function get_module(): ?\ThreadsModule
return $this->module;
}

final public function set_thread(CData $tid): void
{
$this->worker_id = $tid;
}

final public function add(callable $routine, ...$arguments)
{
$callable = \zval_constructor($routine);
Expand Down Expand Up @@ -113,9 +107,10 @@ public function __destruct()
$this->module = null;
}

public function __construct(\ThreadsModule $module)
public function __construct(\ThreadsModule $module, PThread $instance)
{
$this->module = $module;
$this->pthread = $instance;
$this->worker_mutex = \ze_ffi()->tsrm_mutex_alloc();
$this->worker = new \SplQueue();
$this->thread = \c_typedef('zend_threads_t');
Expand Down Expand Up @@ -167,7 +162,7 @@ public function empty(): bool

public function join()
{
return \ts_ffi()->pthread_join($this->worker_id, NULL);/*
return \ts_ffi()->pthread_join($this->pthread->get_ptr(), NULL);/*
php_parallel_monitor_lock(runtime->monitor);
if (php_parallel_monitor_check(runtime->monitor, PHP_PARALLEL_CLOSED)) {
Expand Down

0 comments on commit f84843f

Please sign in to comment.