FraserES
FraserES

Reputation: 356

Using Threaded Object as Multidimensional Associative Array PHP Pthreads

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

Answers (1)

FraserES
FraserES

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

Related Questions