Reputation: 356
My Problem
I am trying to share a multi-dimensional associative array between different threads in a pthreads - based CLI application. The problem I am encountering is with assigning keys and values without overwriting previous keys.
Simple Example
I've created a simple example which I hope reflects what I am trying to achieve in my real code.
class MyWork extends Worker {
public function __construct($log) {
$this->log = $log;
}
public function getLog() {
return $this->log->getLog();
}
public function run() {}
}
class Log extends Threaded {
private $log;
public function __construct() {
$this->log = new class extends Threaded {
public function run() {}
};
}
public function run(){}
public function report() {
print_r($this->log['foo'].PHP_EOL);
print_r($this->log['bar'].PHP_EOL);
}
public function getLog() { return $this->log; }
}
class MyTask extends Threaded {
private $complete=false;
private $i;
public function isComplete() {
return $this->complete;
}
public function run() {
$this->worker->getLog()['bar'][$this->i] = $this->i;
$this->worker->getLog()['foo'][$this->i] = $this->i;
$this->complete= true;
}
public function __construct($i) {
$this->i = $i;
}
}
$log = new Log();
$p = new Pool(4, MyWork::class, [$log]);
foreach(range(0, 20) as $i)
$p->submit(new MyTask($i));
$log->report();
What I'd like the output of this to be is that the foo and bar arrays both have 20 keys and values ranging from 1 to 20.
However, the actual output of this is:
PHP Notice: Indirect modification of overloaded element of class@anonymous has no effect in /home/fraser/Code/AlignDb/src/test.php on line 50
Which somewhat makes sense to me given what's written in https://github.com/krakjoe/pthreads/blob/master/examples/StackableArray.php, namely that "pthreads overrides the dimension read/writers with our own handlers. Our internal handlers are not setup to execute ArrayAccess interfaces."
When I try to use Threaded::merge it overwrites the keys (if the second argument is set to true) or ignores duplicates rather than concatenating nested arrays with the same keys together.
My Question
How do I set and get keys and values in multiple dimensions when extending Threaded?
I'm using PHP version 7.04 and Pthreads version 3.1.6.
Upvotes: 1
Views: 269
Reputation: 356
Eventually, we figured out the answer to this. (Thanks to a remark in https://github.com/krakjoe/pthreads/blob/master/examples/StackableArray.php, where it says "Members of arrays that are themselves an array should also be a derivative of Threaded, though it's not strictly necessary"). Instead of trying to set keys and values with the [] operator we needed to write methods to create new instances of threaded objects to act as arrays if we needed multidimensional arrays.
For example, if you needed a simple threadsafe log with nested arrays it might look something like this:
class BaseLog extends Threaded {
public function run() {}
public function addBaseKey($key) {
$this[$key] = new SafeArray();
}
public function addFirstKey($base, $key) {
$this[$base][$key] = new SafeArray();
}
}
class SafeArray extends Threaded {
public function run() {}
}
Usage might look something like this:
$log = new BaseLog();
$log->addBaseKey("foo");
$log->addFirstKey("bar");
$log["foo"]["bar"]["my"] = "value";
This should then be readable and writeable using the [] operator exactly like an array as long as you don't need to add a further level of nesting (in which case you'd need to add an "addSecondKey" method).
Upvotes: 1