I am running a CGI program in non-threading PHP, a little exercise in artificial life and evolution. Organisms have a genome and an interpreter, which forces them to perform certain operations, including moving and interacting with each other on a common world map. I currently support poor visibility of threads using several PHP processes interacting through a MySQL database, but I want to rewrite the code so that it uses pthreads to run continuously on a single thread, not necessarily using the database (although I'd probably , want to leave it for a message).
I looked through questions and answered questions and code examples on github, but could not find anything that, as far as I can tell, concerns what I want. Since I am not a genius OOP coder and completely new to writing multi-threaded code, especially in PHP, my questions will be quite broad.
I tried to narrow my questions a bit by writing code that shows what I'm trying to do, but it can still be too wide. I would appreciate any advice on how to narrow it further.
My questions about the code below:
- How to make the body act on the object of the common world, so that changes in the World object are transmitted to all flows, avoiding conflicts and maintaining consistency?
- Given that the size of the population is ultimately variable, is there a way to make a reference to part of the Organisms of the World object (i.e. $ world-> organisms), and so that World can create new organisms as shown below (erroneous) code ?
- Given that I ultimately want to create a collection of hundreds of Organisms, do you have any pointers to limiting the number of active threads (i.e. limiting memory / processor usage) while maintaining constancy?
The code below (of course does not work, but) illustrates what I want to achieve:
class World extends Thread
{
public $map;
public $sx;
public $sy;
public $organisms;
public function __construct($sx, $sy, $p)
{
$map = array();
for( $i = 0; $i < $sx; $i++ )
{
$map[$i] = array();
for( $j = 0; $j < $sy; $j++ )
{
$map[$i][$j] = 0;
}
}
$this->map = $map;
$this->sx = $sx;
$this->sy = $sy;
$this->organisms = array();
for( $i = 0; $i < $p; $i++ )
{
$this->makeOrganism($i+1, $i+1, $i+1);
}
}
public function makeOrganism($x, $y, $value)
{
if( $x < 1 || $x > $this->sx ) return false;
if( $y < 1 || $y > $this->sy ) return false;
if( $this->getMap($x, $y) != 0 ) return false;
echo "creating new organism $value\n";
$organisms = $this->organisms;
$organisms[] = new Organism($this, $x, $y, $value);
$this->organisms = $organisms;
return true;
}
public function setMap($x, $y, $value)
{
return $this->map[$x-1][$y-1] = $value;
}
public function getMap($x, $y)
{
return $this->map[$x-1][$y-1];
}
public function getSX()
{
return $this->sx;
}
public function getSY()
{
return $this->sy;
}
public function run()
{
for( $i = 0; $i < count($this->organisms); $i++ )
{
echo "starting organism ", $this->value, "\n";
$this->organisms[$i]->start();
}
}
}
class Organism extends Thread
{
public $value;
public $world;
public $x;
public $y;
public function __construct(World $world, $x, $y, $value)
{
$this->world = $world;
$this->value = $value;
$this->x = $x;
$this->y = $y;
$this->world->setMap($x, $y, $value);
}
public function move($dx, $dy)
{
$x = $this->x + $dx;
$y = $this->y + $dy;
if( $x < 1 || $x > $this->world->getSX() ) return false;
if( $y < 1 || $y > $this->world->getSY() ) return false;
if( $this->world->getMap($x, $y) != 0 ) return false;
$this->world->setMap($x, $y, $this->value);
$this->world->setMap($this->x, $this->y, 0);
$this->x = $x;
$this->y = $y;
return true;
}
public function getValue()
{
return $this->value;
}
public function run()
{
while( true )
{
echo "running organism ", $this->getValue(), "\n";
$dx = rand(-1, 1);
$dy = rand(-1, 1);
$this->move($dx, $dy);
if( rand(0, 100) > 95 )
{
$this->world->makeOrganism($this->x+1, $this->y+1, $this->value+100);
}
$this->wait(1000 + rand(500, 1500));
}
}
}
$world = new World(50, 50, 50);
$world->start();
$world->join();