I've been playing around with the (not new) idea of introducing threads into PHP userland (maybe something to think about havin in PHP6?). What came out of it is available at [1], offering an object oriented API (in comparison to PECL/threads [2]).
Threads would quite likely come in handy in the following situations: - GTK-PHP thin network client application "polling" a socket for events (e.g., IRC client) - Multiple simultaneous connections to slow services (for instance, think of whois + check multiple domain names). Both of these examples could be realized using fork() or socket_select(), though the first is not portable and the latter produces unnecessary overhead. Maybe someone here would like to pick up on this idea or give some directions to what would have to be done to make this actually work dependably. I'm experiencing the same issues as with PECL/threads - variable "confusion" (local function arguments with same names in two threads affect each other), Engine unstability (Warning: ... in ... on line -18182899), but could get a couple of samples[3] to work quite well. Maybe the userland API could be adopted by PECL/threads? Is anyone still working at this or was development given up? 1] http://sitten-polizei.de/php/threads-0.1alpha.tar.gz 2] http://cvs.php.net/cvs.php/pear/PECL/threads 3] http://sitten-polizei.de/php/threads/tests/?file=mythread.php http://sitten-polizei.de/php/threads/tests/?file=timer.php http://sitten-polizei.de/php/threads/tests/?file=simple.php http://sitten-polizei.de/php/threads/tests/?file=calendar.php etc. - Timm
Threads for PHP ======================================================================== $Id$ 1. API: ------- The thread API for PHP was designed to assemble that of Java (see API documentation for lang.Thread). 2. Usage: --------- To create a thread, subclass the Thread class (defined in threads.c) and overwrite its run() method. Put any code to be executed into this function. 3. Basic example: ----------------- <?php class MyThread extends Thread { public function run() { print("<thread> init\n"); sleep(4); print("<thread> finished\n"); } } $m= new MyThread(); $m->start(); // Wait for thread print("<main>\n"); sleep(5); print("<main> done\n"); ?> For more examples, see the tests/ subdirectory. 3.1. Example scripts output: ---------------------------- mythread.php (the sourcecode above) | <thread> init | <main> | <thread> finished | <main> done timer.php (schedule reminder to alert in five seconds from now) | About to schedule task. | Task scheduled at 18:33:59. | 18:33:59 | 18:34:00 | 18:34:01 | 18:34:02 | 18:34:03 | Reminder: It's now 18:34:04! | 18:34:04 | Done. calendar.php (schedule three tasks to alter in 2, 5 and 8 seconds from now) | About to schedule tasks. | Tasks scheduled at 18:34:35. | 18:34:35 | 18:34:36 | Reminder: It's now 18:34:37, Buy food | 18:34:37 | 18:34:38 | 18:34:39 | Reminder: It's now 18:34:40, Cook it | 18:34:40 | 18:34:41 | 18:34:42 | Reminder: It's now 18:34:43, Meal done | 18:34:43 | 18:34:44 | Done. consumer_producer.php (demonstrate wait/notify) | >>> Producer put 0 into resource #0 | <<< Consumer got 0 from resource #0 | >>> Producer put 1 into resource #0 | <<< Consumer got 1 from resource #0 | >>> Producer put 2 into resource #0 | <<< Consumer got 2 from resource #0 | >>> Producer put 3 into resource #0 | <<< Consumer got 3 from resource #0 | >>> Producer put 4 into resource #0 | <<< Consumer got 4 from resource #0 | >>> Producer put 5 into resource #0 | <<< Consumer got 5 from resource #0 | >>> Producer put 6 into resource #0 | <<< Consumer got 6 from resource #0 | >>> Producer put 7 into resource #0 | <<< Consumer got 7 from resource #0 | >>> Producer put 8 into resource #0 | <<< Consumer got 8 from resource #0 | >>> Producer put 9 into resource #0 | <<< Consumer got 9 from resource #0 | ### Done hostcheck.php (NOT WORKING CORRECTLY, threads do not get joined) | ---> Trying test.edu:443 | ---> Trying php3.de:25 | ---> Trying blup.blop:1010 | ---> Trying localhost:80 | ---> Trying localhost:6100 | >> -ERR test.edu:443 [-1078991188]: getaddrinfo: null result pointer | >> +OK php3.de:25 | >> -ERR blup.blop:1010 [-1079200356]: getaddrinfo: null result pointer | ===> Destruct thread for blup.blop:1010 | >> +OK localhost:80 | ===> Destruct thread for localhost:80 | >> -ERR localhost:6100 [61]: Connection refused | ===> Destruct thread for localhost:6100 | DONE | ===> Destruct thread for test.edu:443 | ===> Destruct thread for php3.de:25 The ideas for the examples were taken from http://java.sun.com/docs/books/tutorial/essential/threads/index.html 4. Problems: ------------ - Mysterious things happen at the moment: E.g., global variables dissapear, fatal errors in run() lead to a failed longjmp() and therefore to "Abort trap", join() doesn't return the correct value (mostly returning NULL: I guess this has to do with the thread's EG(retval_ptr_ptr) overwriting one another(?)). - This does NOT work with ZTS, there are segfaults all over Zend Engine (2) probably due to my complete lack of knowlegde of TSRM. In php_threads_run after the first call to TSRMLS_FETCH(), all of the *_init_globals functions are called over, initializing stuff and wrecking all of the EG() stuff, leading to the beloved "Segmentation fault (core dumped)". - tests/hostcheck.php won't work for some reason still to be figured out. - Local method variables with same names get mixed up and interfere with each other. In the examples, private member variables are used to achieve a workaround - Objects are thrown away by the garbage collector since in the main thread, they're not needed. Workaround is to put these into member arrays. - Only pthread is supported (see http://cvs.php.net/co.php/pear/PECL/threads/ --> threadapi.c and TSRM/TSRM.c for how to make this work with other thread libraries). 4.1. TODO: ---------- - Figure out or have someone tell me if there is a glimpse chance of this ever working (as PECL/threads doesn't, either) or if I chose the completely wrong approach(?) 5. Conclusion: -------------- This was a first-shot kind of thing, I didn't expect it to work at all. Surprisingly, the timer examples work wonderfully, as does the simplethread demo and the Consumer/Producer thing, nevermind the necessary sleep to let the threads finish. Therefore, I'm "releasing" this. Maybe someone thinks this is cool, has far more understanding of the Engine/TSRM/Threads and C programming in general than I do and can get some ideas. 6. Build environment: --------------------- # uname -a FreeBSD friebes.net 4.7-STABLE FreeBSD 4.7-STABLE #8: Sat Oct 26 19:38:23 CEST 2002 [EMAIL PROTECTED]:/usr/obj/usr/src/sys/GENERIC i386 # ~/devel/php/php5/sapi/cli/php -v PHP 5.0.0-dev (cli) (built: Mar 5 2003 17:08:05) Copyright (c) 1997-2003 The PHP Group Zend Engine v2.0.0-dev, Copyright (c) 1998-2003 Zend Technologies # ~/devel/php/php5/sapi/cli/php -m [PHP Modules] ctype curl ftp gettext iconv imap ldap mysql openssl pcntl pcre posix session sockets standard sybase_ct sysvsem sysvshm threads tokenizer xml xslt zlib [Zend Modules] # ident /usr/include/pthread.h /usr/include/pthread.h: $FreeBSD: src/include/pthread.h,v 1.20.2.2 2001/03/04 22:38:48 alfred Exp $ 7. Configuration: ----------------- Place the files into ${php-top-srcdir}/ext/threads, run buildconf in ${php-top-srcdir}, and add --enable-threads to your configure line. After make, the following should show up in phpinfo(): # ~/devel/php/php5/sapi/cli/php -i|grep 'Threads ext' Threads extension => enabled Use #define THREADS_DEBUG 1 to control debugging (or simply start PHP with 2>/dev/null :)). <EOF>
-- PHP Development Mailing List <http://www.php.net/> To unsubscribe, visit: http://www.php.net/unsub.php