I took the most basic demo of pthreads PHP7 extension that uses Pool
class (this demo https://github.com/krakjoe/pthreads#polyfill) and extended it a little so I can grab results from the thread (or at least I think I can):
$pool = new Pool(4);
foreach (range(1, 8) as $i) {
$pool->submit(new class($i) extends Threaded
{
public $i;
private $garbage = false;
public function __construct($i)
{
$this->i = $i;
}
public function run()
{
echo "Hello World\n";
$this->result = $this->i * 2;
$this->garbage = true;
}
public function isGarbage() : bool
{
return $this->garbage;
}
});
}
while ($pool->collect(function(Collectable $task) {
if ($task->isGarbage()) {
echo $task->i . ' ' . $task->result . "\n";
}
return $task->isGarbage();
})) continue;
$pool->shutdown();
What's confusing me is that it sometimes doesn't get the result for all tasks:
Hello World
Hello World
Hello World
Hello World
Hello World
1 2
2 4
Hello World
Hello World
3 6
Hello World
7 14
4 8
8 16
Now two lines with 5 10
and 6 12
are missing but I don't understand why. This happens only sometimes (maybe 1/10 runs).
It looks like the original demo is for the older version of pthreads
because there's Collectable
interface which is now automatically implemented by Threaded
if I'm not mistaken.
Then the readme says:
The Pool::collect mechanism was moved from Pool to Worker for a more robust Worker and simpler Pool inheritance.
So I guess I'm doing something wrong.
Edit: I took the example from How does Pool::collect works? and updated it to work with latest pthreads and current PHP7 but the result is the same. It looks like it's not able to collect results from the last threads that are executed.
$pool = new Pool(4);
while (@$i++<10) {
$pool->submit(new class($i) extends Thread implements Collectable {
public $id;
private $garbage;
public function __construct($id) {
$this->id = $id;
}
public function run() {
sleep(1);
printf(
"Hello World from %d\n", $this->id);
$this->setGarbage();
}
public function setGarbage() {
$this->garbage = true;
}
public function isGarbage(): bool {
return $this->garbage;
}
});
}
while ($pool->collect(function(Collectable $work){
printf(
"Collecting %d\n", $work->id);
return $work->isGarbage();
})) continue;
$pool->shutdown();
This outputs the following which is clearly not collecting all threads:
Hello World from 1
Collecting 1
Hello World from 2
Collecting 2
Hello World from 3
Collecting 3
Hello World from 4
Collecting 4
Hello World from 5
Collecting 5
Hello World from 6
Hello World from 7
Collecting 6
Collecting 7
Hello World from 8
Hello World from 9
Hello World from 10