Since GetInfo
does not descend from pthreads
(it is not Threaded
):
$this->get_info_object = $obj;
This results in a serial representation of $obj
being stored as a member of the Thread
. This results in the members of GetInfo
being serialized and will have unexpected results.
The solution is to replace your usage of arrays with suitable objects, the following code is for PHP 7 (pthreads v3+):
<?php
class GetHostByNameCache extends Threaded {
public function lookup(string $host) : string {
return $this->synchronized(function() use($host) {
if (isset($this->cache[$host])) {
return $this->cache[$host];
}
return $this->cache[$host] = gethostbyname($host);
});
}
private $cache = [];
}
class Test extends Thread {
public function __construct(GetHostByNameCache $cache, string $host) {
$this->cache = $cache;
$this->host = $host;
}
public function run() {
var_dump(
$this->cache->lookup($this->host));
}
private $cache;
}
$tests = [];
$cache = new GetHostByNameCache();
$domains = [
"google.co.uk",
"google.com",
"google.co.jp",
"google.co.in",
"google.co.ca",
"google.net"
];
for ($test = 0; $test < count($domains); $test++) {
$tests[$test] = new Test($cache, $domains[$test]);
$tests[$test]->start();
}
foreach ($tests as $test)
$test->join();
var_dump($cache);
?>
This will yield something like:
string(14) "216.58.198.195"
string(14) "216.58.198.206"
string(14) "216.58.198.195"
string(14) "216.58.198.195"
string(12) "66.196.36.16"
string(14) "216.58.198.196"
object(GetHostByNameCache)#1 (1) {
["cache"]=>
object(Volatile)#2 (6) {
["google.co.uk"]=>
string(14) "216.58.198.195"
["google.com"]=>
string(14) "216.58.198.206"
["google.co.jp"]=>
string(14) "216.58.198.195"
["google.co.in"]=>
string(14) "216.58.198.195"
["google.co.ca"]=>
string(12) "66.196.36.16"
["google.net"]=>
string(14) "216.58.198.196"
}
}
The important things to notice are:
- The cache object is
Threaded
.
- The array that appears to be used in the cache is cast to
Volatile
.
- The
lookup
routine logic is synchronized.
Because lookup
is synchronized, not more than one thread can perform a lookup at a time, this ensures no two threads can perform the same lookup twice. You might be able to come up with a more efficient way of synchronizing access to the cache (on a per record basis), but this is a good starting place.