Brakuje mi w PHP wielowątkowości. Jakoś autorom nie jest pilno do tego a czasem by się przydało.
Z potrzeby chwili powstało coś takiego:
class Thread
{
private $token = false;
private $semaphore = false;
private $data = array();
function __construct()
{
$data = array();
$SHM_KEY = ftok(__FILE__,chr(4));
$this->semaphore = sem_get($SHM_KEY,1);
$this->token = shm_attach($SHM_KEY,1024,0666);
@shm_remove($this->token);
shm_attach($this->token);
@shm_put_var($this->token,1,$data);
}
function __call($method,$params)
{
if(substr($method,0,3) === '___')
{
$pid = pcntl_fork();
if($pid)
{
$method = substr($method,3);
@call_user_func_array(array(&$this,$method),$params);
}
}
}
function __set($key,$value)
{
if(substr($key,0,3) === '___')
{
$key = substr($key,3);
sem_acquire($this->semaphore);
$data = @shm_get_var($this->token,1);
$data[$key] = $value;
@shm_put_var($this->token,1,$data);
sem_release($this->semaphore);
}
$this->data[$key] = $value;
return $value;
}
function __get($key)
{
if(substr($key,0,3) === '___')
{
$key = substr($key,3);
$data = @shm_get_var($this->token,1);
if(isset($data[$key]))
{
$ret = $data[$key];
$this->data[$key] = $ret;
}
else
{
$ret = $this->data[$key];
}
}
else
{
$ret = $this->data[$key];
}
return $ret;
}
}
Korzysta się z tego dość prosto.
Przykład klasy wykorzystującej wątkowanie:
class Thread_Test extends Thread
{
function loop1()
{
for($this->___i1=0;true;$this->___i1++)
{
sleep(3);
}
}
function loop2()
{
for($this->i2=0;true;$this->i2++)
{
sleep(2);
}
}
function loop3()
{
for($this->i3=0;true;$this->i3++)
{
echo "loop1: {$this->___i1} loop2: {$this->___i2} loop3: {$this->___i3} loop4: {$this->___i4}\n";
sleep(1);
}
}
function loop4()
{
for($this->___i4=0;true;$this->___i4++)
{
}
}
}
i właściwe wywołanie:
$t = new Thread_Test();
$t->___loop1();
$t->___loop2();
$t->___loop4();
$t->loop3();
while(1)
{
sleep(1);
echo "MAIN {$t->___i1} \n";
}
Jak widać ;P aby wywołać metodę jako osobny wątek dodajemy przed jej nazwą trzy znaki podkreślenia, np $t->___waitLongTime(); To samo tyczy się zmiennych. Zmienne zapisane tradycyjnie ($t->zmienna) są zmiennymi lokalnymi wątku, zmienne z trzema znakami podkreślenia ($t->___zmienna) są zmiennymi współdzielonymi w klasie, dostępnymi dla wszystkich wątków.
Dostęp do zmiennych współdzielonych jest bardzo wolny. Spowodowane jest to koniecznością synchronizowania zapisów do zmiennych.