Skip to content

Commit bd90bfb

Browse files
committed
Improve documentation
1 parent 057c1c4 commit bd90bfb

File tree

2 files changed

+60
-8
lines changed

2 files changed

+60
-8
lines changed

README.md

Lines changed: 26 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,15 +2,37 @@
22

33
Custom coroutines implementation in GNU C.
44

5-
## Supported platforms
5+
## What is a Coroutine?
66

7-
- Linux x86_64
7+
<!-- This is almost an exact copy of "What is a Coroutine?" section from ./examples/counter.c, but it's slightly modified to make more since on the front README page of a GitHub Repo -->
88

9-
*More are planned in the future*
9+
Coroutine is a lightweight user space thread with its own stack that can suspend its execution and switch to another coroutine on demand. Coroutines do not run in parallel but rather cooperatively switch between each other whenever they feel like it.
10+
11+
Coroutines are useful in cases when all your program does majority of the time is waiting on IO. So with coroutines you have an opportunity to switch the context and go do something else. It is not useful to split up heavy CPU computations because they all going to be executed on a single thread. Use proper thread for that (pthreads on POSIX).
12+
13+
Good uses case for coroutines are usually Network Applications and UI. Anything with a slow Async IO.
1014

11-
## Quick Start
15+
<!-- End of the copy of the section -->
16+
17+
See [coroutine.h](./coroutine.h) for more info. See [./examples/counter.c](./examples/counter.c) for a simple usage example in C.
18+
19+
To build the example:
1220

1321
```console
1422
$ make
1523
$ ./build/counter
1624
```
25+
26+
There are actually much more examples in the [./examples/](./examples/) in a variety of languages. To build all of them do:
27+
28+
```console
29+
$ make examples
30+
```
31+
32+
Make sure you have all the corresponding compilers for the languages.
33+
34+
## Supported platforms
35+
36+
- Linux x86_64
37+
38+
*More are planned in the future*

coroutine.h

Lines changed: 34 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,30 @@
11
#ifndef COROUTINE_H_
22
#define COROUTINE_H_
33

4+
// # What is a Coroutine?
5+
//
6+
// Coroutine is a lightweight user space thread with its own stack that can
7+
// suspend its execution and switch to another coroutine (see coroutine_yield()
8+
// function). Coroutines do not run in parallel but rather cooperatively switch
9+
// between each other whenever they feel like it.
10+
//
11+
// Coroutines are useful in cases when all your program does majority of the
12+
// time is waiting on IO. So with coroutines you have an opportunity to do
13+
// coroutine_yield() and go do something else. It is not useful to split up
14+
// heavy CPU computations because they all going to be executed on a single
15+
// thread. Use proper thread for that (pthreads on POSIX).
16+
//
17+
// Good uses case for coroutines are usually Network Applications and UI.
18+
// Anything with a slow Async IO.
19+
//
20+
// # How does it work?
21+
//
22+
// Each coroutine has its own separate call stack. Every time a new coroutine is
23+
// created with coroutine_go() a new call stack is allocated in dynamic memory.
24+
// The library manages a global array of coroutine stacks and switches between
25+
// them (on x86_64 literally swaps out the value of the RSP register) on every
26+
// coroutine_yield(), coroutine_sleep_read(), or coroutine_sleep_write().
27+
428
#ifdef __cplusplus
529
extern "C" {
630
#endif // __cplusplus
@@ -18,7 +42,9 @@ void coroutine_init(void);
1842
// the memory, and killing all the currently running coroutines.
1943
void coroutine_finish(void);
2044

21-
// Switch to the next coroutine.
45+
// Switch to the next coroutine. The execution will continue starting from
46+
// coroutine_yield() (or any other flavor of it like coroutine_sleep_read() or
47+
// coroutine_sleep_write) call of another coroutine.
2248
void coroutine_yield(void);
2349

2450
// Create a new coroutine. This function does not automatically switch to the
@@ -31,19 +57,23 @@ void coroutine_go(void (*f)(void*), void *arg);
3157
size_t coroutine_id(void);
3258

3359
// How many coroutines are currently alive. Could be used by the main coroutine
34-
// to wait until all the "child" coroutines have died.
60+
// to wait until all the "child" coroutines have died. It may also continue from
61+
// the call of coroutine_sleep_read() and coroutine_sleep_write() if the
62+
// corresponding coroutine was woken up.
3563
size_t coroutine_alive(void);
3664

3765
// Put the current coroutine to sleep until the non-blocking socket `fd` has
3866
// avaliable data to read. Trying to read from fd after coroutine_sleep_read()
3967
// may still cause EAGAIN, if the coroutine was woken up by coroutine_wake_up
40-
// before the socket became available for reading.
68+
// before the socket became available for reading. You may treat this function
69+
// as a flavor of coroutine_yield().
4170
void coroutine_sleep_read(int fd);
4271

4372
// Put the current coroutine to sleep until the non-blocking socket `fd` is
4473
// ready to accept data to write. Trying to write to fd after
4574
// coroutine_sleep_write() may still cause EAGAIN, if the coroutine was woken up
46-
// by coroutine_wake_up before the socket became available for writing.
75+
// by coroutine_wake_up before the socket became available for writing. You may
76+
// treat this function as a flavor of coroutine_yield().
4777
void coroutine_sleep_write(int fd);
4878

4979
// Wake up coroutine by id if it is currently sleeping due to

0 commit comments

Comments
 (0)