examples | ||
src | ||
tests | ||
.gitignore | ||
composer.json | ||
phpunit.xml | ||
README.md |
noccylabs/ipc
This is a one-size-fits-all IPC library to facilitate communication between threads and processes.
For complete examples, see the examples
directory in the source tree.
Signals
Asynchronous signals are automatically enabled if supported. Otherwise, the
pcntl_signal_dispatch()
method must be frequently called from your main loop.
You can test for this using the SIGNALS_ASYNC
constant:
if (!SIGNALS_ASYNC) {
pcntl_signal_dispatch();
}
Signal handlers
Signal handlers allow for multiple listeners, with any one of them being able to prevent the signal from bubbling up.
$handler = new SignalHandler(SIGUSR1);
$handler->addHandler(function () {
// Handle SIGUSR1, return true to stop bubbling
return true;
});
You can also handle as well as fire signals using the Signal
class:
$signal = new Signal(SIGUSR1);
$signal->setHandler(function () {
// Handle SIGUSR1
});
// Dispatch the signal to ourselves
(new Signal(SIGUSR1))->dispatch($pid);
Signal traps
Traps are used in the main loop to break on signals
$trap = new SignalTrap(SIGINT);
while (!$trap->isTrapped()) {
// ...
}
Timers
Timers fire asynchronously at fixed 1 second intervals. It requires signals to be processed; see above.
// Once every second...
$timer = new Timer(function () {
echo ".";
});
File locks
File locks uses a shared file as a resource for locking.
// Creating the lock will not acquire it
$lock = new FileLock(__FILE__);
if (!$lock->acquire()) {
echo "fail!\n";
} else {
$lock->release();
}
SysV wrappers
All these wrappers depend on a KeyInterface
being passed to the constructor.
This is usually an instance of a FileKey
, created as such:
$key = new FileKey(__FILE__);
The key has a project identifier that starts at chr(0)
, or "\0"
. To increase
this identifier, and thus point to another segment, just clone it.
$key2 = clone $key1;
Semaphores
Semaphores are created with a key and a max count.
$key = new FileKey(__FILE__);
$sem = new Semaphore($key, 2);
$sem->allocate(); // -> true
$sem->allocate(); // -> true
$sem->allocate(); // -> false
$sem->release();
$mutex->destroy();
Mutexes
A mutex is a semaphore with a max count of 1.
$key = new FileKey(__FILE__);
$mutex = new Mutex($key);
$mutex->allocate(); // -> true
$mutex->allocate(); // -> false
$mutex->release();
$mutex->destroy();
Message Queues
$key = new FileKey(__FILE__);
$msgq = new Queue($key);
$msgq->send(1, [ "Some data", [ "format"=>"foo" ]]);
$data = $msgq->receive(1, $type);
$msgq->destroy();
Shared Memory
Shared memory using SharedData
supports integrity checking when setting, using
the third parameter to set()
.
$key = new FileKey(__FILE__);
$shm = new SharedData($key);
do {
$counter = $shm->get("counter") + 1;
} while (!$shm->set("counter", $counter, true));
$shm->destroy();
The SharedMemory
class is a simple integer-indexed array
$key = new FileKey(__FILE__);
$shm = new SharedMemory($key);
$shm[0] = 42;
$shm->destroy();
Communication
Channels
Channels are essentially connected pipes. A channel can be created with a stream resource,
or through the createPair()
factory method.
[ $ch1, $ch2 ] = StreamChannel::createPair();
$ch1->send($data);
$rcvd = $ch2->receive();
MultiChannels
The MultiStreamChannel
lets you connect multiple clients to a single master channel.
$master = new MultiStreamChannel();
$ch1 = $master->createClient();
$ch2 = $master->createClient();
$ch1->send($data);
$rcvd = $ch2->receive();
Buses
Buses are high-level abstractions of channels, implementing limited rpc with handling of return values.
$master = new Master();
$client = $master->createClient();
$client->export("/db/updateindex", function ($schema) {
// Update the index
return true;
});
$other = $master->createClient();
$other->call("/db/updateindex", "*")->then(function ($status) {
if ($status === true) {
echo "Index updated!\n";
}
});