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;
							 | 
						||
| 
								 | 
							
								            }
							 | 
						||
| 
								 | 
							
								        }
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								}
							 |