کوروتین تو PHP: از Generator تا Fiber
خلاصهٔ کاملتر
نویسنده تو این مقاله سراغ مفهومی میره که همیشه کنار بحث کد ناهمگام و non-blocking شنیده میشه ولی کمتر تعریف دقیقی ازش داده میشه: کوروتین. تعریف سادهش اینه که یه تابع معمولی از بالا تا پایین یهنفس اجرا میشه، ولی کوروتین میتونه وسط کار خودش رو معلق کنه، کنترل رو به بقیهٔ کد بده و بعداً از همون نقطه ادامه بده.
سه ویژگی این رفتار رو میسازه: کوروتین فقط از داخل خودش میتونه معلق شه (کسی از بیرون نمیتونه مجبورش کنه) و از بیرون هم باید بهش دستور ادامه داده شه؛ میتونه موقع معلقشدن یه مقدار برگردونه و موقع ادامه یه مقدار بگیره، یعنی دوطرفهست؛ و تا وقتی تموم نشده، متغیرهای داخلیش تو حافظه میمونن. نویسنده اضافه میکنه که کوروتینها یا نامتقارنن (فقط به فراخوان برمیگردونن) یا متقارن (خودشون انتخاب میکنن کنترل دست کی بیفته)، و یا بدونپشتهن (فقط از بیرونیترین تابع) یا پشتهدار (حتی از دل توابع تودرتو).
اولین پیادهسازی PHP از این ایده Generator بود تو نسخهٔ 5.5. اکثر برنامهنویسها Generator رو فقط بهعنوان یه iterator کممصرف میشناسن، ولی yield دقیقاً همون مکانیزم توقف و ادامهست: current() اجرای اولیه رو شروع میکنه، next() ادامه میده، send() هم ادامه میده هم مقدار میفرسته، و throw() استثنا رو سر جای yield پرت میکنه تو دل کوروتین.
function coroutine(): Generator {
$received = yield 'Hello from the Coroutine';
yield "Received: " . $received;
}اما Generator نه متقارنه نه پشتهدار. متقارن نیست چون چیزی مثل yield to وجود نداره و نمیتونه کنترل رو به یه کوروتین دیگه بسپاره؛ پشتهدار هم نیست چون اگه yield رو داخل یه تابع تودرتو بنویسی، اون تابع خودش تبدیل به Generator میشه و والد رو معلق نمیکنه.
اینجاست که Fiber تو PHP 8.1 وارد میشه: همون مثال بالا با Fiber نوشته میشه، ولی این بار کوروتین پشتهٔ فراخوانی مستقل خودش رو داره و میتونه از هر عمقی معلق شه. نویسنده توضیح میده چرا Fiber::suspend() استاتیکه ولی resume() نه: توابع تودرتو به $this نمونهٔ در حال اجرا دسترسی ندارن، ولی خود Fiber از روی پشتهش میفهمه کدوم نمونه رو باید معلق کنه؛ و چون کوروتین نمیتونه خودش رو ادامه بده، resume() باید از بیرون و روی نمونه صدا زده شه.
$coroutine = new Fiber(function () {
$received = Fiber::suspend('Hello from the Coroutine');
Fiber::suspend('Received: ' . $received);
});نکات کلیدی:
- کوروتین تابعیه که خودش رو معلق میکنه، مقدار میده و میگیره، و وضعیتش رو نگه میداره
- تفکیک متقارن/نامتقارن یعنی کنترل به کی برمیگرده؛ پشتهدار/بدونپشته یعنی از کجا میشه معلق شد
- Generator از PHP 5.5: کوروتین نامتقارن و بدونپشته، با current، next، send و throw
- Fiber از PHP 8.1: پشتهٔ مستقل داره، پس از دل توابع تودرتو هم میشه معلقش کرد
- Fiber::suspend() استاتیکه چون از روی پشته نزدیکترین نمونه رو پیدا میکنه، ولی resume() باید از بیرون صدا زده شه




