-
Notifications
You must be signed in to change notification settings - Fork 24
Expand file tree
/
Copy pathRunner.php
More file actions
94 lines (85 loc) · 2.58 KB
/
Copy pathRunner.php
File metadata and controls
94 lines (85 loc) · 2.58 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
<?php
/**
* Copyright (C) 2014-2026 Textalk and contributors.
* This file is part of Websocket PHP and is free software under the ISC License.
*/
namespace WebSocket\Runtime;
use Closure;
use Phrity\Net\{
Context,
SocketServer,
SocketStream,
StreamCollection,
StreamContainerInterface,
StreamException,
StreamFactory,
StreamInterface,
Uri
};
use WebSocket\{
Server,
};
use WebSocket\Exception\{
ExceptionInterface,
RunnerException,
};
/**
* WebSocket\Runtime\Runner class.
* Stream select runner.
* @phpstan-type Container object{
* container: StreamContainerInterface,
* stream: StreamInterface,
* onSelect: Closure
* }
*/
class Runner
{
private StreamFactory $streamFactory;
private StreamCollection $streamCollection;
/** @var array<string, Container> $containers */
private array $containers = [];
public function __construct(StreamFactory $streamFactory)
{
$this->streamFactory = $streamFactory;
$this->streamCollection = $this->streamFactory->createStreamCollection();
}
public function attach(StreamContainerInterface $streamContainer, Closure $onSelect, string $identity): void
{
if (array_key_exists($identity, $this->containers)) {
// On repeated identity, check if actually readable (detach if not)
if ($this->containers[$identity]->stream->isReadable()) {
throw new RunnerException("Stream container with identity {$identity} already attached");
}
$this->detach($identity);
}
$stream = $streamContainer->getStream();
$this->streamCollection->attach($stream, $identity);
$this->containers[$identity] = (object)[
'container' => $streamContainer,
'stream' => $stream,
'onSelect' => $onSelect,
];
}
public function detach(string $identity): void
{
if (array_key_exists($identity, $this->containers)) {
$this->streamCollection->detach($identity);
unset($this->containers[$identity]);
}
}
/**
* @throws ExceptionInterface
*/
public function handle(int|float $timeout): void
{
foreach ($this->select($timeout) as $identity => $stream) {
$container = $this->containers[$identity];
/** @throws ExceptionInterface */
call_user_func($container->onSelect, $this, $container->container);
}
}
public function select(int|float $timeout): StreamCollection
{
return $this->streamCollection->waitRead($timeout);
}
}