Bearsampp 2026.9.23
Loading...
Searching...
No Matches
class.fibermoduleloader.php
Go to the documentation of this file.
1<?php
2/*
3 * Copyright (c) 2021-2026 Bearsampp
4 * License: GNU General Public License version 3 or later; see LICENSE.txt
5 * Website: https://bearsampp.com
6 * Github: https://github.com/Bearsampp
7 */
8
18{
20 private static $fibers = [];
21
23 private static $enabled = false;
24
31 public static function init(): bool
32 {
33 self::$enabled = PHP_VERSION_ID >= 80100;
34
35 if (!self::$enabled) {
36 Log::warning('FiberModuleLoader unavailable (requires PHP 8.1+, using fallback async)');
37 }
38
39 return self::$enabled;
40 }
41
52 public static function loadInFiber(
53 string $module,
54 callable $loader,
55 int $timeout = 5000
56 ): bool {
57 if (!self::$enabled) {
58 // Fallback: load synchronously
59 call_user_func($loader);
60
61 return false;
62 }
63
64 // Create fiber for concurrent execution
65 $fiberModule = new FiberModule($module, $loader, $timeout);
66 self::$fibers[$module] = $fiberModule;
67
68 return true;
69 }
70
80 public static function waitForModule(string $module, int $timeout = 5000): bool
81 {
82 if (!isset(self::$fibers[$module])) {
83 return true; // Not loaded in fiber, must be ready
84 }
85
86 return self::$fibers[$module]->wait($timeout);
87 }
88
97 public static function waitAll(int $timeout = 5000): bool
98 {
99 if (!self::$enabled || empty(self::$fibers)) {
100 return true;
101 }
102
103 $start = microtime(true);
104 $maxWait = $timeout / 1000;
105
106 foreach (self::$fibers as $module => $fiber) {
107 $elapsed = microtime(true) - $start;
108 $remaining = max(100, ($maxWait - $elapsed) * 1000);
109
110 if (!$fiber->wait((int)$remaining)) {
111 Log::warning('Timeout waiting for module: ' . $module);
112
113 return false;
114 }
115 }
116
117 return true;
118 }
119
127 public static function isLoaded(string $module): bool
128 {
129 if (!isset(self::$fibers[$module])) {
130 return true; // Not in fiber system
131 }
132
133 return self::$fibers[$module]->isReady();
134 }
135
143 public static function isLoading(string $module): bool
144 {
145 if (!isset(self::$fibers[$module])) {
146 return false;
147 }
148
149 return !self::$fibers[$module]->isReady();
150 }
151
159 public static function getFiber(string $module): ?FiberModule
160 {
161 return self::$fibers[$module] ?? null;
162 }
163
169 public static function isAvailable(): bool
170 {
171 return self::$enabled;
172 }
173
179 public static function getLoadedModules(): array
180 {
181 return array_keys(self::$fibers);
182 }
183}
184
192{
194 private $fiber;
195
197 private $moduleName;
198
200 private $initialized = false;
201
203 private $result = null;
204
206 private $timeout;
207
217 public function __construct(string $moduleName, callable $loader, int $timeout = 5000)
218 {
219 $this->moduleName = $moduleName;
220 $this->timeout = $timeout;
221
222 // Create fiber (PHP 8.1+)
223 $this->fiber = new Fiber(function () use ($loader) {
224 try {
225 $this->result = call_user_func($loader);
226 $this->initialized = true;
227 } catch (Throwable $e) {
228 Log::error('Fiber error in ' . $this->moduleName . ': ' . $e->getMessage());
229 $this->initialized = true; // Mark as done even on error
230 }
231 });
232
233 // Start the fiber (begins execution until first yield)
234 try {
235 $this->fiber->start();
236 } catch (Throwable $e) {
237 Log::error('Failed to start fiber for ' . $this->moduleName . ': ' . $e->getMessage());
238 $this->initialized = true;
239 }
240 }
241
250 public function wait(int $timeout = 5000): bool
251 {
252 if ($this->initialized) {
253 return true;
254 }
255
256 $start = microtime(true);
257 $maxWait = $timeout / 1000;
258
259 while (!$this->initialized) {
260 // Try to resume the fiber if suspended
261 if ($this->fiber->isSuspended()) {
262 try {
263 $this->fiber->resume();
264 } catch (Throwable $e) {
265 Log::error('Fiber resume error: ' . $e->getMessage());
266 $this->initialized = true;
267 break;
268 }
269 }
270
271 // Check if fiber completed
272 if ($this->fiber->isTerminated()) {
273 $this->initialized = true;
274 break;
275 }
276
277 // Timeout check
278 if ((microtime(true) - $start) > $maxWait) {
279 Log::warning('Timeout waiting for module: ' . $this->moduleName);
280
281 return false;
282 }
283
284 // Prevent busy-waiting (yield to other operations)
285 usleep(1000);
286 }
287
288 return true;
289 }
290
296 public function isReady(): bool
297 {
298 return $this->initialized || $this->fiber->isTerminated();
299 }
300
306 public function isSuspended(): bool
307 {
308 return $this->fiber->isSuspended();
309 }
310
316 public function isTerminated(): bool
317 {
318 return $this->fiber->isTerminated();
319 }
320
326 public function getModuleName(): string
327 {
328 return $this->moduleName;
329 }
330
336 public function getResult()
337 {
338 return $this->result;
339 }
340}
__construct(string $moduleName, callable $loader, int $timeout=5000)
wait(int $timeout=5000)
static waitForModule(string $module, int $timeout=5000)
static getFiber(string $module)
static waitAll(int $timeout=5000)
static loadInFiber(string $module, callable $loader, int $timeout=5000)
static isLoading(string $module)
static isLoaded(string $module)
static warning($data, $file=null)
static error($data, $file=null)
if('@'. 'php_dir'.'@'=='@'. 'php_dir'.'@')
Definition helper.inc:2