File | Date | Author | Commit |
---|---|---|---|
examples | 2015-11-04 |
![]() |
[45a44f] remove queue channel params |
src | 2015-11-04 |
![]() |
[85b53b] remove queue channel params and test |
tests | 2015-11-04 |
![]() |
[45a44f] remove queue channel params |
.gitignore | 2015-08-21 |
![]() |
[3ae61b] add phpdoc |
.scrutinizer.yml | 2015-10-28 |
![]() |
[8872a7] tests |
.travis.yml | 2015-10-28 |
![]() |
[ce81eb] tests |
LICENSE | 2015-08-12 |
![]() |
[94ef5b] Initial commit |
README.ZH.MD | 2015-09-06 |
![]() |
[fed778] update readme |
README.md | 2015-11-04 |
![]() |
[45a44f] remove queue channel params |
autoload.php | 2015-08-13 |
![]() |
[020141] add autoload.php and tests |
composer.json | 2015-10-28 |
![]() |
[56ae72] release |
phpunit.xml | 2015-10-26 |
![]() |
[123a13] tests |
中文README.MD
Simple Fork Framework based on PCNTL, the interfaces are like Thread and Runnable in Java.
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.
composer require jenner/simple_fork
require path/to/SimpleFork/autoload.php
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
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)
)
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.
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);