Моя проблема
Я пытаюсь разделить многомерный ассоциативный массив между различными потоками в CLI-приложении на основе pthreads. Проблема, с которой я сталкиваюсь, заключается в назначении ключей и значений без перезаписи предыдущих ключей.
Простой пример
Я создал простой пример, который, я надеюсь, отражает то, что я пытаюсь достичь в моем реальном коде.
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();
Что я хотел бы получить, так это то, что массивы foo и bar имеют по 20 ключей и значений в диапазоне от 1 до 20.
Тем не менее, фактический результат этого:
PHP Notice: Indirect modification of overloaded element of class@anonymous has no effect in /home/fraser/Code/AlignDb/src/test.php on line 50
Что несколько имеет смысл для меня, учитывая, что написано в https://github.com/krakjoe/pthreads/blob/master/examples/StackableArray.php, а именно, что «pthreads переопределяет чтение / запись измерений нашими собственными обработчиками. Наши внутренние обработчики не настроены для выполнения интерфейсов ArrayAccess».
Когда я пытаюсь использовать Threaded :: merge, он перезаписывает ключи (если для второго аргумента задано значение true) или игнорирует дубликаты, а не объединяет вложенные массивы с одинаковыми ключами вместе.
Мой вопрос
Как установить и получить ключи и значения в нескольких измерениях при расширении потока?
Я использую PHP версии 7.04 и Pthreads версии 3.1.6.
В конце концов, мы разобрались с ответом на это. (Благодаря замечанию в https://github.com/krakjoe/pthreads/blob/master/examples/StackableArray.php, где написано: «Члены массивов, которые сами являются массивом, также должны быть производными от Threaded, хотя это не является строго обязательным»). Вместо того, чтобы пытаться задавать ключи и значения с помощью оператора [], нам нужно было написать методы для создания новых экземпляров потоковых объектов, которые будут действовать как массивы, если нам нужны многомерные массивы.
Например, если вам нужен простой потокобезопасный журнал с вложенными массивами, он может выглядеть примерно так:
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() {}
}
Использование может выглядеть примерно так:
$log = new BaseLog();
$log->addBaseKey("foo");
$log->addFirstKey("bar");
$log["foo"]["bar"]["my"] = "value";
Затем он должен быть доступен для чтения и записи с использованием оператора [] точно так же, как массив, если вам не нужно добавлять дополнительный уровень вложенности (в этом случае вам потребуется добавить метод «addSecondKey»).
Других решений пока нет …