Coroutine — bajarilishini ma’lum nuqtada to‘xtatib, holatini saqlagan holda keyin davom ettira oladigan dasturiy bajarilish birligi.
Oddiy funksiya chaqiriladi, natija qaytaradi va tugaydi. Coroutine esa yield, await yoki runtime mexanizmi orqali boshqaruvni vaqtincha qaytarib, keyinchalik ayni joydan davom etadi.
Coroutine asynchronous I/O, event loop, generator va cooperative multitaskingda qo‘llanadi.
Asosiy xususiyat
Coroutine to‘xtaganda quyidagi holat saqlanadi:
Qayta ishga tushirilganda funksiya boshidan emas, to‘xtagan nuqtadan davom etadi.
Stackful va stackless
Stackful coroutine
Har coroutine o‘z stackiga ega. Oddiy function calllar ichidan ham yield qilish mumkin.
Afzalligi — tabiiy control flow. Kamchiligi — stack xotirasi va context switching murakkabligi.
Stackless coroutine
Compiler yoki runtime holat mashinasiga aylantiradi.
async/await ko‘p tillarda stackless modelga yaqin.
Xotira sarfi kichik, lekin faqat belgilangan await nuqtalarida to‘xtaydi.
Generator
Generator coroutine’ning sodda ko‘rinishi.
Misol mantiqi:
yield 1
yield 2
yield 3
Har chaqirishda keyingi qiymat qaytadi.
Generator katta ma’lumotni bir yo‘la xotiraga yuklamasdan bosqichma-bosqich ishlab chiqishi mumkin.
Async va await
async funksiya coroutine yaratadi. await uzoq operatsiya tugashini kutib, event loopga boshqa vazifalarni bajarish imkonini beradi.
Masalan:
- HTTP so‘rov yuboriladi.
- Coroutine socket javobini kutishda to‘xtaydi.
- Event loop boshqa coroutinelarni ishlatadi.
- Javob kelganda oldingi coroutine davom etadi.
Bu kutish vaqtida threadni band qilmaslikka yordam beradi.
Cooperative scheduling
Coroutine o‘zi boshqaruvni qaytarmaguncha ishlaydi.
Bu cooperative scheduling hisoblanadi.
Afzalligi:
- context switch nuqtalari aniq;
- kernel thread switchdan yengil;
- umumiy state ustida kamroq tasodifiy preemption.
Kamchiligi — coroutine uzoq CPU ishida yield qilmasa, event loop bloklanadi.
Event loop
Event loop:
ni boshqaradi.
U I/O tayyorligi haqida operatsion tizimdan epoll, kqueue yoki boshqa mexanizm orqali xabar oladi.
Future va Promise
Future keyinchalik tayyor bo‘ladigan natijani ifodalaydi.
Coroutine future’ni await qiladi.
Natija:
- muvaffaqiyatli qiymat;
- exception;
- cancellation
bo‘lishi mumkin.
Promise ayrim tillarda natijani ishlab chiqaruvchi tomonni bildiradi.
Task
Runtime coroutine’ni schedule qilingan Taskga o‘raydi.
Task:
- holat;
- natija;
- exception;
- cancellation;
- callback
ni boshqaradi.
Coroutine obyektini yaratish uning avtomatik ishga tushganini har doim anglatmaydi.
Coroutine va thread
| Jihat | Coroutine | Thread |
|---|---|---|
| Scheduling | Odatda runtime | Kernel |
| Switch | Cooperative | Preemptive bo‘lishi mumkin |
| Xotira | Kichikroq | Stack kattaroq |
| Parallel CPU | O‘zi bilan emas | Ko‘p coreda mumkin |
| I/O concurrency | Juda qulay | Mumkin |
| Blocking call | Event loopni bloklaydi | Bitta threadni bloklaydi |
Coroutine threadlar ustida ishlaydi. Ular bir-birini inkor qilmaydi.
Blocking kod
Async funksiya ichida oddiy blocking disk yoki network chaqirig‘i ishlatilsa, event loop to‘xtaydi.
Yechimlar:
CPU-bound vazifa
Katta hisob coroutine uchun mos emas, chunki event loop boshqa vazifalarni bajara olmaydi.
CPU-bound ish:
ga beriladi.
Cancellation
Task bekor qilinganda coroutinega cancellation signali yoki exception beriladi.
Coroutine:
- file;
- lock;
- transaction;
- socket
ni finally yoki cleanup blokida yopishi kerak.
Cancellationni butunlay yutib yuborish shutdownni qiyinlashtiradi.
Timeout
Timeout coroutine’ni belgilangan muddatdan keyin bekor qiladi.
Timeout qo‘llanganda background operation haqiqatan to‘xtaganmi yoki faqat natijani kutish tugaganmi aniqlanadi.
Database yoki remote serverda amal davom etishi mumkin.
Structured concurrency
Child tasklar parent scope bilan boshqariladi.
Scope tugaganda barcha child task:
- tugagan;
- bekor qilingan;
- exceptioni qayta ishlangan
bo‘lishi kerak.
Bu orphan task va yashirin exceptionlarni kamaytiradi.
Race condition
Coroutine cooperative bo‘lsa ham race condition yuz berishi mumkin.
Coroutine umumiy state’ni o‘zgartirish orasida await qilsa, boshqa coroutine shu state’ga kiradi.
Async mutex, queue yoki immutable data ishlatiladi.
Backpressure
Producer coroutinesi consumerdan tez ishlasa, queue cheksiz o‘sishi mumkin.
Bounded queue producer’ni vaqtincha kutdiradi.
Bu backpressure xotira sarfini boshqaradi.
Debugging
Async stack oddiy call stackdan murakkabroq.
Vositalar:
Coroutine yaratilgan, ammo await qilinmagan bo‘lsa warning chiqishi mumkin.
Coroutine lifecycle
Coroutine quyidagi holatlarda bo‘lishi mumkin:
- yaratilgan;
- schedule qilingan;
- ishlayotgan;
- await holatida;
- tugagan;
- bekor qilingan;
- xato bilan tugagan.
Tugagan coroutine qayta boshlanmaydi. Yangi ish uchun yangi coroutine obyekt yaratiladi.
Context propagation
Tracing ID, user context va deadline asynchronous chaqiriqlar bo‘ylab uzatilishi kerak. Oddiy thread-local qiymat event loopda bir nechta request orasida aralashishi mumkin.
Async runtime context variable yoki task-local storage beradi. Worker threadga o‘tilganda contextni alohida ko‘chirish talab qilinishi mumkin.
Resource cleanup
Coroutine suspended holatda file yoki connectionni ushlab turishi mumkin. Scope tugaganda asynchronous context manager yoki finally bloki resursni bo‘shatadi. Aks holda connection pool asta-sekin tugaydi.
Bog‘liq tushunchalar
Async, Await, Event loop, Generator, Future, Task, Thread, Cooperative multitasking, Cancellation, Backpressure