Skip to content

Commit 43199bb

Browse files
committed
Add MapPool component.
1 parent 5085965 commit 43199bb

1 file changed

Lines changed: 131 additions & 0 deletions

File tree

src/MapPool.php

Lines changed: 131 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,131 @@
1+
<?php
2+
/**
3+
* Copyright: Swlib
4+
* Author: Twosee <twose@qq.com>
5+
* Date: 2018/6/30 下午6:03
6+
*/
7+
8+
namespace Swlib\Util;
9+
10+
use Swoole\Coroutine\Channel;
11+
12+
/**
13+
* Class MapPool
14+
* Use SplQueue(unlimited) or Channel(max_size)
15+
* @package Swlib\Util
16+
*/
17+
class MapPool
18+
{
19+
20+
use Singleton;
21+
22+
/** @var Channel[]|\SplQueue[] */
23+
protected $resource_map = [];
24+
/** @var [][] */
25+
protected $status_map = [];
26+
27+
public function init(string $key, int $max_size = -1): bool
28+
{
29+
if (!isset($this->resource_map[$key])) {
30+
if ($max_size < 0) {
31+
$this->resource_map[$key] = new \SplQueue();
32+
} else {
33+
$this->resource_map[$key] = new Channel($max_size);
34+
}
35+
$this->status_map[$key] = [
36+
'max' => $max_size,
37+
'existing' => 0
38+
];
39+
return true;
40+
}
41+
return false;
42+
}
43+
44+
public function create(array $options, string $key = null)
45+
{
46+
if (!$key) {
47+
throw new \InvalidArgumentException('Argument#2 $key can not be empty!');
48+
}
49+
@$this->status_map[$key]['existing']++;
50+
}
51+
52+
public function get(string $key)
53+
{
54+
if (!isset($this->resource_map[$key])) {
55+
$this->init($key);
56+
}
57+
$pool = $this->resource_map[$key];
58+
if ($pool instanceof \SplQueue) {
59+
$available = $this->resource_map[$key]->count() > 0;
60+
} else {
61+
// the resource available or over the max num, use pop or yield and waiting
62+
$available = $this->resource_map[$key]->length() > 0 || $this->status_map[$key]['existing'] >= $this->status_map[$key]['max'];
63+
}
64+
if ($available) {
65+
return $this->resource_map[$key]->pop();
66+
} else {
67+
return null; // need create new one
68+
}
69+
}
70+
71+
public function put($value, string $key = null)
72+
{
73+
if (!$key) {
74+
throw new \InvalidArgumentException('Argument#2 $key can not be empty!');
75+
}
76+
$this->resource_map[$key]->push($value);
77+
}
78+
79+
public function getStatus(string $key): array
80+
{
81+
if (!isset($this->status_map[$key])) {
82+
return [
83+
'max' => null,
84+
'existing' => null,
85+
'in_queue' => null
86+
];
87+
} else {
88+
$pool = $this->resource_map[$key];
89+
$in_queue = $pool instanceof \SplQueue ? $pool->count() : $pool->length();
90+
$this->status_map[$key]['in_queue'] = $in_queue;
91+
return $this->status_map[$key];
92+
}
93+
}
94+
95+
public function getMax(string $key): ?int
96+
{
97+
return $this->status_map[$key]['max'] ?? null;
98+
}
99+
100+
/**
101+
* expend will create the new chan
102+
*
103+
* @param string $key
104+
* @param int $max_size
105+
* @return int do what
106+
*/
107+
public function setMax(string $key, int $max_size = -1): int
108+
{
109+
$is_exist = !$this->init($key, $max_size);
110+
if ($is_exist && $this->resource_map[$key] instanceof Channel) {
111+
$current_max = $this->status_map[$key]['max'];
112+
$this->status_map[$key]['max'] = $max_size;
113+
if ($max_size > $current_max || $max_size < 0) { // expend or unlimited
114+
if ($max_size < 0) { // chan to queue
115+
$new_pool = new \SplQueue();
116+
} else {
117+
$new_pool = new Channel($max_size);
118+
}
119+
$old_chan = $this->resource_map[$key];
120+
while (!$old_chan->isEmpty()) {
121+
$new_pool->push($old_chan->pop());
122+
}
123+
$old_chan->close();
124+
return 1; // expend
125+
} elseif ($max_size < $this->status_map[$key]['max']) {
126+
return -1; // reduce
127+
}
128+
}
129+
return 0; // do nothing
130+
}
131+
}

0 commit comments

Comments
 (0)