PHP (pseudo)Threads

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.