Кіріспе
Компьютерлік бағдарламалық компонент
Корутиндер – компьютерлік бағдарлама компоненттері, олар орындалуды тоқтатуға және қайта бастауға мүмкіндік береді, кооперативтік көп тапсырмалылық үшін қосалқы бағдарламаларды ұзартады. Корутиндер кооперативтік тапсырмалар, ерекше жағдайлар, оқиға тізбектері, итераторлар, шексіз тізімдер және арналар сияқты таныс бағдарлама компоненттерін жүзеге асыруға өте ыңғайлы. Олар "орындалуын тоқтата алатын функциялар" деп сипатталған. Мелвин Конвей 1958 жылы корутин терминін енгізді, оны жиналым бағдарламасын құрастыруға қолданды. Корутиннің екі кеңінен танылған негізгі ерекшелігі:
корутинге жергілікті деректердің мәндері тізбектеп шақырылғанда сақталады;
корутиннің орындалуы басқару оны тастағанда тоқтатылады, ал басқару кейінірек корутинге кіргенде тоқтаған жерінен жалғасады. Бұдан басқа, корутинді жүзеге асырудың 3 ерекшелігі бар:
the execution of a coroutine is suspended as control leaves it, only to carry on where it left off when control re enters the coroutine at some later stage. Besides that, a coroutine implementation has 3 features:
басқару беру механизмі. Асимметриялық корутиндер әдетте yield және resume сияқты кілт сөздерді ұсынады. Бағдарламашылар қай фреймге басқаруды беруді еркін таңдай алмайды. Орындалу ортасы тек ағымдағы корутиннің ең жақын шақырушысына басқарады. Екінші жағынан, симметриялық корутиндерде бағдарламашылар өнімділік бағытын нақты көрсетуі керек. Корутиндер тілде бірінші сыныпты объектілер ретінде ұсынылған, оларды бағдарламашы еркін манипуляциялай алады немесе шектеулі конструкциялар ретінде;
корутин ішкі функция шақыруларынан орындалуын тоқтата ала ма. Мұндай корутин – үйірмелі корутин. Керісінше, үйірмелі емес корутиндер бар, онда егер функция корутин ретінде белгіленбесе, yield кілт сөзін пайдалана алмайды. 2009 жылы жарияланған «Корутиндерді қайта қарау» еңбегі бірінші сыныпты корутинды қолдайтын және үйірмелі болатын толық корутин терминін ұсынды. Толық корутиндер өз атына лайық, өйткені олар бір реттік жалғаулар мен шектелген жалғаулар сияқты көркемдік қуатқа ие. Толық корутиндер симметриялық немесе асимметриялық болуы мүмкін. Маңыздысы, корутин симметриялық немесе асимметриялық болғанымен, оның көркемдік қуатына ешқандай әсер етпейді, өйткені олар бірдей көркемдік қуатқа ие, бірақ толық корутиндер толық емес корутиндерге қарағанда көркемдік қуат жағынан артықшылыққа ие. Олардың көркемдік қуаты бірдей болғанымен, асимметриялық корутиндер басқаруды үнемі шақырушыға қайтаратындықтан, бағдарламашыларға көбірек таныс болатындықтан, процедуралық басқару құрылымдарына жақын.
whether a coroutine is able to suspend its execution from within nested function calls. Such a coroutine is a stackful coroutine. One to the contrary is called stackless coroutines, where unless marked as coroutine, a regular function can't use the keyword yield. Revisiting Coroutines published in 2009 proposed term full coroutine to denote one that supports first class coroutine and is stackful. Full Coroutines deserve their own name in that they have the same expressive power as one shot continuations and delimited continuations. Full coroutines are either symmetric or asymmetric. Importantly, whether a coroutine is symmetric or asymmetric has no bearing on how expressive it can be as they are equally as expressive, though full coroutines are more expressive than non full coroutines. While their expressive power is the same, asymmetrical coroutines more closely resemble routine based control structures in the sense that control is always passed back to the invoker, which programmers may find more familiar.
Қолданылу
2003 жылдан бастап көптеген танымал бағдарламалау тілдері, C және оның туындылары сияқты, тілдің өзінде немесе стандартты кітапханаларында корутиналарды қолдауға ие емес. Бұл, көбінесе, стекке негізделген қосалқы бағдарламаларды жүзеге асырудың шектеулеріне байланысты. Бір ерекшелік – C++ кітапханасы Boost.Context, Boost кітапханаларының бір бөлігі, ол ARM, MIPS, PowerPC, SPARC және x86 процессорларында POSIX, Mac OS X және Windows жүйелерінде контекст алмасуды қолдайды. Корутиналарды Boost.Context негізінде құруға болады. Корутина механизмді іске асырудың табиғи жолы болған жағдайларда, бірақ ол қол жетімді болмаса, әдеттегі шешім – жай-күйді сақтау үшін жай-күй айнымалыларымен (әдетте, статикалық айнымалылар, көбінесе логикалық флагтар) жабылу (closure) қосалқы бағдарламасын пайдалану және басқаруды дұрыс нүктеге беру болып табылады. Кодтағы шартты операторлар, жай-күй айнымалыларының мәніне байланысты, кезекті шақыруларда әртүрлі код бөлімдерін орындауға мүмкіндік береді. Тағы бір кең таралған шешім – үлкен және күрделі `switch` операторын немесе, әсіресе, есептелген `goto` операторын пайдаланып, нақты жай-күй машинасының моделін жүзеге асыру. Мұндай жүзеге асыруларды түсіну және қолдау қиын деп есептеледі, және корутиналарды қолдауға ынталандырады. Жіптер (threads), және аз дәрежеде талшықтар (fibers), бүгінгі таңдағы бағдарламалау орталарында корутиналарға балама болып табылады. Жіптер кодты бір уақытта орындалатын бөліктердің өзара әрекеттесуін басқаруға мүмкіндік береді. Жіптер C тілін қолдайтын орталарда кеңінен қолжетімді (және көптеген басқа заманауи тілдерде де туылған), көптеген бағдарламашыларға таныс және әдетте жақсы жүзеге асырылған, жақсы құжатталған және жақсы қолдау көрсетіледі. Дегенмен, олар үлкен және күрделі мәселені шешетіндіктен, көптеген қуатты және күрделі мүмкіндіктерді қамтиды және оған сәйкес оқу қисынымен келеді. Сондықтан, егер корутина ғана қажет болса, жіпті пайдалану артық болуы мүмкін. Жіптер мен корутиналардың арасындағы маңызды айырмашылық – жіптер әдетте алдын ала жоспарланады, ал корутиналар жоспарланбайды. Жіптер кез келген сәтте қайта жоспарлануы мүмкін және бір уақытта орындалуы мүмкін болғандықтан, жіптерді пайдаланатын бағдарламалар құлыптау туралы сақ болуы керек. Керісінше, корутиналар бағдарламаның белгілі бір нүктелерінде ғана қайта жоспарлануы мүмкін және бір уақытта орындалмайды, сондықтан корутиналарды пайдаланатын бағдарламалар көбінесе құлыптаудан толығымен аулақ бола алады. Бұл қасиет оқиғаға негізделген немесе асинхронды бағдарламалаудың артықшылығы ретінде де аталады. Талшықтар өзара жұмыс істейтіндіктен, олар корутиналарды жүзеге асыру үшін өте қолайлы негіз болып табылады. Дегенмен, талшықтарды жүйелік деңгейде қолдау, жіптерге қарағанда көбінесе нашар болады.
С#
C# 2.0 итератор үлгісі және yield кілт сөзі арқылы жартылай coroutine (генератор) функционалдығын қосты. C# 5.0 await синтаксисін қолдайды. Сонымен қатар:
MindTouch Dream REST фреймворкі C# 2.0 итератор үлгісіне негізделген coroutine-дерді іске асыруды қамтамасыз етеді. WPF үшін Caliburn экран үлгілері фреймворкі пайдаланушы интерфейсін бағдарламалауды жеңілдету үшін, әсіресе асинхронды сценарийлерде C# 2.0 итераторларын пайдаланады. Джеффри Рихтердің Power Threading Library бағдарламасында итераторларға негізделген coroutine-дерді пайдалану арқылы жеңілдетілген асинхронды бағдарламалау моделін ұсынатын AsyncEnumerator іске асырылған. Unity ойын қозғалтқышы coroutine-дерді іске асырады. Евген Бобровтың Servelat Pieces жобасы Silverlight WCF қызметтері үшін мөлдір асинхрондықты және кез келген синхронды әдісті асинхронды түрде шақыру мүмкіндігін қамтамасыз етеді. Іске асырылу Caliburn-нің Coroutine итераторы мен C# итератор блоктарына негізделген. StreamThreads – итераторлық кеңейту әдістеріне негізделген, ашық кодты, жеңіл салмақты C# coroutine кітапханасы. Ол қателерді өңдеу және нәтижелерді қайтаруды қолдайды.
Клозур
Cloroutine — Clojure-те тірегі жоқ корутиналарды қолдауды қамтамасыз ететін үшінші тарап кітапханасы. Ол макрос ретінде жүзеге асырылған, кез келген код блогын кез келген айнымалы шақырулары бойынша статикалық түрде бөліп, корутинаны күйлі функция ретінде шығарады.
D
D тілі coroutines-ті стандартты кітапхана класы Fiber ретінде іске асырады. Генератор талшық функциясын енгізу диапазоны ретінде көрсетуді оңайлатып, кез келген талшықты қолданыстағы диапазон алгоритмдерімен үйлесімді етеді.
Жүре беріңіз
Go-да "goroutines" деген ұғым бар, олар Go орындалу ортасымен басқарылатын жеңіл, тәуелсіз процестер. Жаңа goroutine-ды "go" кілт сөзін пайдаланып іске қосуға болады. Әрбір goroutine-ның қажеттілікке қарай кеңейтілетін өзгермелі көлемді стегі болады. Goroutine-дар көбінесе Go-дағы каналдар арқылы байланысады.
Жава
Java-да корутиндерді іске асырудың бірнеше тәсілі бар. Java абстракцияларының шектеулеріне қарамастан, JVM мұндай мүмкіндікті жоққа шығармайды. Қолданылатын негізгі әдістердің төртеуі бар, бірақ олардың екеуі стандартқа сай JVM-дер арасында байт-кодтың үйлесімділігін бұзады. Өзгертілген JVM. Корутиндерді тікелей қолдау үшін түзетілген JVM құруға болады. Da Vinci JVM-де түзетулер жасалған. Өзгертілген байт-код. Java байт-кодын қайта жазу арқылы, компиляция кезінде немесе орындалу барысында, корутин функционалдығын іске асыруға болады. Javaflow, Java Coroutines және Coroutines сияқты құралдар жиынтығы бар. Платформаға қатысты JNI механизмдері. Бұл механизмдер JVM-ге функционалдық мүмкіндіктерді беру үшін операциялық жүйе немесе C кітапханаларында іске асырылған JNI әдістерін пайдаланады. Жіптік абстракциялар. Жіптерді пайдалана отырып іске асырылған корутин кітапханалары ауыр болуы мүмкін, бірақ өнімділік JVM-нің жіптік іске асыруына байланысты өзгереді.
Котлин
Kotlin коррутиналарды бірінші тараптан шыққан кітапхананың құрамында іске асырады.
Луа
Lua стандартты кітапханасындағы coroutine модулі 5.0 (2003) нұсқасынан бері бірінші деңгейдегі үйілген асимметриялық корутиналарды қолдайды.
Модуль-2
Вирт анықтаған Modula 2 стандартты SYSTEM кітапханасының құрамындағы coroutines-ты іске асырады. NEWPROCESS процедурасы код блогы мен стекке арналған орынды параметрлер ретінде алып, контексті толтырады, ал TRANSFER процедурасы coroutine-ның контекстін параметр ретінде алып, басқаруды coroutine-ға жүктейді.
Моно
Mono Common Language Runtime жалғастыруларды қолдайды, олардың негізінде корутиналар құруға болады.
.NET Framework-тің нұсқасы
NET Framework 2.0 әзірлеу барысында Microsoft жалпы тілдік орындалу ортасының (CLR) хостинг API-ін кеңейтіп, SQL сервері үшін талшықты режимде қолдануды ескере отырып, талшықтар негізіндегі жоспарлауды қолдауға мүмкіндік берді. Жариялауға дейін, ICLRTask::SwitchOut тапсырма ауыстыру құралының қолдауы уақыт шектеулеріне байланысты алынып тасталды. Осының салдарынан, тапсырмаларды ауыстыру үшін талшықты API-ді пайдалану қазіргі уақытта NET Framework-те мүмкін емес.
ОКамл
OCaml өзінің Thread модулі арқылы корутиналарды қолдайды. Бұл корутиналар параллелизмсіз бірмезгілікті ұсынады және бір операциялық жүйе желісінде үзіліспен жоспарланады. OCaml 5.0 нұсқасынан бастап, жасыл желілер де қолжетімді; олар басқа модульдермен қамтамасыз етіледі.
Ракета
Racket жергілікті жалғастыруларды ұсынады, ал ресми пакет каталогында coroutines-тің қарапайым іске асырылуы бар. Іске асырушы: С. Де Габриэль.
Схема
Схема толыққанды жалғастыруларды қолдайтындықтан, корутиналарды іске асыру өте оңай, жалғастырулардың кезекін ұстап тұруды ғана қажет етеді.
Кішкене әңгіме
Smalltalk орталарының көпшілігінде орындалу стегі бірінші дәрежелі ұғым болып саналатындықтан, корутиналарды қосымша кітапханалар немесе VM қолдауысыз жүзеге асыруға болады.
Құрал командалар тілі (Tcl)
8.6 нұсқасынан бастап Tool Command Language тілінің өзінде корутиналар қолдауға ие.
Вала
Вала корутиналарға толыққанды қолдауды жүзеге асырады. Олар Gtk Main Loop-пен бірге қолдану үшін жасалған, бірақ егер соңғы кері шақыруды кем дегенде бір рет yield жасамай тұрып шақыру қажет болмайтынына көз жеткізілсе, дербес қолдануға да болады.
Ассамблея тілдері
Машинаға тәуелді ассемблер тілдері көбінесе корутинаны орындау үшін тікелей әдістер ұсынады. Мысалы, PDP 11 миникомпьютерлер отбасының ассемблер тіліндегі MACRO 11 жүйесінде "классикалық" корутина ауыстыруы "JSR PC,@(SP)+ " нұсқауы арқылы жүзеге асырылады, ол стекден алынған мекен-жайға секіріп өтеді және ағымдағы (яғни келесі) нұсқау мекен-жайын стекке салады. VAX жүйелерінде (VAX MACRO-да) осыған ұқсас нұсқау "JSB @(SP)+ " болып табылады. Тіпті Motorola 6809 процессорында "JSR [,S++] " нұсқауы бар; "++" белгісіне назар аударыңыз, себебі стекен 2 байт (мекен-жай) алынады. Бұл нұсқау (стандартты) "монитор" Assist 09-да кеңінен қолданылады.