Autor | Zpráva | ||
---|---|---|---|
David Klouček Profil |
Třída Program využívá Model, který potřebuje připojení k databázi. Teď potřebuju Program spustit ve více vláknech najednou. Zkouším to pomocí rozšíření pthreads. Když spustím následující kód:
<?php $connection = new PDO('mysql:host=localhost;dbname=x', 'y', 'z'); class Model { public $connection; public function setConnection(PDO $connection) { $this->connection = $connection; //echo get_class($this->connection)." | setConnection<br />\n"; //zde ještě vrátí PDO } } class Program { public $model; public function setModel(Model $model) { $this->model = $model; } public function run() { echo get_class($this->model->connection)." | run<br />\n"; } } class ProgramThread extends Thread { public $i; public $program; public function __construct($i, Program $program, PDO $connection) { $this->i = $i; $this->program = $program; $this->program->model->setConnection($connection); echo get_class($this->program->model->connection)." | __construct<br />\n"; } public function run() { $this->program->run(); } } $program = new Program(); $model = new Model;//nemůžu předat připojení už teď do modelu, hlásilo by to nelze serializovat PDO $program->setModel($model); /* 1. varianta $pt = new ProgramThread(1, clone $program, clone $connection); $pt->run(); exit; */ //2. varianta $threads = []; foreach (range(1, 1) as $i) { $threads[$i] = new ProgramThread($i, clone $program, clone $connection); $threads[$i]->start(); } Dostanu: Program | run ProgramThread | __construct Což je špatně, někam se vytrácí připojení předané modelu a nevím proč. Když odkomentuju variantu 1 a odmažu extends Thread, dostanu správný výsledek: PDO | __construct PDO | run Co to může způsobovat? |
||
David Klouček Profil |
Jednodušší příklad se skoro stejnym výstupem:
<?php class Program { public $connection; public function run() { echo get_class($this->connection)." | run<br />\n"; } } class Connection { //neserializovatelná třída } class ProgramThread extends Thread { //zkuste odmazat "extends Thread" a bude to fungovat dobře public $program; public function __construct(Program $program, Connection $connection) { $this->program = $program; //$connection je v pořádku, ale do $this->program->connection se nechce zapsat $this->program->connection = $connection; // $this->program->connection je i po tomhle NULL echo get_class($this->program->connection)." | __construct<br />\n"; } public function run() { $this->program->run(); } } $connection = new Connection(); $program = new Program; $pt = new ProgramThread(clone $program, clone $connection); $pt->run(); |
||
Alphard Profil |
Zkušenosti s tím bohužel nemám, ale po rychlém projití kódu mi to celé připadá jako snaha dostat do té knihovny něco, s čím nedokáže pracovat. To, že nejde connection předat přímo není bug, ale vlastnost. I když to interně neznám, ani se moc nedivím, že ten workaround selhává.
Viděl jste příklad na SQL worker? https://github.com/krakjoe/pthreads/blob/master/examples/SQLWorker.php hodně dotazů spojených s pthreads a databází vede sem. Tady se teda připojení k db stále opakuje, což doporučuje i dokumentace... Static Members: (...) For example, upon starting the context, a class whose static members include connection information for a database server, and the connection itself, will only have the simple connection information copied, not the connection. Allowing the new context to initiate a connection in the same way as the context that created it, storing the connection in the same place without affecting the original context. (Zdroj http://php.net/manual/en/intro.pthreads.php) Ovšem mysql extenzi má ještě další specifikat, a práce s MySQLi nebo PDO se řeší jinak. Konkrétně s PDO je myslím docela relevantní příspěvek https://github.com/krakjoe/pthreads/issues/120#issuecomment-18869391 (což přesně odpovídá popisu v manuálu). Ukládání connection staticky je trochu dál posunuto u příkladu s MySQLi https://github.com/krakjoe/pthreads/blob/seven/examples/MySQLi.php. Tam je teda i pool, snad to půjde dát dohromady i s PDO. pthreads tady momentálně nemám, takže to nemohu zkusit, ale předpokládám, že se Worker prostřednictvím Poolu 4x připojí k db a dále bude Pool Workery s jejich připojením recyklovat (protože Note that the link is stored statically, which for pthreads, means thread local).
|
||
Časová prodleva: 9 let
|
0