Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit ca960cb

Browse files
author
root
committed
add isWaiting
add disable importing from ini add some statistical output in php.ini
1 parent 0267f96 commit ca960cb

6 files changed

Lines changed: 97 additions & 56 deletions

File tree

examples/AdvancedSynchronization.php

Lines changed: 14 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -14,10 +14,13 @@ public function __construct($other){
1414
public function run(){
1515
printf("%s: %lu running\n", __CLASS__, $this->getThreadId());
1616
if (($other = Thread::getThread($this->other))) {
17-
printf("%s: %lu discovering if %lu is running: %d\n", __CLASS__, $this->getThreadId(), $this->other, $other->isRunning());
18-
printf("%s: %lu discovering if %lu is joined: %d\n", __CLASS__, $this->getThreadId(), $this->other, $other->isJoined());
19-
printf("%s: %lu notifying %lu: %d\n", __CLASS__, $this->getThreadId(), $this->other, $other->notify());
20-
} else printf("%s: %lu failed to find %lu\n", __CLASS__, $this->getThreadId(), $this->other);
17+
printf("%s: %lu working ...\n", __CLASS__, $this->getThreadId());
18+
usleep(1000000); /* simulate some work */
19+
if ($other->isWaiting())
20+
printf("%s: %lu notifying %lu: %d\n", __CLASS__, $this->getThreadId(), $this->other, $other->notify());
21+
} else {
22+
printf("%s: %lu failed to find %lu\n", __CLASS__, $this->getThreadId(), $this->other);
23+
};
2124
printf("%s: %lu notified: %d\n", __CLASS__, $this->getThreadId(), $this->wait());
2225
}
2326
}
@@ -28,7 +31,12 @@ public function run(){
2831
$test2 = new ScopeTest2($test->getThreadId());
2932
$test2->start();
3033

31-
usleep(100000);
34+
printf("Process: notifying %lu: %d\n", $test2->getThreadId(), $test2->notify());
3235

33-
printf("Process: notifying %lu: %d\n", $test->getThreadId(), $test2->notify());
36+
if ($test->isWaiting()) {
37+
/*
38+
* If importing has been disabled then the responsability to notify the waiting thread must fall back to the Process to avoid deadlock
39+
*/
40+
printf("Process: notifying %lu: %d\n", $test->getThreadId(), $test->notify());
41+
} else printf("Process: nothing to do ... bye\n");
3442
?>

php_pthreads.c

Lines changed: 77 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -44,13 +44,6 @@ pthread_mutexattr_t defmutex;
4444
#endif
4545
/* }}} */
4646

47-
/* {{ userland mutex types */
48-
#ifdef PTHREAD_MUTEX_ERRORCHECK_NP
49-
# define PTHREADS_MUTEX_CHECKING 1
50-
#elifdef PTHREAD_MUTEX_ERRORCHECK
51-
# define PTHREADS_MUTEX_CHECKING 2
52-
#endif /* }}} */
53-
5447
#ifndef HAVE_PTHREADS_COMPAT_H
5548
#include "pthreads_compat.h"
5649
#endif
@@ -115,8 +108,11 @@ ZEND_END_ARG_INFO()
115108
ZEND_BEGIN_ARG_INFO_EX(Thread_isJoined, 0, 0, 0)
116109
ZEND_END_ARG_INFO()
117110

111+
ZEND_BEGIN_ARG_INFO_EX(Thread_isWaiting, 0, 0, 0)
112+
ZEND_END_ARG_INFO()
113+
118114
ZEND_BEGIN_ARG_INFO_EX(Thread_isBusy, 0, 0, 0)
119-
ZEND_END_ARG_INFO()
115+
ZEND_END_ARG_INFO()
120116
/* }}} */
121117

122118
/* {{{ statics/globals */
@@ -194,6 +190,7 @@ zend_function_entry pthreads_methods[] = {
194190
PHP_ME(Thread, isStarted, Thread_isStarted, ZEND_ACC_PUBLIC|ZEND_ACC_FINAL)
195191
PHP_ME(Thread, isRunning, Thread_isRunning, ZEND_ACC_PUBLIC|ZEND_ACC_FINAL)
196192
PHP_ME(Thread, isJoined, Thread_isJoined, ZEND_ACC_PUBLIC|ZEND_ACC_FINAL)
193+
PHP_ME(Thread, isWaiting, Thread_isWaiting, ZEND_ACC_PUBLIC|ZEND_ACC_FINAL)
197194
PHP_ME(Thread, isBusy, Thread_isBusy, ZEND_ACC_PUBLIC|ZEND_ACC_FINAL)
198195
PHP_ME(Thread, getThread, Thread_getThread, ZEND_ACC_PUBLIC|ZEND_ACC_FINAL|ZEND_ACC_STATIC)
199196
PHP_ME(Thread, getThreadId, Thread_getThreadId, ZEND_ACC_PUBLIC|ZEND_ACC_FINAL)
@@ -210,10 +207,10 @@ zend_function_entry pthreads_import_methods[] = {
210207
PHP_ME(Thread, join, Thread_join, ZEND_ACC_PUBLIC|ZEND_ACC_FINAL)
211208
PHP_ME(Thread, lock, Thread_lock, ZEND_ACC_PUBLIC|ZEND_ACC_FINAL)
212209
PHP_ME(Thread, unlock, Thread_unlock, ZEND_ACC_PUBLIC|ZEND_ACC_FINAL)
213-
/* {{{ Will this work */
214210
PHP_ME(Thread, isStarted, Thread_isStarted, ZEND_ACC_PUBLIC|ZEND_ACC_FINAL)
215211
PHP_ME(Thread, isRunning, Thread_isRunning, ZEND_ACC_PUBLIC|ZEND_ACC_FINAL)
216212
PHP_ME(Thread, isJoined, Thread_isJoined, ZEND_ACC_PUBLIC|ZEND_ACC_FINAL)
213+
PHP_ME(Thread, isWaiting, Thread_isWaiting, ZEND_ACC_PUBLIC|ZEND_ACC_FINAL)
217214
PHP_ME(Thread, isBusy, Thread_isBusy, ZEND_ACC_PUBLIC|ZEND_ACC_FINAL)
218215
/* }}} */
219216
{NULL, NULL, NULL}
@@ -250,16 +247,17 @@ zend_module_entry pthreads_module_entry = {
250247
PHP_MSHUTDOWN(pthreads),
251248
NULL,
252249
NULL,
253-
NULL,
250+
PHP_MINFO(pthreads),
254251
PHP_PTHREADS_VERSION,
255252
STANDARD_MODULE_PROPERTIES
256253
}; /* }}} */
257254

258255
/* {{{ INI Entries */
259256
PHP_INI_BEGIN()
260-
/*{{{ pthreads.max allows admins some control over how many threads a user can create */
261-
PHP_INI_ENTRY("pthreads.max", "0", PHP_INI_SYSTEM, NULL)
262-
/* }}} */
257+
/* {{{ pthreads.max allows admins some control over how many threads a user can create */
258+
PHP_INI_ENTRY("pthreads.max", "0", PHP_INI_SYSTEM, NULL) /* }}} */
259+
/* {{{ pthreads.importing allows importing threads to be disabled where it poses a security risk */
260+
PHP_INI_ENTRY("pthreads.importing", "1", PHP_INI_SYSTEM, NULL) /* }}} */
263261
PHP_INI_END()
264262
/* }}} */
265263

@@ -274,24 +272,22 @@ PHP_MINIT_FUNCTION(pthreads)
274272
zend_class_entry ie;
275273
zend_class_entry me;
276274
zend_class_entry ce;
277-
278-
REGISTER_LONG_CONSTANT("PTHREADS_FAIL", 0, CONST_CS | CONST_PERSISTENT);
279-
REGISTER_LONG_CONSTANT("PTHREADS_ST_STARTED", PTHREADS_ST_STARTED, CONST_CS | CONST_PERSISTENT);
280-
REGISTER_LONG_CONSTANT("PTHREADS_ST_RUNNING", PTHREADS_ST_RUNNING, CONST_CS | CONST_PERSISTENT);
281-
REGISTER_LONG_CONSTANT("PTHREADS_ST_JOINED", PTHREADS_ST_JOINED, CONST_CS | CONST_PERSISTENT);
282-
REGISTER_LONG_CONSTANT("PTHREADS_ST_WAITING", PTHREADS_ST_WAITING, CONST_CS | CONST_PERSISTENT);
283-
275+
276+
REGISTER_INI_ENTRIES();
277+
284278
INIT_CLASS_ENTRY(te, "Thread", pthreads_methods);
285279
te.create_object = pthreads_attach_to_instance;
286280
te.serialize = zend_class_serialize_deny;
287281
te.unserialize = zend_class_unserialize_deny;
288282
pthreads_class_entry=zend_register_internal_class(&te TSRMLS_CC);
289283

290-
INIT_CLASS_ENTRY(ie, "ImportedThread", pthreads_import_methods);
291-
ie.create_object = pthreads_attach_to_import;
292-
ie.serialize = zend_class_serialize_deny;
293-
ie.unserialize = zend_class_unserialize_deny;
294-
pthreads_import_entry=zend_register_internal_class(&ie TSRMLS_CC);
284+
if (INI_INT("pthreads.importing")) {
285+
INIT_CLASS_ENTRY(ie, "ImportedThread", pthreads_import_methods);
286+
ie.create_object = pthreads_attach_to_import;
287+
ie.serialize = zend_class_serialize_deny;
288+
ie.unserialize = zend_class_unserialize_deny;
289+
pthreads_import_entry=zend_register_internal_class(&ie TSRMLS_CC);
290+
}
295291

296292
INIT_CLASS_ENTRY(me, "Mutex", pthreads_mutex_methods);
297293
me.serialize = zend_class_serialize_deny;
@@ -312,8 +308,6 @@ PHP_MINIT_FUNCTION(pthreads)
312308
#endif
313309
}
314310

315-
REGISTER_INI_ENTRIES();
316-
317311
if (!PTHREADS_G(init))
318312
PTHREADS_G_INIT();
319313

@@ -332,11 +326,31 @@ PHP_MSHUTDOWN_FUNCTION(pthreads)
332326
return SUCCESS;
333327
} /* }}} */
334328

329+
/* {{{ minfo */
330+
PHP_MINFO_FUNCTION(pthreads)
331+
{
332+
char numbers[10];
333+
334+
php_info_print_table_start();
335+
php_info_print_table_row(2, "Version", PHP_PTHREADS_VERSION);
336+
if (INI_INT("pthreads.max")) {
337+
php_info_print_table_row(2, "Maximum Threads", INI_STR("pthreads.max"));
338+
} else php_info_print_table_row(2, "Maximum Threads", "No Limits");
339+
340+
snprintf(numbers, sizeof(numbers), "%d", PTHREADS_G_COUNT());
341+
php_info_print_table_row(2, "Current Threads", numbers);
342+
343+
snprintf(numbers, sizeof(numbers), "%d", PTHREADS_G_PEAK());
344+
php_info_print_table_row(2, "Peak Threads", numbers);
345+
346+
php_info_print_table_end();
347+
} /* }}} */
348+
335349
/* {{{ Thread methods */
336350

337351
/* {{{ proto boolean Thread::start([boolean sync])
338352
Starts executing your implemented run method in a thread, will return a boolean indication of success
339-
If sync is true, your new thread runs synchronized with the current thread until you call notify from within the new thread or the thread ends
353+
If sync is true, your new thread runs synchronized with the current thread ( causing the current thread to block ) until you call notify from within the new thread or the thread ends
340354
If sync is false or void, the new thread will run asynchronously to the current thread and this call will return as quickly as possible */
341355
PHP_METHOD(Thread, start)
342356
{
@@ -500,6 +514,25 @@ PHP_METHOD(Thread, isBusy)
500514
}
501515
} /* }}} */
502516

517+
/* {{{ proto boolean Thread::isWaiting()
518+
Will return true if the referenced thread is waiting for notification */
519+
PHP_METHOD(Thread, isWaiting)
520+
{
521+
PTHREAD thread = PTHREADS_FETCH;
522+
523+
if (thread) {
524+
if (PTHREADS_IS_IMPORT(thread)){
525+
PTHREADS_LOCK(thread->sig);
526+
ZVAL_BOOL(return_value, PTHREADS_IN_STATE(thread->sig, PTHREADS_ST_WAITING));
527+
PTHREADS_UNLOCK(thread->sig);
528+
} else if (!PTHREADS_IS_SELF(thread)){
529+
PTHREADS_LOCK(thread);
530+
ZVAL_BOOL(return_value, PTHREADS_IN_STATE(thread, PTHREADS_ST_WAITING));
531+
PTHREADS_UNLOCK(thread);
532+
} else zend_error(E_WARNING, "pthreads has detected an attempt to use Thread::isWaiting from a Thread");
533+
}
534+
}
535+
503536
/* {{{ proto boolean Thread::wait([long timeout])
504537
Will cause the calling process or thread to wait for the referenced thread to notify
505538
When a timeout is used an reached boolean false will return
@@ -637,20 +670,22 @@ PHP_METHOD(Thread, getThread)
637670
PTHREAD found = NULL;
638671
unsigned long tid = 0L;
639672

640-
if (EG(called_scope) == pthreads_class_entry) {
641-
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l", &tid)==SUCCESS) {
642-
if (tid && tid >0L) {
643-
if ((found=PTHREADS_FIND((unsigned long)tid))!=NULL) {
644-
if (!PTHREADS_IS_CREATOR(found)) {
645-
if (PTHREADS_IMPORT(found, &return_value TSRMLS_CC)) {
646-
return;
647-
} else zend_error(E_WARNING, "pthreads has detected that Thread::getThread(%lu) has failed", tid);
648-
} else zend_error(E_WARNING, "pthreads has detected that Thread::getThread(%lu) has nothing to import as the requested thread was created in the current", tid);
649-
RETURN_FALSE;
650-
} else zend_error(E_WARNING, "pthreads has detected that Thread::getThread(%lu) has nothing to import as the requested thread is no longer running", tid);
651-
} else zend_error(E_WARNING, "pthreads has detected incorrect use of Thread::getThread, no valid Thread identifier was specified");
652-
}
653-
} else zend_error(E_WARNING, "pthreads has detected incorrect use of Thread::getThread, this method may only be called statically as Thread::getThread");
673+
if (pthreads_import_entry != NULL) {
674+
if (EG(called_scope) == pthreads_class_entry) {
675+
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l", &tid)==SUCCESS) {
676+
if (tid && tid >0L) {
677+
if ((found=PTHREADS_FIND((unsigned long)tid))!=NULL) {
678+
if (!PTHREADS_IS_CREATOR(found)) {
679+
if (PTHREADS_IMPORT(found, &return_value TSRMLS_CC)) {
680+
return;
681+
} else zend_error(E_WARNING, "pthreads has detected that Thread::getThread(%lu) has failed", tid);
682+
} else zend_error(E_WARNING, "pthreads has detected that Thread::getThread(%lu) has nothing to import as the requested thread was created in the current", tid);
683+
RETURN_FALSE;
684+
} else zend_error(E_WARNING, "pthreads has detected that Thread::getThread(%lu) has nothing to import as the requested thread is no longer running", tid);
685+
} else zend_error(E_WARNING, "pthreads has detected incorrect use of Thread::getThread, no valid Thread identifier was specified");
686+
}
687+
} else zend_error(E_WARNING, "pthreads has detected incorrect use of Thread::getThread, this method may only be called statically as Thread::getThread");
688+
} else zend_error(E_WARNING, "pthreads has detected an attempt to use a prohibited method (Thread::getThread), importing Threads is disabled in this environment");
654689
RETURN_NULL();
655690
}
656691
/* }}} */

php_pthreads.h

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@
1818
#ifndef HAVE_PHP_PTHREADS_H
1919
#define HAVE_PHP_PTHREADS_H
2020
#define PHP_PTHREADS_EXTNAME "pthreads"
21-
#define PHP_PTHREADS_VERSION "0.30"
21+
#define PHP_PTHREADS_VERSION "0.31"
2222

2323
#include <stdio.h>
2424
#include <pthread.h>
@@ -54,6 +54,7 @@
5454

5555
PHP_MINIT_FUNCTION(pthreads);
5656
PHP_MSHUTDOWN_FUNCTION(pthreads);
57+
PHP_MINFO_FUNCTION(pthreads);
5758

5859
/* {{{ basic */
5960
PHP_METHOD(Thread, start);
@@ -71,6 +72,7 @@ PHP_METHOD(Thread, unlock);
7172
PHP_METHOD(Thread, isStarted);
7273
PHP_METHOD(Thread, isRunning);
7374
PHP_METHOD(Thread, isJoined);
75+
PHP_METHOD(Thread, isWaiting);
7476
PHP_METHOD(Thread, isBusy);
7577
/* }}} */
7678

pthreads_globals.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,8 @@
2525
* 3. providing peak usage and current realtime statistics can help you to design and execute more efficiently
2626
* 4. these globals are completely safe; they are protected by mutex
2727
* 5. in some SAPI environments it may not make sense to use pthreads.max ini setting, that is for the server administrator to decide
28+
* 6. in some SAPI environments it may make sense to disable importing Threads for security reasons, pthreads.importing should be set to 0
29+
* 7. pthreads.* ini settings are system only for security
2830
*
2931
* TODO
3032
* 1. look into the possibility of providing persistent threads that survive across SAPI requests

pthreads_object.h

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -22,12 +22,6 @@
2222
* NOTES
2323
* 1. Not happy with inability to detect scope properly in Threads, too many annoyances to be acceptable
2424
* 2. Private/Protected Members in user declared Threads not working properly as a result of the above
25-
*
26-
* TODO
27-
* 1. Importer Functionality
28-
* 2. Attempt to import the definition, perhaps internalize the class in the creating thread so that $this in the threading context can initialize in a more compatible manor, this should fix scoping issues by proxy
29-
* 3. Test thoroughly synchronization routines, ensure that imported threads will function, ensure bits aren't set when they shouldn't be on state
30-
* 4. User defined functions should be imported with imports, concurrency poses a problem, it could be left up to the user to use mutex and locking ... keep thinking ...
3125
*/
3226

3327
#ifdef HAVE_CONFIG_H

tests/wait.phpt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,4 +15,4 @@ if($thread->start(true)) {
1515
}
1616
?>
1717
--EXPECT--
18-
int(1)
18+
bool(true)

0 commit comments

Comments
 (0)