Skip to content

Commit

Permalink
feat: Pool修复及文档
Browse files Browse the repository at this point in the history
  • Loading branch information
chaz6chez committed Oct 13, 2024
1 parent dc27419 commit f4fefd8
Show file tree
Hide file tree
Showing 2 changed files with 68 additions and 2 deletions.
63 changes: 62 additions & 1 deletion docs/doc/utils.md
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,8 @@

### 基础使用

> 以下示例包含了协程通道、协程等待、协程的基础使用方式,关于其工具的大致理论内容可以参考同类型其他语言的相同工具。
- 常见的协程使用
```php
use Workbunny\WebmanCoroutine\Utils\Coroutine\Coroutine;
Expand Down Expand Up @@ -86,6 +88,8 @@
### 自定义`Worker`

> 自定义`Worker`包含了对`Workerman\Worker`及上层应用`监听类进程``普通进程`的协程化实现,需要一些简单的代码入侵,兼容协程化前的逻辑。
#### 普通进程

- 原代码,使用workerman的worker启动4个进程输出start和stop
Expand Down Expand Up @@ -184,4 +188,61 @@
### 对象池

// todo
#### 说明

- PHP中的标量数据在C中是以`zval`体现的,本质上是在C堆上的
- 简单理解:以`$a=1`举例,`$a``1`都保存在其中
- `zval`可以简单理解为PHP栈
- PHP中的对象等数据是在C中以`zheap`体现的,本质上也是在C堆上
- 简单理解:以`$a=new stdClass()`举例,`$a``new stdClass()的地址`保存在`zval`其中,而`new stdClass()`保存在`zheap`
- `zheap`可以简单理解为PHP堆
- PHP堆的相关数据回收策略,可以详见PHP官方文档关于GC部分,可使用gc开头的函数进行操作
- `有栈协程`对于上下文会自动管理`寄存器信息``栈数据`,除此之外的`堆数据`**非协程并发安全**
- 对象池提供了对PHP堆数据的深拷贝操作`不完全支持`
- `callable | Closure` 类型数据因为可能存在引用上下文,无法对引用的上下文进行深拷贝
- `object` 类型可能存在静态属性,静态属性无法递归clone
- `resource` 类型存在资源句柄、连接等信息,所以无法clone
- `array` 类型是一种特殊的复合类型,可能存在以上所有情况的竞合
- 对象池提供了对PHP堆数据的锁功能

#### 示例

- 池化拷贝

```php
use Workbunny\WebmanCoroutine\Utils\Pool\Pool;
$source = new class {
public $id = 1;
}
// 池化拷贝2个source的对象,放入名为normal-object的区域,区域索引以1开始
Pool::create('normal-object', 2, $source, true);

// 此时堆数据中存在三个source对象,其中Pool池的normal-object区域存在两个source对象
```
> Tips:
> - 可用于主线程初始化时对象数据的池化操作
> - 可用于对对象的深拷贝操作`不完全支持,请参考说明`
- 资源对象锁

```php
use Workbunny\WebmanCoroutine\Utils\Pool\Pool;
$source = new class {
public $id = 1;
}
// 将source的对象放入名为normal-object的区域,不进行拷贝,PHP栈中多出一次对source对象的引用
Pool::create('normal-object', 1, $source, false);

// 此时堆数据中存在1个source对象,其中Pool池的normal-object区域是引用的source对象

// 等待获取normal-object区域闲置的source对象,获取到时执行回调
// 超时时间10秒,如果超时则抛出TimeoutException
Pool::waitForIdle('normal-object', function ($source) {
$source->id = 2;
}, 10);
```
> Tips:
> - 可用于为资源对象的操作加锁,避免协程间的竞争状态
> - `waitForIdle`在协程环境下当前线程非阻塞,非协程环境下当前线程阻塞,基建使用`wait_for()`函数实现
- 更多使用,TODO
7 changes: 6 additions & 1 deletion src/Utils/Pool/Pool.php
Original file line number Diff line number Diff line change
Expand Up @@ -151,7 +151,12 @@ public static function waitForIdle(string $name, \Closure $closure, int $timeout
$pool = self::idle($name);
return $pool !== null;
}, $timeout);
return call_user_func($closure, $pool);
try {
$pool->setIdle(false);
return call_user_func($closure, $pool);
} finally {
$pool->setIdle(true);
}
}

/**
Expand Down

0 comments on commit f4fefd8

Please sign in to comment.