Skip to content

Commit 0222985

Browse files
committed
Optimization of timeout-related content for wait/waitFor.
1 parent f319a56 commit 0222985

File tree

9 files changed

+70
-56
lines changed

9 files changed

+70
-56
lines changed

src/Handlers/DefaultHandler.php

+1-1
Original file line numberDiff line numberDiff line change
@@ -58,7 +58,7 @@ public static function waitFor(?\Closure $closure = null, float|int $timeout = -
5858
return;
5959
}
6060
// @codeCoverageIgnoreEnd
61-
sleep(max(intval($timeout), 0));
61+
sleep(0);
6262
}
6363
}
6464
}

src/Handlers/RevoltHandler.php

+1-1
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,7 @@ public static function waitFor(?\Closure $closure = null, float|int $timeout = -
4848
if ($timeout > 0 && microtime(true) - $time >= $timeout) {
4949
throw new TimeoutException("Timeout after $timeout seconds.");
5050
}
51-
RevoltHandler::sleep($timeout);
51+
RevoltHandler::sleep(0);
5252
}
5353
}
5454

src/Handlers/RippleHandler.php

+1-1
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,7 @@ public static function waitFor(?\Closure $closure = null, float|int $timeout = -
4747
if ($timeout > 0 && microtime(true) - $time >= $timeout) {
4848
throw new TimeoutException("Timeout after $timeout seconds.");
4949
}
50-
static::_sleep($timeout);
50+
static::_sleep(0);
5151
}
5252
}
5353

src/Handlers/SwooleHandler.php

+1-1
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@ public static function waitFor(?\Closure $closure = null, float|int $timeout = -
4040
if ($timeout > 0 && microtime(true) - $time >= $timeout) {
4141
throw new TimeoutException("Timeout after $timeout seconds.");
4242
}
43-
usleep(max((int) ($timeout * 1000 * 1000), 0));
43+
usleep(0);
4444
}
4545
}
4646
}

src/Handlers/SwowHandler.php

+1-1
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,7 @@ public static function waitFor(?\Closure $closure = null, float|int $timeout = -
4242
if ($timeout > 0 && microtime(true) - $time >= $timeout) {
4343
throw new TimeoutException("Timeout after $timeout seconds.");
4444
}
45-
usleep(max((int) ($timeout * 1000 * 1000), 0));
45+
usleep(0);
4646
}
4747
}
4848
}

src/Utils/WaitGroup/Handlers/RevoltWaitGroup.php

+14-10
Original file line numberDiff line numberDiff line change
@@ -7,13 +7,16 @@
77

88
namespace Workbunny\WebmanCoroutine\Utils\WaitGroup\Handlers;
99

10-
use Workbunny\WebmanCoroutine\Handlers\RevoltHandler;
10+
use Revolt\EventLoop\Suspension;
11+
use Revolt\EventLoop;
1112

1213
class RevoltWaitGroup implements WaitGroupInterface
1314
{
1415
/** @var int */
1516
protected int $_count;
1617

18+
protected ?Suspension $_suspension = null;
19+
1720
/** @inheritdoc */
1821
public function __construct()
1922
{
@@ -32,6 +35,7 @@ public function __destruct()
3235
}
3336
} finally {
3437
$this->_count = 0;
38+
$this->_suspension = null;
3539
}
3640
}
3741

@@ -47,6 +51,9 @@ public function add(int $delta = 1): bool
4751
public function done(): bool
4852
{
4953
$this->_count--;
54+
if ($this->_count <= 0) {
55+
$this->_suspension?->resume();
56+
}
5057

5158
return true;
5259
}
@@ -60,15 +67,12 @@ public function count(): int
6067
/** @inheritdoc */
6168
public function wait(int|float $timeout = -1): void
6269
{
63-
$time = microtime(true);
64-
while (1) {
65-
if ($timeout > 0 and microtime(true) - $time >= $timeout) {
66-
return;
67-
}
68-
if ($this->_count <= 0) {
69-
return;
70-
}
71-
RevoltHandler::sleep(max($timeout, 0));
70+
$this->_suspension = EventLoop::getSuspension();
71+
if ($timeout > 0) {
72+
EventLoop::delay($timeout, function () {
73+
$this->_suspension?->resume();
74+
});
7275
}
76+
$this->_suspension->suspend();
7377
}
7478
}

src/Utils/WaitGroup/Handlers/RippleWaitGroup.php

+33-14
Original file line numberDiff line numberDiff line change
@@ -7,11 +7,19 @@
77

88
namespace Workbunny\WebmanCoroutine\Utils\WaitGroup\Handlers;
99

10+
use Closure;
11+
use Revolt\EventLoop\Suspension;
12+
1013
class RippleWaitGroup implements WaitGroupInterface
1114
{
1215
/** @var int */
1316
protected int $_count;
1417

18+
/**
19+
* @var Suspension|null
20+
*/
21+
protected ?Suspension $_suspension = null;
22+
1523
/** @inheritdoc */
1624
public function __construct()
1725
{
@@ -30,6 +38,7 @@ public function __destruct()
3038
}
3139
} finally {
3240
$this->_count = 0;
41+
$this->_suspension = null;
3342
}
3443
}
3544

@@ -45,6 +54,9 @@ public function add(int $delta = 1): bool
4554
public function done(): bool
4655
{
4756
$this->_count--;
57+
if ($this->_count <= 0) {
58+
$this->_suspension?->resume();
59+
}
4860

4961
return true;
5062
}
@@ -58,25 +70,32 @@ public function count(): int
5870
/** @inheritdoc */
5971
public function wait(int|float $timeout = -1): void
6072
{
61-
$time = microtime(true);
62-
while (1) {
63-
if ($timeout > 0 and microtime(true) - $time >= $timeout) {
64-
return;
65-
}
66-
if ($this->_count <= 0) {
67-
return;
68-
}
69-
$this->_sleep(0);
73+
$this->_suspension = $this->_getSuspension();
74+
if ($timeout > 0) {
75+
$this->_delay(function () {
76+
$this->_suspension?->resume();
77+
}, $timeout);
7078
}
79+
$this->_suspension->suspend();
80+
}
81+
82+
/**
83+
* @codeCoverageIgnore 用于测试mock,忽略覆盖
84+
* @param Closure $closure
85+
* @param int|float $timeout
86+
* @return string
87+
*/
88+
protected function _delay(Closure $closure, int|float $timeout): string
89+
{
90+
return \Co\delay($closure, max($timeout, 0.1));
7191
}
7292

7393
/**
74-
* @codeCoverageIgnore 测试mock,忽略覆盖
75-
* @param int|float $second
76-
* @return void
94+
* @codeCoverageIgnore 用于测试mock,忽略覆盖
95+
* @return Suspension
7796
*/
78-
protected function _sleep(int|float $second): void
97+
protected function _getSuspension(): Suspension
7998
{
80-
\Co\sleep(max($second, 0));
99+
return \Co\getSuspension();
81100
}
82101
}

tests/UtilsCase/WaitGroup/RippleWaitGroupTest.php

+10
Original file line numberDiff line numberDiff line change
@@ -41,14 +41,24 @@ public function testCount()
4141

4242
public function testWait()
4343
{
44+
$suspensionMock = Mockery::mock('alias:\Revolt\EventLoop\Suspension');
45+
$suspensionMock->shouldReceive('resume')->andReturnNull();
46+
$suspensionMock->shouldReceive('suspend')->andReturnNull();
4447
$partialMock = Mockery::mock(RippleWaitGroup::class, [1])->makePartial();
4548
$partialMock->add();
4649
$partialMock->shouldAllowMockingProtectedMethods()->shouldReceive('_sleep')->andReturnNull();
50+
$partialMock->shouldAllowMockingProtectedMethods()->shouldReceive('_getSuspension')->andReturn($suspensionMock);
51+
4752

4853
$partialMock->done();
4954
$partialMock->wait();
5055
$this->assertEquals(0, $partialMock->count());
5156

57+
$partialMock->shouldAllowMockingProtectedMethods()->shouldReceive('_delay')->andReturnUsing(function ($callback, $timeout) {
58+
$this->assertEquals(1, $timeout);
59+
$callback();
60+
return 'delayEventId';
61+
});
5262
$partialMock->add();
5363
$partialMock->wait(1);
5464
$this->assertEquals(1, $partialMock->count());

tests/UtilsCase/WaitGroup/SwowWaitGroupTest.php

+8-27
Original file line numberDiff line numberDiff line change
@@ -8,9 +8,6 @@
88
use Workbunny\Tests\TestCase;
99
use Workbunny\WebmanCoroutine\Utils\WaitGroup\Handlers\SwowWaitGroup;
1010

11-
/**
12-
* @runTestsInSeparateProcesses
13-
*/
1411
class SwowWaitGroupTest extends TestCase
1512
{
1613
protected int $_count = 0;
@@ -25,13 +22,9 @@ protected function tearDown(): void
2522
public function testAdd()
2623
{
2724
$swowMock = Mockery::mock('alias:Swow\Sync\WaitGroup');
28-
$swowMock->shouldReceive('add')->with(1)->andReturnUsing(function () {
25+
$swowMock->shouldReceive('add')->with(1)->andReturnUsing(function ($delta) {
2926
// 模拟增加计数
30-
$this->_count++;
31-
});
32-
$swowMock->shouldReceive('count')->with(1)->andReturnUsing(function () {
33-
// 模拟增加计数
34-
return $this->_count;
27+
$this->_count += $delta;
3528
});
3629

3730
$wg = new SwowWaitGroup();
@@ -47,18 +40,14 @@ public function testAdd()
4740
public function testDone()
4841
{
4942
$swowMock = Mockery::mock('alias:Swow\Sync\WaitGroup');
50-
$swowMock->shouldReceive('add')->with(1)->andReturnUsing(function () {
43+
$swowMock->shouldReceive('add')->with(1)->andReturnUsing(function ($delta) {
5144
// 模拟增加计数
52-
$this->_count++;
45+
$this->_count += $delta;
5346
});
5447
$swowMock->shouldReceive('done')->andReturnUsing(function () {
5548
// 模拟减少计数
5649
$this->_count--;
5750
});
58-
$swowMock->shouldReceive('count')->with(1)->andReturnUsing(function () {
59-
// 模拟增加计数
60-
return $this->_count;
61-
});
6251

6352
$wg = new SwowWaitGroup();
6453
$reflection = new \ReflectionClass($wg);
@@ -74,13 +63,9 @@ public function testDone()
7463
public function testCount()
7564
{
7665
$swowMock = Mockery::mock('alias:Swow\Sync\WaitGroup');
77-
$swowMock->shouldReceive('add')->with(1)->andReturnUsing(function () {
66+
$swowMock->shouldReceive('add')->with(1)->andReturnUsing(function ($delta) {
7867
// 模拟增加计数
79-
$this->_count++;
80-
});
81-
$swowMock->shouldReceive('count')->with(1)->andReturnUsing(function () {
82-
// 模拟增加计数
83-
return $this->_count;
68+
$this->_count += $delta;
8469
});
8570
$wg = new SwowWaitGroup();
8671
$reflection = new \ReflectionClass($wg);
@@ -96,18 +81,14 @@ public function testCount()
9681
public function testWait()
9782
{
9883
$swowMock = Mockery::mock('alias:Swow\Sync\WaitGroup');
99-
$swowMock->shouldReceive('add')->with(1)->andReturnUsing(function () {
84+
$swowMock->shouldReceive('add')->with(1)->andReturnUsing(function ($delta) {
10085
// 模拟增加计数
101-
$this->_count++;
86+
$this->_count += $delta;
10287
});
10388
$swowMock->shouldReceive('done')->andReturnUsing(function () {
10489
// 模拟减少计数
10590
$this->_count--;
10691
});
107-
$swowMock->shouldReceive('count')->with(1)->andReturnUsing(function () {
108-
// 模拟增加计数
109-
return $this->_count;
110-
});
11192
$swowMock->shouldReceive('wait')->with(-1)->andReturnNull();
11293

11394
$wg = new SwowWaitGroup();

0 commit comments

Comments
 (0)