superuser
2012-01-29 13:00:45
Hello,
I case anybody ever wondered, it's possible to launch threads in PHP. However, currently it's possible only on *nix environments, due to the fact that libpcntl is not supported in Windows.
Here's the class:
[php]<?php
/** A class to spawn a thread. Only works in *nix environments, as Windows platform is missing libpcntl.
* Forks the process.
*
* @author Superuser
* @version $Id: Thread.class.php 23 2012-01-23 09:40:32Z superuser $
*/
class Thread
{
public function __construct($callback = null)
{
if (!function_exists('pcntl_fork'))
throw new Exception('PHP is compiled without –enable-pcntl');
if ($callback != null)
$this->SetCallback($callback);
}
public function IsAlive()
{
return (pcntl_waitpid($this->_pid, $status, WNOHANG) === 0);
}
public function SetCallback($callback)
{
if (function_exists($callback) && is_callable($callback))
$this->_callback = $callback;
else
throw new Exception("$callback is not valid function");
}
public function Start()
{
if (($this->_pid = pcntl_fork()) == -1)
throw new Exception('Couldn\'t fork the process');
if (!$this->_pid) {
// Child.
pcntl_signal(SIGTERM, array($this, 'SignalHandler'));
$args = func_get_args();
!empty($args) ? call_user_func_array($this->_callback, $args) : call_user_func($this->_callback);
exit(0);
}
// Parent.
}
public function Stop($signal = SIGKILL, $wait = false)
{
if ($this->IsAlive()) {
posix_kill($this->_pid, $signal);
if ($wait)
pcntl_waitpid($this->_pid, $status);
}
}
private function SignalHandler($signal)
{
switch ($signal) {
case SIGTERM:
exit(0);
}
}
private $_callback, $_pid;
}[/php]
The class works like this:
[php]<?php
require_once('Thread.class.php');
function Foo($t)
{
for ($i = 0; $i < 10; $i++) {
echo "Hello from thread #{$t + 1}. i=$i" . PHP_EOL;
sleep(1);
}
}
try {
$t = array();
for ($i = 0; $i < 10; $i++) {
$thr = new Thread('Foo');
$thr->Start($i);
$t[] = $thr;
}
$done = false;
while (!$done) {
sleep(1);
$done = true;
foreach ($t as $thread)
if ($thread->IsAlive()) {
$done = false;
break;
}
}
} catch (Exception $e) {
echo 'Exception: ' . $e . PHP_EOL;
}
[/php]
Enjoy!
I case anybody ever wondered, it's possible to launch threads in PHP. However, currently it's possible only on *nix environments, due to the fact that libpcntl is not supported in Windows.
Here's the class:
[php]<?php
/** A class to spawn a thread. Only works in *nix environments, as Windows platform is missing libpcntl.
* Forks the process.
*
* @author Superuser
* @version $Id: Thread.class.php 23 2012-01-23 09:40:32Z superuser $
*/
class Thread
{
public function __construct($callback = null)
{
if (!function_exists('pcntl_fork'))
throw new Exception('PHP is compiled without –enable-pcntl');
if ($callback != null)
$this->SetCallback($callback);
}
public function IsAlive()
{
return (pcntl_waitpid($this->_pid, $status, WNOHANG) === 0);
}
public function SetCallback($callback)
{
if (function_exists($callback) && is_callable($callback))
$this->_callback = $callback;
else
throw new Exception("$callback is not valid function");
}
public function Start()
{
if (($this->_pid = pcntl_fork()) == -1)
throw new Exception('Couldn\'t fork the process');
if (!$this->_pid) {
// Child.
pcntl_signal(SIGTERM, array($this, 'SignalHandler'));
$args = func_get_args();
!empty($args) ? call_user_func_array($this->_callback, $args) : call_user_func($this->_callback);
exit(0);
}
// Parent.
}
public function Stop($signal = SIGKILL, $wait = false)
{
if ($this->IsAlive()) {
posix_kill($this->_pid, $signal);
if ($wait)
pcntl_waitpid($this->_pid, $status);
}
}
private function SignalHandler($signal)
{
switch ($signal) {
case SIGTERM:
exit(0);
}
}
private $_callback, $_pid;
}[/php]
The class works like this:
[php]<?php
require_once('Thread.class.php');
function Foo($t)
{
for ($i = 0; $i < 10; $i++) {
echo "Hello from thread #{$t + 1}. i=$i" . PHP_EOL;
sleep(1);
}
}
try {
$t = array();
for ($i = 0; $i < 10; $i++) {
$thr = new Thread('Foo');
$thr->Start($i);
$t[] = $thr;
}
$done = false;
while (!$done) {
sleep(1);
$done = true;
foreach ($t as $thread)
if ($thread->IsAlive()) {
$done = false;
break;
}
}
} catch (Exception $e) {
echo 'Exception: ' . $e . PHP_EOL;
}
[/php]
Enjoy!