1
0
mirror of https://github.com/danog/parallel.git synced 2024-12-12 17:17:20 +01:00
parallel/lib/Worker/BasicEnvironment.php

204 lines
4.4 KiB
PHP
Raw Normal View History

2016-12-30 02:16:04 +01:00
<?php
2016-01-15 00:44:43 +01:00
2016-08-23 23:47:40 +02:00
namespace Amp\Parallel\Worker;
2016-01-15 00:44:43 +01:00
use Amp\Loop;
use Amp\Struct;
2016-08-18 18:04:48 +02:00
2018-10-21 17:54:46 +02:00
final class BasicEnvironment implements Environment
2018-10-07 16:50:45 +02:00
{
2016-08-26 17:10:03 +02:00
/** @var array */
2016-01-15 00:44:43 +01:00
private $data = [];
2016-08-26 17:10:03 +02:00
/** @var \SplPriorityQueue */
2016-01-15 00:44:43 +01:00
private $queue;
2016-08-26 17:10:03 +02:00
/** @var string */
2016-01-15 00:44:43 +01:00
private $timer;
2018-10-07 16:50:45 +02:00
public function __construct()
{
$this->queue = $queue = new \SplPriorityQueue;
$data = &$this->data;
2016-01-15 00:44:43 +01:00
$this->timer = Loop::repeat(1000, static function ($watcherId) use ($queue, &$data) {
2016-08-18 18:04:48 +02:00
$time = \time();
while (!$queue->isEmpty()) {
list($key, $expiration) = $queue->top();
2016-01-15 00:44:43 +01:00
if (!isset($data[$key])) {
// Item removed.
$queue->extract();
continue;
}
$struct = $data[$key];
if ($struct->expire === 0) {
// Item was set again without a TTL.
$queue->extract();
continue;
}
2016-01-15 00:44:43 +01:00
if ($struct->expire !== $expiration) {
// Expiration changed or TTL updated.
$queue->extract();
continue;
}
if ($time < $struct->expire) {
// Item at top has not expired, break out of loop.
break;
2016-01-15 00:44:43 +01:00
}
unset($data[$key]);
$queue->extract();
2016-01-15 00:44:43 +01:00
}
if ($queue->isEmpty()) {
Loop::disable($watcherId);
2016-01-15 00:44:43 +01:00
}
});
2017-05-18 09:51:31 +02:00
2016-08-18 18:04:48 +02:00
Loop::disable($this->timer);
Loop::unreference($this->timer);
2016-01-15 00:44:43 +01:00
}
/**
* @param string $key
*
* @return bool
*/
2018-10-07 16:50:45 +02:00
public function exists(string $key): bool
{
2016-01-23 07:00:56 +01:00
return isset($this->data[$key]);
2016-01-15 00:44:43 +01:00
}
/**
* @param string $key
*
* @return mixed|null Returns null if the key does not exist.
*/
2018-10-07 16:50:45 +02:00
public function get(string $key)
{
if (!isset($this->data[$key])) {
return null;
2016-01-15 00:44:43 +01:00
}
$struct = $this->data[$key];
if ($struct->ttl !== null) {
$expire = \time() + $struct->ttl;
if ($struct->expire < $expire) {
$struct->expire = $expire;
$this->queue->insert([$key, $struct->expire], -$struct->expire);
}
}
return $struct->data;
2016-01-15 00:44:43 +01:00
}
2017-05-18 09:51:31 +02:00
2016-01-15 00:44:43 +01:00
/**
* @param string $key
* @param mixed $value Using null for the value deletes the key.
* @param int $ttl Number of seconds until data is automatically deleted. Use null for unlimited TTL.
*
* @throws \Error If the time-to-live is not a positive integer.
2016-01-15 00:44:43 +01:00
*/
2018-10-07 16:50:45 +02:00
public function set(string $key, $value, int $ttl = null)
{
if ($value === null) {
2016-01-15 00:44:43 +01:00
$this->delete($key);
return;
}
if ($ttl !== null && $ttl <= 0) {
throw new \Error("The time-to-live must be a positive integer or null");
2016-01-15 00:44:43 +01:00
}
$struct = new class {
use Struct;
public $data;
public $expire = 0;
public $ttl;
};
$struct->data = $value;
if ($ttl !== null) {
$struct->ttl = $ttl;
$struct->expire = \time() + $ttl;
$this->queue->insert([$key, $struct->expire], -$struct->expire);
2016-01-15 00:44:43 +01:00
2016-08-18 18:04:48 +02:00
Loop::enable($this->timer);
2016-01-15 00:44:43 +01:00
}
$this->data[$key] = $struct;
2016-01-15 00:44:43 +01:00
}
/**
* @param string $key
*/
2018-10-07 16:50:45 +02:00
public function delete(string $key)
{
unset($this->data[$key]);
2016-01-15 00:44:43 +01:00
}
/**
* Alias of exists().
*
* @param $key
*
* @return bool
*/
2018-10-07 16:50:45 +02:00
public function offsetExists($key)
{
2016-01-15 00:44:43 +01:00
return $this->exists($key);
}
/**
* Alias of get().
*
* @param string $key
*
* @return mixed
*/
2018-10-07 16:50:45 +02:00
public function offsetGet($key)
{
2016-01-15 00:44:43 +01:00
return $this->get($key);
}
/**
* Alias of set() with $ttl = null.
2016-01-15 00:44:43 +01:00
*
* @param string $key
* @param mixed $value
*/
2018-10-07 16:50:45 +02:00
public function offsetSet($key, $value)
{
2016-01-15 00:44:43 +01:00
$this->set($key, $value);
}
/**
* Alias of delete().
*
* @param string $key
*/
2018-10-07 16:50:45 +02:00
public function offsetUnset($key)
{
2016-01-15 00:44:43 +01:00
$this->delete($key);
}
/**
* Removes all values.
*/
2018-10-07 16:50:45 +02:00
public function clear()
{
2016-01-15 00:44:43 +01:00
$this->data = [];
2016-08-18 18:04:48 +02:00
Loop::disable($this->timer);
2016-08-23 01:25:19 +02:00
$this->queue = new \SplPriorityQueue;
2016-01-15 00:44:43 +01:00
}
}