PHP7 Pool

This commit is contained in:
Dominik Liebler 2016-09-22 14:16:12 +02:00
parent 7beb1420b4
commit 61a6f03f04
5 changed files with 58 additions and 98 deletions

View File

@ -1,51 +0,0 @@
<?php
namespace DesignPatterns\Creational\Pool;
class Processor
{
private $pool;
private $processing = 0;
private $maxProcesses = 3;
private $waitingQueue = array();
public function __construct(Pool $pool)
{
$this->pool = $pool;
}
public function process($image)
{
if ($this->processing++ < $this->maxProcesses) {
$this->createWorker($image);
} else {
$this->pushToWaitingQueue($image);
}
}
private function createWorker($image)
{
$worker = $this->pool->get();
$worker->run($image, array($this, 'processDone'));
}
public function processDone($worker)
{
$this->processing--;
$this->pool->dispose($worker);
if (count($this->waitingQueue) > 0) {
$this->createWorker($this->popFromWaitingQueue());
}
}
private function pushToWaitingQueue($image)
{
$this->waitingQueue[] = $image;
}
private function popFromWaitingQueue()
{
return array_pop($this->waitingQueue);
}
}

View File

@ -33,21 +33,15 @@ Code
You can also find these code on `GitHub`_ You can also find these code on `GitHub`_
Pool.php WorkerPool.php
.. literalinclude:: Pool.php .. literalinclude:: WorkerPool.php
:language: php :language: php
:linenos: :linenos:
Processor.php StringReverseWorker.php
.. literalinclude:: Processor.php .. literalinclude:: StringReverseWorker.php
:language: php
:linenos:
Worker.php
.. literalinclude:: Worker.php
:language: php :language: php
:linenos: :linenos:
@ -60,11 +54,5 @@ Tests/PoolTest.php
:language: php :language: php
:linenos: :linenos:
Tests/TestWorker.php
.. literalinclude:: Tests/TestWorker.php
:language: php
:linenos:
.. _`GitHub`: https://github.com/domnikl/DesignPatternsPHP/tree/master/Creational/Pool .. _`GitHub`: https://github.com/domnikl/DesignPatternsPHP/tree/master/Creational/Pool
.. __: http://en.wikipedia.org/wiki/Object_pool_pattern .. __: http://en.wikipedia.org/wiki/Object_pool_pattern

View File

@ -2,18 +2,20 @@
namespace DesignPatterns\Creational\Pool; namespace DesignPatterns\Creational\Pool;
class Worker class StringReverseWorker
{ {
/**
* @var \DateTime
*/
private $createdAt;
public function __construct() public function __construct()
{ {
// let's say that constuctor does really expensive work... $this->createdAt = new \DateTime();
// for example creates "thread"
} }
public function run($image, array $callback) public function run(string $text)
{ {
// do something with $image... return strrev($text);
// and when it's done, execute callback
call_user_func($callback, $this);
} }
} }

View File

@ -2,21 +2,28 @@
namespace DesignPatterns\Creational\Pool\Tests; namespace DesignPatterns\Creational\Pool\Tests;
use DesignPatterns\Creational\Pool\Pool; use DesignPatterns\Creational\Pool\WorkerPool;
class PoolTest extends \PHPUnit_Framework_TestCase class PoolTest extends \PHPUnit_Framework_TestCase
{ {
public function testPool() public function testCanGetNewInstancesWithGet()
{ {
$pool = new Pool('DesignPatterns\Creational\Pool\Tests\TestWorker'); $pool = new WorkerPool();
$worker = $pool->get(); $worker1 = $pool->get();
$worker2 = $pool->get();
$this->assertEquals(1, $worker->id); $this->assertCount(2, $pool);
$this->assertNotSame($worker1, $worker2);
}
$worker->id = 5; public function testCanGetSameInstanceTwiceWhenDisposingItFirst()
$pool->dispose($worker); {
$pool = new WorkerPool();
$worker1 = $pool->get();
$pool->dispose($worker1);
$worker2 = $pool->get();
$this->assertEquals(5, $pool->get()->id); $this->assertCount(1, $pool);
$this->assertEquals(1, $pool->get()->id); $this->assertSame($worker1, $worker2);
} }
} }

View File

@ -2,29 +2,43 @@
namespace DesignPatterns\Creational\Pool; namespace DesignPatterns\Creational\Pool;
class Pool class WorkerPool implements \Countable
{ {
private $instances = []; /**
* @var StringReverseWorker[]
*/
private $occupiedWorkers = [];
/**
* @var StringReverseWorker[]
*/
private $freeWorkers = [];
private $class; public function get(): StringReverseWorker
public function __construct($class)
{ {
$this->class = $class; if (count($this->freeWorkers) == 0) {
} $worker = new StringReverseWorker();
} else {
public function get() $worker = array_pop($this->freeWorkers);
{
if (count($this->instances) > 0) {
return array_pop($this->instances);
} }
return new $this->class(); $this->occupiedWorkers[spl_object_hash($worker)] = $worker;
return $worker;
} }
public function dispose($instance) public function dispose(StringReverseWorker $worker)
{ {
$this->instances[] = $instance; $key = spl_object_hash($worker);
if (isset($this->occupiedWorkers[$key])) {
unset($this->occupiedWorkers[$key]);
$this->freeWorkers[$key] = $worker;
}
}
public function count(): int
{
return count($this->occupiedWorkers) + count($this->freeWorkers);
} }
} }