Bearsampp 2026.7.11
Loading...
Searching...
No Matches
class.fibermoduleloader.php
Go to the documentation of this file.
1<?php
2/*
3 * Copyright (c) 2021-2024 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{
19 private static $fibers = [];
20 private static $enabled = false;
21
28 public static function init(): bool
29 {
30 self::$enabled = PHP_VERSION_ID >= 80100;
31
32 if (!self::$enabled) {
33 Log::warning('FiberModuleLoader unavailable (requires PHP 8.1+, using fallback async)');
34 }
35
36 return self::$enabled;
37 }
38
48 public static function loadInFiber(
49 string $module,
50 callable $loader,
51 int $timeout = 5000
52 ): bool {
53 if (!self::$enabled) {
54 // Fallback: load synchronously
55 call_user_func($loader);
56 return false;
57 }
58
59 // Create fiber for concurrent execution
60 $fiberModule = new FiberModule($module, $loader, $timeout);
61 self::$fibers[$module] = $fiberModule;
62
63 return true;
64 }
65
74 public static function waitForModule(string $module, int $timeout = 5000): bool
75 {
76 if (!isset(self::$fibers[$module])) {
77 return true; // Not loaded in fiber, must be ready
78 }
79
80 return self::$fibers[$module]->wait($timeout);
81 }
82
90 public static function waitAll(int $timeout = 5000): bool
91 {
92 if (!self::$enabled || empty(self::$fibers)) {
93 return true;
94 }
95
96 $start = microtime(true);
97 $maxWait = $timeout / 1000;
98
99 foreach (self::$fibers as $module => $fiber) {
100 $elapsed = microtime(true) - $start;
101 $remaining = max(100, ($maxWait - $elapsed) * 1000);
102
103 if (!$fiber->wait((int)$remaining)) {
104 Log::warning('Timeout waiting for module: ' . $module);
105 return false;
106 }
107 }
108
109 return true;
110 }
111
118 public static function isLoaded(string $module): bool
119 {
120 if (!isset(self::$fibers[$module])) {
121 return true; // Not in fiber system
122 }
123
124 return self::$fibers[$module]->isReady();
125 }
126
133 public static function isLoading(string $module): bool
134 {
135 if (!isset(self::$fibers[$module])) {
136 return false;
137 }
138
139 return !self::$fibers[$module]->isReady();
140 }
141
148 public static function getFiber(string $module): ?FiberModule
149 {
150 return self::$fibers[$module] ?? null;
151 }
152
158 public static function isAvailable(): bool
159 {
160 return self::$enabled;
161 }
162
168 public static function getLoadedModules(): array
169 {
170 return array_keys(self::$fibers);
171 }
172}
173
179{
180 private $fiber;
181 private $moduleName;
182 private $initialized = false;
183 private $result = null;
184 private $timeout;
185
186 public function __construct(string $moduleName, callable $loader, int $timeout = 5000)
187 {
188 $this->moduleName = $moduleName;
189 $this->timeout = $timeout;
190
191 // Create fiber (PHP 8.1+)
192 $this->fiber = new Fiber(function() use ($loader) {
193 try {
194 $this->result = call_user_func($loader);
195 $this->initialized = true;
196 } catch (Throwable $e) {
197 Log::error('Fiber error in ' . $this->moduleName . ': ' . $e->getMessage());
198 $this->initialized = true; // Mark as done even on error
199 }
200 });
201
202 // Start the fiber (begins execution until first yield)
203 try {
204 $this->fiber->start();
205 } catch (Throwable $e) {
206 Log::error('Failed to start fiber for ' . $this->moduleName . ': ' . $e->getMessage());
207 $this->initialized = true;
208 }
209 }
210
218 public function wait(int $timeout = 5000): bool
219 {
220 if ($this->initialized) {
221 return true;
222 }
223
224 $start = microtime(true);
225 $maxWait = $timeout / 1000;
226
227 while (!$this->initialized) {
228 // Try to resume the fiber if suspended
229 if ($this->fiber->isSuspended()) {
230 try {
231 $this->fiber->resume();
232 } catch (Throwable $e) {
233 Log::error('Fiber resume error: ' . $e->getMessage());
234 $this->initialized = true;
235 break;
236 }
237 }
238
239 // Check if fiber completed
240 if ($this->fiber->isTerminated()) {
241 $this->initialized = true;
242 break;
243 }
244
245 // Timeout check
246 if ((microtime(true) - $start) > $maxWait) {
247 Log::warning('Timeout waiting for module: ' . $this->moduleName);
248 return false;
249 }
250
251 // Prevent busy-waiting (yield to other operations)
252 usleep(1000);
253 }
254
255 return true;
256 }
257
263 public function isReady(): bool
264 {
265 return $this->initialized || $this->fiber->isTerminated();
266 }
267
273 public function isSuspended(): bool
274 {
275 return $this->fiber->isSuspended();
276 }
277
283 public function isTerminated(): bool
284 {
285 return $this->fiber->isTerminated();
286 }
287
293 public function getModuleName(): string
294 {
295 return $this->moduleName;
296 }
297
303 public function getResult()
304 {
305 return $this->result;
306 }
307}
__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(!defined("APPPREFIX")) define("APPPREFIX"