Menu

Tree [85b53b] master /
 History

HTTPS access


File Date Author Commit
 examples 2015-11-04 huyanping huyanping [45a44f] remove queue channel params
 src 2015-11-04 huyanping huyanping [85b53b] remove queue channel params and test
 tests 2015-11-04 huyanping huyanping [45a44f] remove queue channel params
 .gitignore 2015-08-21 huyanping huyanping [3ae61b] add phpdoc
 .scrutinizer.yml 2015-10-28 huyanping huyanping [8872a7] tests
 .travis.yml 2015-10-28 huyanping huyanping [ce81eb] tests
 LICENSE 2015-08-12 Jenner Jenner [94ef5b] Initial commit
 README.ZH.MD 2015-09-06 huyanping huyanping [fed778] update readme
 README.md 2015-11-04 huyanping huyanping [45a44f] remove queue channel params
 autoload.php 2015-08-13 huyanping huyanping [020141] add autoload.php and tests
 composer.json 2015-10-28 huyanping huyanping [56ae72] release
 phpunit.xml 2015-10-26 huyanping huyanping [123a13] tests

Read Me

SimpleFork

Latest Stable Version
Total Downloads
Latest Unstable Version
License
travis
Scrutinizer Code Quality
Code Coverage

中文README.MD
Simple Fork Framework based on PCNTL, the interfaces are like Thread and Runnable in Java.

Why SimpleFork

Writing Multi-Process program is hard for freshman. You must consider that how to recover zombie process, interprocess communication and so on. Especially handle the process signal.
SimpleFork framework provide several interfaces which like Java and solutions in process collect, sync and IPC. You do not need to consider that how to control multi-process.

Require

composer require jenner/simple_fork
require path/to/SimpleFork/autoload.php

Dependencies

must
+ ext-pcntl process control

optional
+ ext-sysvmsg message queue
+ ext-sysvsem semaphore
+ ext-sysvshm shared memory
+ ext-redis redis cache and redis message queue

Property

  • Process Pool
  • Recover zombie process automatically
  • shared memory, system v message queue, semaphore lock. redis cache, redis queue
  • Two ways to make Process: extends Process or implements Runnable
  • You can get the status of sub process
  • You can stop any process if you want, or just shutdown all process.
  • You can register Process::BEFORE_EXIT and Process::BEFORE_START
    callback functions by Process::on().
    If the callback function return true, the process will exit, else it will continue to run.
  • You can reload the processes by reload() method, then the processes
    will exit and start new process instead.

Callback functions

Use Process::on($event, $callback) method to register callback functions
+ Process::BEFORE_START It will be called when the process start.
If it return false, the process will not start and exit with status 0.
+ Process::BEFORE_EXIT It will be called when the main process call stop() method.
If it return false, the process will not exit.
+ Process::AFTER_FINISHED It will be called after the sub process callback is finished.
It accept a param which is the return value of the
callback(Runnable::run(), Process::run, new Process(callable))

Notice

If you want to register signal handler in the master process, the child will inherit the handler.
If you want to register signal handler in child process but before it start,
you can call the Process::registerSignalHandler method. After the child process
start, it will register the signal handler automatically.

Examples

More examples in examples dictionary
A simple example.

class TestRunnable implements \Jenner\SimpleFork\Runnable{

    /**
     * Entrance
     * @return mixed
     */
    public function run()
    {
        echo "I am a sub process" . PHP_EOL;
    }
}

$process = new \Jenner\SimpleFork\Process(new TestRunnable());
$process->start();
$process->wait();

A process using callback

$process = new \Jenner\SimpleFork\Process(function(){
    for($i=0; $i<3; $i++){
        echo $i . PHP_EOL;
        sleep(1);
    }
});

$process->start();
$process->wait();

Process communication using shared memory

class Producer extends \Jenner\SimpleFork\Process{
    public function run(){
        $cache = new \Jenner\SimpleFork\Cache\SharedMemory();
        //$cache = new \Jenner\SimpleFork\Cache\RedisCache();
        for($i = 0; $i<10; $i++){
            $cache->set($i, $i);
            echo "set {$i} : {$i}" . PHH_EOL;
        }
    }
}

class Worker extends \Jenner\SimpleFork\Process{
    public function run(){
        sleep(5);
        $cache = new \Jenner\SimpleFork\Cache\SharedMemory();
        //$cache = new \Jenner\SimpleFork\Cache\RedisCache();
        for($i=0; $i<10; $i++){
            echo "get {$i} : " . $cache->get($i) . PHP_EOL;
        }
    }
}

$producer = new Producer();

$worker = new Worker();

$pool = new \Jenner\SimpleFork\Pool();
$pool->submit($producer);
$pool->submit($worker);
$pool->start();
$pool->wait();

Process communication using system v message queue

class Producer extends \Jenner\SimpleFork\Process
{
    public function run()
    {
        $queue = new \Jenner\SimpleFork\Queue\SystemVMessageQueue();
        //$queue = new \Jenner\SimpleFork\Queue\RedisQueue();
        for ($i = 0; $i < 10; $i++) {
            echo getmypid() . PHP_EOL;
            $queue->put($i);
        }
    }
}

class Worker extends \Jenner\SimpleFork\Process
{
    public function run()
    {
        sleep(5);
        $queue = new \Jenner\SimpleFork\Queue\SystemVMessageQueue();
        //$queue = new \Jenner\SimpleFork\Queue\RedisQueue();
        for ($i = 0; $i < 10; $i++) {
            $res = $queue->get();
            echo getmypid() . ' = ' . $i . PHP_EOL;
            var_dump($res);
        }
    }
}

$producer = new Producer();

$worker = new Worker();

$pool = new \Jenner\SimpleFork\Pool();
$pool->submit($producer);
$pool->submit($worker);
$pool->start();
$pool->wait();

Process communication using Semaphore lock

class TestRunnable implements \Jenner\SimpleFork\Runnable
{

    /**
     * @var \Jenner\SimpleFork\Lock\LockInterface
     */
    protected $sem;

    public function __construct()
    {
        $this->sem = \Jenner\SimpleFork\Lock\Semaphore::create("test");
        //$this->sem = \Jenner\SimpleFork\Lock\FileLock::create("/tmp/test.lock");
    }

    /**
     * @return mixed
     */
    public function run()
    {
        for ($i = 0; $i < 20; $i++) {
            $this->sem->acquire();
            echo "my turn: {$i} " . getmypid() . PHP_EOL;
            $this->sem->release();
            sleep(1);
        }
    }
}

$pool = new \Jenner\SimpleFork\Pool();
$pool->submit(new \Jenner\SimpleFork\Process(new TestRunnable()));
$pool->submit(new \Jenner\SimpleFork\Process(new TestRunnable()));

$pool->start();
$pool->wait();

Process pool to manage processes

class TestRunnable implements \Jenner\SimpleFork\Runnable
{

    /**
     * @return mixed
     */
    public function run()
    {
        sleep(10);
        echo getmypid() . ':done' . PHP_EOL;
    }
}

$pool = new \Jenner\SimpleFork\Pool();
$pool->submit(new \Jenner\SimpleFork\Process(new TestRunnable()));
$pool->submit(new \Jenner\SimpleFork\Process(new TestRunnable()));
$pool->submit(new \Jenner\SimpleFork\Process(new TestRunnable()));

$pool->start();
$pool->wait();

FixedPool to manage processes

class TestRunnable2 implements \Jenner\SimpleFork\Runnable {

    /**
     * process entry
     *
     * @return mixed
     */
    public function run()
    {
        echo 'sub process:' . getmypid() . PHP_EOL;
    }
}

$fixed_pool = new \Jenner\SimpleFork\FixedPool(new TestRunnable2(), 10);
$fixed_pool->start();

$fixed_pool->keep(true);
Want the latest updates on software, tech news, and AI?
Get latest updates about software, tech news, and AI from SourceForge directly in your inbox once a month.