Open main menu
Home
Random
Recent changes
Special pages
Community portal
Preferences
About Wikipedia
Disclaimers
Incubator escapee wiki
Search
User menu
Talk
Dark mode
Contributions
Create account
Log in
Editing
Coroutine
(section)
Warning:
You are not logged in. Your IP address will be publicly visible if you make any edits. If you
log in
or
create an account
, your edits will be attributed to your username, along with other benefits.
Anti-spam check. Do
not
fill this in!
===C=== In order to implement general-purpose coroutines, a second [[call stack]] must be obtained, which is a feature not directly supported by the [[C (programming language)|C]] language. A reliable (albeit platform-specific) way to achieve this is to use a small amount of [[inline assembly]] to explicitly manipulate the stack pointer during initial creation of the coroutine. This is the approach recommended by [[Tom Duff]] in a discussion on its relative merits vs. the method used by [[Protothreads]].<ref name="duff">{{Cite web| url=https://brainwagon.org/2005/03/05/coroutines-in-c/#comment-1878| title=Coroutines in C β brainwagon| date=5 March 2005| access-date=7 August 2018| archive-date=23 July 2019| archive-url=https://web.archive.org/web/20190723071827/https://brainwagon.org/2005/03/05/coroutines-in-c/#comment-1878| url-status=live}}</ref>{{Primary source inline|date=March 2022}} On platforms which provide the [[POSIX]] [[sigaltstack]] system call, a second call stack can be obtained by calling a springboard function from within a signal handler<ref name="rse-pmt">{{cite conference|url=https://www.gnu.org/software/pth/rse-pmt.ps|title=Portable Multithreading β The Signal Stack Trick For User-Space Thread Creation|format=PS|conference=USENIX Annual Technical Conference|date=18β23 June 2000|location=San Diego, USA|author=Ralf S. Engelschall|access-date=27 November 2017|archive-date=31 October 2019|archive-url=https://web.archive.org/web/20191031120105/http://www.gnu.org/software/pth/rse-pmt.ps|url-status=live}}</ref><ref name="libco">{{Cite web|url=https://code.byuu.org/libco|title=libco|website=code.byuu.org}}{{Dead link|date=March 2022 |bot=InternetArchiveBot |fix-attempted=yes }}</ref> to achieve the same goal in portable C, at the cost of some extra complexity. C libraries complying to [[POSIX]] or the [[Single Unix Specification]] (SUSv3) provided such routines as [[setcontext|getcontext, setcontext, makecontext and swapcontext]], but these functions were declared obsolete in POSIX 1.2008.<ref>{{Cite web|url=http://man7.org/linux/man-pages/man3/getcontext.3.html|title=getcontext(3) - Linux manual page|website=man7.org|access-date=2017-11-22|archive-date=2019-11-27|archive-url=https://web.archive.org/web/20191127031557/http://man7.org/linux/man-pages/man3/getcontext.3.html|url-status=live}}</ref> Once a second call stack has been obtained with one of the methods listed above, the [[setjmp/longjmp|setjmp and longjmp]] functions in the [[standard C library]] can then be used to implement the switches between coroutines. These functions save and restore, respectively, the [[stack pointer]], [[program counter]], callee-saved [[processor register|registers]], and any other internal state as required by the [[application binary interface|ABI]], such that returning to a coroutine after having yielded restores all the state that would be restored upon returning from a function call. Minimalist implementations, which do not piggyback off the setjmp and longjmp functions, may achieve the same result via a small block of [[inline assembly]] which swaps merely the stack pointer and program counter, and [[Clobbering#Assembly|clobbers]] all other registers. This can be significantly faster, as setjmp and longjmp must conservatively store all registers which may be in use according to the ABI, whereas the clobber method allows the compiler to store (by spilling to the stack) only what it knows is actually in use. Due to the lack of direct language support, many authors have written their own libraries for coroutines which hide the above details. Russ Cox's libtask library<ref name="libtask">http://swtch.com/libtask/ {{Webarchive|url=https://web.archive.org/web/20191115104620/http://swtch.com/libtask/ |date=2019-11-15 }} - Russ Cox's libtask coroutine library for FreeBSD, Linux, Mac OS X, and SunOS</ref> is a good example of this genre. It uses the context functions if they are provided by the native C library; otherwise it provides its own implementations for ARM, PowerPC, Sparc, and x86. Other notable implementations include libpcl,<ref>[http://xmailserver.org/libpcl.html ''Portable Coroutine Library''] {{Webarchive|url=https://web.archive.org/web/20051214201518/http://xmailserver.org/libpcl.html |date=2005-12-14 }} - C library using POSIX/SUSv3 facilities</ref> coro,<ref>http://www.goron.de/~froese/coro/ {{Webarchive|url=https://web.archive.org/web/20060110123338/http://www.goron.de/~froese/coro/ |date=2006-01-10 }} - Edgar Toernig's coro library for x86, Linux & FreeBSD</ref> lthread,<ref>https://github.com/halayli/lthread {{Webarchive|url=https://web.archive.org/web/20200613175536/https://github.com/halayli/lthread |date=2020-06-13 }} - lthread is a multicore/multithread coroutine library written in C</ref> libCoroutine,<ref>{{cite web|url=http://dekorte.com/projects/opensource/libcoroutine/|title=libcoroutine: A portable coroutine implementation|access-date=2013-09-06|archive-date=2019-11-12|archive-url=https://web.archive.org/web/20191112231845/http://dekorte.com/projects/opensource/libcoroutine/}} for FreeBSD, Linux, OS X PPC and x86, SunOS, Symbian and others</ref> libconcurrency,<ref>{{cite web|url=http://code.google.com/p/libconcurrency/libconcurrency|title=libconcurrency - A scalable concurrency library for C}} a simple C library for portable stack-switching coroutines</ref> libcoro,<ref>{{cite web|url=http://software.schmorp.de/pkg/libcoro.html|title=libcoro: C-library that implements coroutines (cooperative multitasking) in a portable fashion|access-date=2008-04-17|archive-date=2019-12-02|archive-url=https://web.archive.org/web/20191202064402/http://software.schmorp.de/pkg/libcoro.html|url-status=live}} used as the basis for the Coro perl module.</ref> ribs2,<ref>{{Cite web|url=https://github.com/aolarchive/ribs2|title=RIBS (Robust Infrastructure for Backend Systems) version 2: aolarchive/ribs2|date=August 13, 2019|via=GitHub|access-date=October 21, 2019|archive-date=April 22, 2020|archive-url=https://web.archive.org/web/20200422015941/https://github.com/aolarchive/ribs2|url-status=live}}</ref> libdill.,<ref>{{Cite web|url=http://libdill.org/|title=libdill|website=libdill.org|access-date=2019-10-21|archive-date=2019-12-02|archive-url=https://web.archive.org/web/20191202174632/http://libdill.org/}}</ref> libaco,<ref>{{Cite web|url=https://github.com/hnes/libaco|title=A blazing fast and lightweight C asymmetric coroutine library π β πβ π: hnes/libaco|date=October 21, 2019|via=GitHub|access-date=October 16, 2018|archive-date=November 29, 2018|archive-url=https://web.archive.org/web/20181129154044/https://github.com/hnes/libaco|url-status=live}}</ref> and libco.<ref name="libco" /> In addition to the general approach above, several attempts have been made to approximate coroutines in C with combinations of subroutines and macros. [[Simon Tatham]]'s contribution,<ref name="tatham">{{cite web|url=http://www.chiark.greenend.org.uk/~sgtatham/coroutines.html|author=Simon Tatham|title=Coroutines in C|year=2000|access-date=2003-09-19|archive-date=2019-11-09|archive-url=https://web.archive.org/web/20191109155253/https://www.chiark.greenend.org.uk/~sgtatham/coroutines.html|url-status=live}}</ref> based on [[Duff's device]], is a notable example of the genre, and is the basis for [[Protothread]]s and similar implementations.<ref>{{Cite web|url=https://github.com/jsseldenthuis/coroutine|title=Stackless coroutine implementation in C and C++: jsseldenthuis/coroutine|date=March 18, 2019|via=GitHub|access-date=March 18, 2019|archive-date=June 13, 2020|archive-url=https://web.archive.org/web/20200613175624/https://github.com/jsseldenthuis/coroutine|url-status=live}}</ref> In addition to Duff's objections,<ref name="duff" /> Tatham's own comments provide a frank evaluation of the limitations of this approach: "As far as I know, this is the worst piece of C hackery ever seen in serious production code."<ref name="tatham" /> The main shortcomings of this approximation are that, in not maintaining a separate stack frame for each coroutine, local variables are not preserved across yields from the function, it is not possible to have multiple entries to the function, and control can only be yielded from the top-level routine.<ref name="duff" />
Edit summary
(Briefly describe your changes)
By publishing changes, you agree to the
Terms of Use
, and you irrevocably agree to release your contribution under the
CC BY-SA 4.0 License
and the
GFDL
. You agree that a hyperlink or URL is sufficient attribution under the Creative Commons license.
Cancel
Editing help
(opens in new window)