106 lines
2.7 KiB
PHP
106 lines
2.7 KiB
PHP
<?php
|
|
/**
|
|
* @author Jenner <hypxm@qq.com>
|
|
* @blog http://www.huyanping.cn
|
|
* @license https://opensource.org/licenses/MIT MIT
|
|
* @datetime: 2015/11/19 20:49
|
|
*/
|
|
|
|
namespace Jenner\SimpleFork;
|
|
|
|
/**
|
|
* parallel pool
|
|
*
|
|
* @package Jenner\SimpleFork
|
|
*/
|
|
class ParallelPool extends AbstractPool
|
|
{
|
|
|
|
/**
|
|
* @var callable|Runnable sub process callback
|
|
*/
|
|
protected $runnable;
|
|
|
|
/**
|
|
* @var int max process count
|
|
*/
|
|
protected $max;
|
|
|
|
/**
|
|
* @param callable|Runnable $callback
|
|
* @param int $max
|
|
*/
|
|
public function __construct($callback, $max = 4)
|
|
{
|
|
if (!is_callable($callback) && !($callback instanceof Runnable)) {
|
|
throw new \InvalidArgumentException('callback must be a callback function or a object of Runnalbe');
|
|
}
|
|
|
|
$this->runnable = $callback;
|
|
$this->max = $max;
|
|
}
|
|
|
|
/**
|
|
* start the same number processes and kill the old sub process
|
|
* just like nginx -s reload
|
|
* this method will block until all the old process exit;
|
|
*
|
|
* @param bool $block
|
|
*/
|
|
public function reload($block = true)
|
|
{
|
|
$old_processes = $this->processes;
|
|
for ($i = 0; $i < $this->max; $i++) {
|
|
$process = new Process($this->runnable);
|
|
$process->start();
|
|
$this->processes[$process->getPid()] = $process;
|
|
}
|
|
|
|
foreach ($old_processes as $process) {
|
|
$process->shutdown();
|
|
$process->wait($block);
|
|
unset($this->processes[$process->getPid()]);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* keep sub process count
|
|
*
|
|
* @param bool $block block the master process
|
|
* to keep the sub process count all the time
|
|
* @param int $interval check time interval
|
|
*/
|
|
public function keep($block = false, $interval = 100)
|
|
{
|
|
do {
|
|
$this->start();
|
|
|
|
// recycle sub process and delete the processes
|
|
// which are not running from process list
|
|
foreach ($this->processes as $process) {
|
|
if (!$process->isRunning()) {
|
|
unset($this->processes[$process->getPid()]);
|
|
}
|
|
}
|
|
|
|
$block ? usleep($interval) : null;
|
|
} while ($block);
|
|
}
|
|
|
|
/**
|
|
* start the pool
|
|
*/
|
|
public function start()
|
|
{
|
|
$alive_count = $this->aliveCount();
|
|
// create sub process and run
|
|
if ($alive_count < $this->max) {
|
|
$need = $this->max - $alive_count;
|
|
for ($i = 0; $i < $need; $i++) {
|
|
$process = new Process($this->runnable);
|
|
$process->start();
|
|
$this->processes[$process->getPid()] = $process;
|
|
}
|
|
}
|
|
}
|
|
} |