Skip to content

Commit

Permalink
Fixed a bug in the dining_philosophers.c example. Some more docs upda…
Browse files Browse the repository at this point in the history
…tes.
  • Loading branch information
tylov committed Jan 7, 2025
1 parent 85877a3 commit 6b6e7bd
Show file tree
Hide file tree
Showing 4 changed files with 28 additions and 57 deletions.
17 changes: 9 additions & 8 deletions docs/coroutine_api.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ on the stack), which holds all variables used within their coroutine scopes. Thi
that they become extremely lightweight and therefore useful on severely memory constrained systems
like microcontrollers with limited resources.
- In stackful mode, the coroutine frames are allocated on the heap just before they await another
coroutine. Examples below.
coroutine. See examples.


## Methods and statements
Expand Down Expand Up @@ -204,27 +204,28 @@ int main(void) {
### Actor models of concurrency in video games and simulations
A common usage of coroutines is long-running concurrent tasks, often found in video games. An example of this is the
[Dining philosopher's problem](https://en.wikipedia.org/wiki/Dining_philosophers_problem). The following
implementation uses `cco_await*()` and `cco_yield`. It avoids deadlocks because it waits until both forks are
available before aquiring them. It also avoids starvation as the neighbor's hunger increases for each "round".
implementation uses `cco_await` and `cco_yield`. It avoids deadlocks by awaiting for both forks to be
available before aquiring them. It also avoids starvation by increasing both neighbor's hunger when a philosopher
starts eating (because they must be waiting).

<details>
<summary>The "Dining philosophers" C implementation</summary>

[ [Run this code](https://godbolt.org/z/WoaMv6js5) ]
[ [Run this code](https://godbolt.org/z/EK6zs6vbz) ]
```c++
#include <stdio.h>
#include <time.h>
#include "stc/random.h"
#include "stc/coroutine.h"
// Define the number of philosophers

enum {num_philosophers = 5};
enum {ph_thinking, ph_eating, ph_hungry};
enum PhState {ph_thinking, ph_hungry, ph_eating};

// Philosopher coroutine
struct Philosopher {
int id;
cco_timer tm;
int state;
enum PhState state;
int hunger;
struct Philosopher* left;
struct Philosopher* right;
Expand Down Expand Up @@ -272,7 +273,7 @@ int Dining(struct Dining* self) {
for (int i = 0; i < num_philosophers; ++i) {
cco_reset(&self->philos[i]);
self->philos[i].id = i + 1;
self->philos[i].left = &self->philos[i];
self->philos[i].left = &self->philos[(i - 1 + num_philosophers) % num_philosophers];
self->philos[i].right = &self->philos[(i + 1) % num_philosophers];
}

Expand Down
14 changes: 0 additions & 14 deletions docs/hset_api.md
Original file line number Diff line number Diff line change
Expand Up @@ -117,17 +117,3 @@ int main(void)
c_drop(Strings, &first, &second, &third, &fourth, &fifth);
}
```
Output:
```
fifth contains:
red
green
flour
orange
blue
pink
yellow
milk
potatoes
```
47 changes: 16 additions & 31 deletions docs/smap_api.md
Original file line number Diff line number Diff line change
Expand Up @@ -117,6 +117,8 @@ void smap_X_value_drop(i_key* pval);
| `smap_X_iter` | `struct { smap_X_value *ref; ... }` | Iterator type |
## Examples
[ [Run this code](https://godbolt.org/z/qs1Gsv5zh) ]
```c++
#include "stc/cstr.h"
Expand Down Expand Up @@ -149,15 +151,6 @@ int main(void)
smap_cstr_drop(&colors);
}
```
Output:
```
Key:[BLUE] Value:[#0000FF]
Key:[GREEN] Value:[#00FF00]
Key:[RED] Value:[#FF0000]
The HEX of color RED is:[#FF0000]
The HEX of color BLACK is:[#000000]
```


### Example 2
Translate a
Expand Down Expand Up @@ -196,44 +189,44 @@ int main(void)
```
### Example 3
This example uses a smap with cstr as mapped value.
This example uses a smap with cstr as mapped value. Note the `i_valpro` usage.
[ [Run this code](https://godbolt.org/z/M397fG7fM) ]
```c++
#include "stc/cstr.h"
#define i_type IDSMap, int
#define i_type IdMap
#define i_key int
#define i_valpro cstr
#include "stc/smap.h"
int main(void)
{
uint32_t col = 0xcc7744ff;
IDSMap idnames = c_make(IDSMap, {{100, "Red"}, {110, "Blue"}});
IdMap idnames = c_make(IdMap, {{100, "Red"}, {110, "Blue"}});
// Assign/overwrite an existing mapped value with a const char*
IDSMap_emplace_or_assign(&idnames, 110, "White");
IdMap_emplace_or_assign(&idnames, 110, "White");
// Insert (or assign) a new cstr
IDSMap_insert_or_assign(&idnames, 120, cstr_from_fmt("#%08x", col));
IdMap_insert_or_assign(&idnames, 120, cstr_from_fmt("#%08x", col));
// emplace() adds only when key does not already exist:
IDSMap_emplace(&idnames, 100, "Green"); // ignored
IdMap_emplace(&idnames, 100, "Green"); // ignored
c_foreach (i, IDSMap, idnames)
c_foreach (i, IdMap, idnames)
printf("%d: %s\n", i.ref->first, cstr_str(&i.ref->second));
IDSMap_drop(&idnames);
IdMap_drop(&idnames);
}
```
Output:
```c++
100: Red
110: White
120: #cc7744ff
```

### Example 4
Demonstrate smap with plain-old-data key type Vec3i and int as mapped type: smap<Vec3i, int>.

[ [Run this code](https://godbolt.org/z/KE8qEYsvY) ]
```c++
#include <stdio.h>
typedef struct { int x, y, z; } Vec3i;

static int Vec3i_cmp(const Vec3i* a, const Vec3i* b) {
Expand All @@ -246,7 +239,6 @@ static int Vec3i_cmp(const Vec3i* a, const Vec3i* b) {
#define i_type smap_vi, Vec3i, int
#define i_cmp Vec3i_cmp
#include "stc/smap.h"
#include <stdio.h>

int main(void)
{
Expand All @@ -263,10 +255,3 @@ int main(void)
smap_vi_drop(&vmap);
}
```
Output:
```c++
{ 0, 0, 100 }: 3
{ 0, 100, 0 }: 2
{ 100, 0, 0 }: 1
{ 100, 100, 100 }: 4
```
7 changes: 3 additions & 4 deletions examples/coroutines/dining_philosophers.c
Original file line number Diff line number Diff line change
Expand Up @@ -4,15 +4,14 @@
#include "stc/random.h"
#include "stc/coroutine.h"

// Define the number of philosophers
enum {num_philosophers = 5};
enum {ph_thinking, ph_hungry, ph_eating};
enum PhState {ph_thinking, ph_hungry, ph_eating};

// Philosopher coroutine
struct Philosopher {
int id;
cco_timer tm;
int state;
enum PhState state;
int hunger;
struct Philosopher* left;
struct Philosopher* right;
Expand Down Expand Up @@ -60,7 +59,7 @@ int Dining(struct Dining* self) {
for (int i = 0; i < num_philosophers; ++i) {
cco_reset(&self->philos[i]);
self->philos[i].id = i + 1;
self->philos[i].left = &self->philos[i];
self->philos[i].left = &self->philos[(i - 1 + num_philosophers) % num_philosophers];
self->philos[i].right = &self->philos[(i + 1) % num_philosophers];
}

Expand Down

0 comments on commit 6b6e7bd

Please sign in to comment.