I have a scenario where an array of objects (Players) must be read and modified by objects of other classes. Those objects will work on the same array, that is, any change to the array is seen by all objects. Anything is likely to modify the array including threads and IO event functions.
Here are the specifics:
class Player {
public $connection;
public $x,$y,$velocity;
public function __construct(ConnectionInterface $conn, $initx, $inity)
{ /* ... */ }
public function updateVelocity($newVelocity) { /* ... */ }
}
$players_arr = array();
class ConnectionClass extends Thread implements MessageComponentInterface {
private $players;
// A new player connected
public function onOpen(ConnectionInterface $conn) {
// ...
array_push($this->players, new Player($conn, x, y);
}
public function run() {
while(true) {
// ...
foreach ($this->players as $player)
$player->connection->send(data);
sleep(1);
}
}
}
class World extends Thread {
private $players;
public function run() {
while(true) {
// ...
foreach ($this->players as $player)
$player->updateVelocity($vel);
usleep(30000);
}
}
}
$players in World
and in ConnectionClass
should always be identical!!
The ConnectionInterface
and MessageComponentInterface
are part of "Ratchet" a Web-Socket library I'm using. Also, if it makes any difference, each class is in its own .php file.
How should I structure the code?
Should I make the shared array static in Player
class itself? if so, how to access it from other classes?
Things I've tried:
$players_arr
to the classes' constructors and assigning it to $players
: got cannot assign by reference to overloaded object
error.
http://ubuntuforums.org/showthread.php?t=2082788ArrayObject
: adding a new Player()
to it in onOpen()
is not yielding no effects. (Could have done wrong?)
Sharing array inside object through classes in phpNote: I'm aware that multi-threaded access to the array requires special measures and synchronization (Please elaborate), but the main issue is how to share the array across classes (not necessarily threads)
If the purpose that the World
and ConnectionClass
are extending the Thread
class is to share same $players this won't work.
As far as I can get your problem a new instance of ArrayObject
should do the job, you just have pass it's instance to the World
's and ConnectionClass
's instances:
$players = new ArrayObject();
$connection = new ConnectionClass($players); //add it to the other arguments if any
$world = new World($players); //add it to the other arguments if any
//or you can with setter
$players = new ArrayObject();
$connection = new ConnectionClass();
$connection->setPlayers($players);
$world = new World($players);
$world-> setPlayers($players);
You should change the controllers of your World
and ConnectionClass
to initiate the private $players
property with the new argument, or implement a setter.
public function __construct($players)
{
$this->players = $players;
}
//or
public function setPlayers($players)
{
$this->players = $players;
}
You should also change onOpen
's implemention:
public function onOpen(ConnectionInterface $conn) {
// ...
$this->players->append(new Player($conn, x, y));
}