From f69fb08603aca020e8d855b0469809982bb67322 Mon Sep 17 00:00:00 2001 From: Tyge Løvset Date: Tue, 11 Jan 2022 21:41:21 +0100 Subject: Fix / simplified unistd.h and renamed some examples that uses arc. (atomic ref. count / shared_ptr) --- examples/arc_containers.c | 75 +++++++++++++++++++++++++++++++++++++++++++++++ examples/arc_demo.c | 56 +++++++++++++++++++++++++++++++++++ examples/arcvec_erase.c | 53 +++++++++++++++++++++++++++++++++ examples/music_arc.c | 58 ++++++++++++++++++++++++++++++++++++ examples/person_arc.c | 67 ++++++++++++++++++++++++++++++++++++++++++ examples/sptr.c | 67 ------------------------------------------ examples/sptr_demo.c | 56 ----------------------------------- examples/sptr_erase.c | 53 --------------------------------- examples/sptr_music.c | 58 ------------------------------------ examples/sptr_threads.c | 62 --------------------------------------- examples/sptr_to_maps.c | 75 ----------------------------------------------- examples/threads_demo.c | 62 +++++++++++++++++++++++++++++++++++++++ 12 files changed, 371 insertions(+), 371 deletions(-) create mode 100644 examples/arc_containers.c create mode 100644 examples/arc_demo.c create mode 100644 examples/arcvec_erase.c create mode 100644 examples/music_arc.c create mode 100644 examples/person_arc.c delete mode 100644 examples/sptr.c delete mode 100644 examples/sptr_demo.c delete mode 100644 examples/sptr_erase.c delete mode 100644 examples/sptr_music.c delete mode 100644 examples/sptr_threads.c delete mode 100644 examples/sptr_to_maps.c create mode 100644 examples/threads_demo.c (limited to 'examples') diff --git a/examples/arc_containers.c b/examples/arc_containers.c new file mode 100644 index 00000000..0873d297 --- /dev/null +++ b/examples/arc_containers.c @@ -0,0 +1,75 @@ +// Create a stack and a list of shared pointers to maps, +// and demonstrate sharing and cloning of maps. +#define i_type Map +#define i_key_str // strings +#define i_val int +#define i_keydrop(p) (printf("drop name: %s\n", (p)->str), cstr_drop(p)) +#include + +#define i_type Arc // (atomic) ref. counted type +#define i_val Map +#define i_drop(p) (printf("drop Arc:\n"), Map_drop(p)) +// no need for atomic ref. count in single thread: +// no compare function available for csmap: +#define i_opt c_no_atomic|c_no_cmp +#include + +#define i_type Stack +#define i_val_sptr Arc // define i_val_bind for carc/cbox value (not i_val) +#include + +#define i_type List +#define i_val_sptr Arc // as above +#include + +int main() +{ + c_auto (Stack, stack) + c_auto (List, list) + { + // POPULATE stack with shared pointers to Maps: + Map *map; + map = Stack_push(&stack, Arc_from(Map_init()))->get; + c_apply(v, Map_emplace(map, c_pair(v)), Map_raw, { + {"Joey", 1990}, {"Mary", 1995}, {"Joanna", 1992} + }); + map = Stack_push(&stack, Arc_from(Map_init()))->get; + c_apply(v, Map_emplace(map, c_pair(v)), Map_raw, { + {"Rosanna", 2001}, {"Brad", 1999}, {"Jack", 1980} + }); + + // POPULATE list: + map = List_push_back(&list, Arc_from(Map_init()))->get; + c_apply(v, Map_emplace(map, c_pair(v)), Map_raw, { + {"Steve", 1979}, {"Rick", 1974}, {"Tracy", 2003} + }); + + // Share two Maps from the stack with the list using emplace (clone the carc): + List_push_back(&list, Arc_clone(stack.data[0])); + List_push_back(&list, Arc_clone(stack.data[1])); + + // Clone (deep copy) a Map from the stack to the list + // List will contain two shared and two unshared maps. + map = List_push_back(&list, Arc_from(Map_clone(*stack.data[1].get)))->get; + + // Add one more element to the cloned map: + Map_emplace_or_assign(map, "CLONED", 2021); + + // Add one more element to the shared map: + Map_emplace_or_assign(stack.data[1].get, "SHARED", 2021); + + + puts("STACKS"); + c_foreach (i, Stack, stack) { + c_forpair (name, year, Map, *i.ref->get) + printf(" %s:%d", _.name.str, _.year); + puts(""); + } + puts("LIST"); + c_foreach (i, List, list) { + c_forpair (name, year, Map, *i.ref->get) + printf(" %s:%d", _.name.str, _.year); + puts(""); + } + } +} diff --git a/examples/arc_demo.c b/examples/arc_demo.c new file mode 100644 index 00000000..8626e2d4 --- /dev/null +++ b/examples/arc_demo.c @@ -0,0 +1,56 @@ +#include +#include + +void int_drop(int* x) { + printf("drop: %d\n", *x); +} + +// carc implements its own clone method using reference counting, +// so 'i_valfrom' need not be defined (will be ignored). + +#define i_type iref // set type name to be defined (instead of 'carc_int') +#define i_val int +#define i_drop int_drop // optional, just to display the elements destroyed +#include // iref + +#define i_key_sptr iref // note: use i_key_bind instead of i_key for carc/cbox elements +#include // csset_iref (like: std::set>) + +#define i_val_sptr iref // note: as above. +#include // cvec_iref (like: std::vector>) + +int main() +{ + c_auto (cvec_iref, vec) // declare and init vec, call cvec_iref_drop() at scope exit + c_auto (csset_iref, set) // declare and init set, call csset_iref_drop() at scope exit + { + const int years[] = {2021, 2012, 2022, 2015}; + c_forrange (i, c_arraylen(years)) + cvec_iref_push_back(&vec, iref_from(years[i])); + + printf("vec:"); + c_foreach (i, cvec_iref, vec) printf(" %d", *i.ref->get); + puts(""); + + // add odd numbers from vec to set + c_foreach (i, cvec_iref, vec) + if (*i.ref->get & 1) + csset_iref_insert(&set, iref_clone(*i.ref)); // copy shared pointer => increments counter. + + // erase the two last elements in vec + cvec_iref_pop_back(&vec); + cvec_iref_pop_back(&vec); + + printf("vec:"); + c_foreach (i, cvec_iref, vec) printf(" %d", *i.ref->get); + + printf("\nset:"); + c_foreach (i, csset_iref, set) printf(" %d", *i.ref->get); + + c_autovar (iref p = iref_clone(vec.data[0]), iref_drop(&p)) { + printf("\n%d is now owned by %ld objects\n", *p.get, *p.use_count); + } + + puts("\nDone"); + } +} diff --git a/examples/arcvec_erase.c b/examples/arcvec_erase.c new file mode 100644 index 00000000..d40d8fe7 --- /dev/null +++ b/examples/arcvec_erase.c @@ -0,0 +1,53 @@ +#include + +void show_drop(int* x) { printf("drop: %d\n", *x); } + +#define i_type Arc +#define i_val int +#define i_drop show_drop +// carc/cbox will use pointer address comparison of i_val +// if 'i_opt c_no_cmp' is defined, otherwise i_cmp is used +// to compare object values. See the two differences by +// commenting out the next line. +#include // Shared pointer to int + +#define i_type Vec +#define i_val_sptr Arc +#include // Vec: cvec + + +int main() +{ + c_auto (Vec, vec) + { + const int v[] = {2012, 1990, 2012, 2019, 2015}; + c_forrange (i, c_arraylen(v)) + Vec_push_back(&vec, Arc_from(v[i])); + + // clone the second 2012 and push it back. + // note: cloning make sure that vec.data[2] has ref count 2. + Vec_push_back(&vec, Arc_clone(vec.data[2])); + + printf("vec before erase :"); + c_foreach (i, Vec, vec) + printf(" %d", *i.ref->get); + puts(""); + + printf("erase vec.data[2]; or first matching value depending on compare.\n"); + Vec_iter it; + it = Vec_find(&vec, *vec.data[2].get); + if (it.ref != Vec_end(&vec).ref) + Vec_erase_at(&vec, it); + + int year = 2015; + it = Vec_find(&vec, year); // Ok as tmp only. + if (it.ref != Vec_end(&vec).ref) + Vec_erase_at(&vec, it); + + printf("vec after erase :"); + c_foreach (i, Vec, vec) + printf(" %d", *i.ref->get); + + puts("\nDone"); + } +} diff --git a/examples/music_arc.c b/examples/music_arc.c new file mode 100644 index 00000000..42bb3455 --- /dev/null +++ b/examples/music_arc.c @@ -0,0 +1,58 @@ +// shared_ptr-examples.cpp +// based on https://docs.microsoft.com/en-us/cpp/cpp/how-to-create-and-use-shared-ptr-instances?view=msvc-160 + +#include + +struct Song +{ + cstr artist; + cstr title; +} typedef Song; + +Song Song_new(const char* artist, const char* title) + { return (Song){cstr_from(artist), cstr_from(title)}; } + +void Song_drop(Song* s) { + printf("drop: %s\n", s->title.str); + c_drop(cstr, &s->artist, &s->title); +} + +#define i_type SongPtr +#define i_val Song +#define i_drop Song_drop +#define i_opt c_no_cmp +#include + +#define i_type SongVec +#define i_val_sptr SongPtr +#include + +void example3() +{ + c_auto (SongVec, vec, vec2) + { + c_apply(v, SongVec_push_back(&vec, v), SongPtr, { + SongPtr_from(Song_new("Bob Dylan", "The Times They Are A Changing")), + SongPtr_from(Song_new("Aretha Franklin", "Bridge Over Troubled Water")), + SongPtr_from(Song_new("Thalia", "Entre El Mar y Una Estrella")) + }); + + c_foreach (s, SongVec, vec) + if (!cstr_equals(s.ref->get->artist, "Bob Dylan")) + SongVec_push_back(&vec2, SongPtr_clone(*s.ref)); + + c_apply(v, SongVec_push_back(&vec2, v), SongPtr, { + SongPtr_from(Song_new("Michael Jackson", "Billie Jean")), + SongPtr_from(Song_new("Rihanna", "Stay")), + }); + + c_foreach (s, SongVec, vec2) + printf("%s - %s: refs %lu\n", s.ref->get->artist.str, s.ref->get->title.str, + *s.ref->use_count); + } +} + +int main() +{ + example3(); +} diff --git a/examples/person_arc.c b/examples/person_arc.c new file mode 100644 index 00000000..0c22bd68 --- /dev/null +++ b/examples/person_arc.c @@ -0,0 +1,67 @@ +/* cbox: heap allocated boxed type */ +#include + +typedef struct { cstr name, last; } Person; + +Person Person_new(const char* name, const char* last) { + return (Person){.name = cstr_from(name), .last = cstr_from(last)}; +} + +int Person_cmp(const Person* a, const Person* b) { + int c = strcmp(a->name.str, b->name.str); + return c ? c : strcmp(a->last.str, b->last.str); +} + +Person Person_clone(Person p) { + p.name = cstr_clone(p.name); + p.last = cstr_clone(p.last); + return p; +} + +void Person_drop(Person* p) { + printf("drop: %s %s\n", p->name.str, p->last.str); + c_drop(cstr, &p->name, &p->last); +} + +#define i_type PSPtr +#define i_val_bind Person // binds Person_cmp, ... +#include + +#define i_type Persons +#define i_val_sptr PSPtr // binds PSPtr_cmp, ... +#include + + +int main() +{ + c_auto (Persons, vec) + c_auto (PSPtr, p, q) + { + p = PSPtr_from(Person_new("Laura", "Palmer")); + + // We want a deep copy -- PSPtr_clone(p) only shares! + q = PSPtr_from(Person_clone(*p.get)); + cstr_assign(&q.get->name, "Leland"); + + printf("orig: %s %s\n", p.get->name.str, p.get->last.str); + printf("copy: %s %s\n", q.get->name.str, q.get->last.str); + + Persons_push_back(&vec, PSPtr_from(Person_new("Dale", "Cooper"))); + Persons_push_back(&vec, PSPtr_from(Person_new("Audrey", "Home"))); + + // Clone/share p and q to the vector + c_apply(v, Persons_push_back(&vec, PSPtr_clone(v)), PSPtr, {p, q}); + + c_foreach (i, Persons, vec) + printf("%s %s\n", i.ref->get->name.str, i.ref->get->last.str); + puts(""); + + // Look-up Audrey! + c_autovar (Person a = Person_new("Audrey", "Home"), Person_drop(&a)) { + const PSPtr *v = Persons_get(&vec, a); + if (v) printf("found: %s %s\n", v->get->name.str, v->get->last.str); + } + + puts(""); + } +} diff --git a/examples/sptr.c b/examples/sptr.c deleted file mode 100644 index 0c22bd68..00000000 --- a/examples/sptr.c +++ /dev/null @@ -1,67 +0,0 @@ -/* cbox: heap allocated boxed type */ -#include - -typedef struct { cstr name, last; } Person; - -Person Person_new(const char* name, const char* last) { - return (Person){.name = cstr_from(name), .last = cstr_from(last)}; -} - -int Person_cmp(const Person* a, const Person* b) { - int c = strcmp(a->name.str, b->name.str); - return c ? c : strcmp(a->last.str, b->last.str); -} - -Person Person_clone(Person p) { - p.name = cstr_clone(p.name); - p.last = cstr_clone(p.last); - return p; -} - -void Person_drop(Person* p) { - printf("drop: %s %s\n", p->name.str, p->last.str); - c_drop(cstr, &p->name, &p->last); -} - -#define i_type PSPtr -#define i_val_bind Person // binds Person_cmp, ... -#include - -#define i_type Persons -#define i_val_sptr PSPtr // binds PSPtr_cmp, ... -#include - - -int main() -{ - c_auto (Persons, vec) - c_auto (PSPtr, p, q) - { - p = PSPtr_from(Person_new("Laura", "Palmer")); - - // We want a deep copy -- PSPtr_clone(p) only shares! - q = PSPtr_from(Person_clone(*p.get)); - cstr_assign(&q.get->name, "Leland"); - - printf("orig: %s %s\n", p.get->name.str, p.get->last.str); - printf("copy: %s %s\n", q.get->name.str, q.get->last.str); - - Persons_push_back(&vec, PSPtr_from(Person_new("Dale", "Cooper"))); - Persons_push_back(&vec, PSPtr_from(Person_new("Audrey", "Home"))); - - // Clone/share p and q to the vector - c_apply(v, Persons_push_back(&vec, PSPtr_clone(v)), PSPtr, {p, q}); - - c_foreach (i, Persons, vec) - printf("%s %s\n", i.ref->get->name.str, i.ref->get->last.str); - puts(""); - - // Look-up Audrey! - c_autovar (Person a = Person_new("Audrey", "Home"), Person_drop(&a)) { - const PSPtr *v = Persons_get(&vec, a); - if (v) printf("found: %s %s\n", v->get->name.str, v->get->last.str); - } - - puts(""); - } -} diff --git a/examples/sptr_demo.c b/examples/sptr_demo.c deleted file mode 100644 index 8626e2d4..00000000 --- a/examples/sptr_demo.c +++ /dev/null @@ -1,56 +0,0 @@ -#include -#include - -void int_drop(int* x) { - printf("drop: %d\n", *x); -} - -// carc implements its own clone method using reference counting, -// so 'i_valfrom' need not be defined (will be ignored). - -#define i_type iref // set type name to be defined (instead of 'carc_int') -#define i_val int -#define i_drop int_drop // optional, just to display the elements destroyed -#include // iref - -#define i_key_sptr iref // note: use i_key_bind instead of i_key for carc/cbox elements -#include // csset_iref (like: std::set>) - -#define i_val_sptr iref // note: as above. -#include // cvec_iref (like: std::vector>) - -int main() -{ - c_auto (cvec_iref, vec) // declare and init vec, call cvec_iref_drop() at scope exit - c_auto (csset_iref, set) // declare and init set, call csset_iref_drop() at scope exit - { - const int years[] = {2021, 2012, 2022, 2015}; - c_forrange (i, c_arraylen(years)) - cvec_iref_push_back(&vec, iref_from(years[i])); - - printf("vec:"); - c_foreach (i, cvec_iref, vec) printf(" %d", *i.ref->get); - puts(""); - - // add odd numbers from vec to set - c_foreach (i, cvec_iref, vec) - if (*i.ref->get & 1) - csset_iref_insert(&set, iref_clone(*i.ref)); // copy shared pointer => increments counter. - - // erase the two last elements in vec - cvec_iref_pop_back(&vec); - cvec_iref_pop_back(&vec); - - printf("vec:"); - c_foreach (i, cvec_iref, vec) printf(" %d", *i.ref->get); - - printf("\nset:"); - c_foreach (i, csset_iref, set) printf(" %d", *i.ref->get); - - c_autovar (iref p = iref_clone(vec.data[0]), iref_drop(&p)) { - printf("\n%d is now owned by %ld objects\n", *p.get, *p.use_count); - } - - puts("\nDone"); - } -} diff --git a/examples/sptr_erase.c b/examples/sptr_erase.c deleted file mode 100644 index d40d8fe7..00000000 --- a/examples/sptr_erase.c +++ /dev/null @@ -1,53 +0,0 @@ -#include - -void show_drop(int* x) { printf("drop: %d\n", *x); } - -#define i_type Arc -#define i_val int -#define i_drop show_drop -// carc/cbox will use pointer address comparison of i_val -// if 'i_opt c_no_cmp' is defined, otherwise i_cmp is used -// to compare object values. See the two differences by -// commenting out the next line. -#include // Shared pointer to int - -#define i_type Vec -#define i_val_sptr Arc -#include // Vec: cvec - - -int main() -{ - c_auto (Vec, vec) - { - const int v[] = {2012, 1990, 2012, 2019, 2015}; - c_forrange (i, c_arraylen(v)) - Vec_push_back(&vec, Arc_from(v[i])); - - // clone the second 2012 and push it back. - // note: cloning make sure that vec.data[2] has ref count 2. - Vec_push_back(&vec, Arc_clone(vec.data[2])); - - printf("vec before erase :"); - c_foreach (i, Vec, vec) - printf(" %d", *i.ref->get); - puts(""); - - printf("erase vec.data[2]; or first matching value depending on compare.\n"); - Vec_iter it; - it = Vec_find(&vec, *vec.data[2].get); - if (it.ref != Vec_end(&vec).ref) - Vec_erase_at(&vec, it); - - int year = 2015; - it = Vec_find(&vec, year); // Ok as tmp only. - if (it.ref != Vec_end(&vec).ref) - Vec_erase_at(&vec, it); - - printf("vec after erase :"); - c_foreach (i, Vec, vec) - printf(" %d", *i.ref->get); - - puts("\nDone"); - } -} diff --git a/examples/sptr_music.c b/examples/sptr_music.c deleted file mode 100644 index 42bb3455..00000000 --- a/examples/sptr_music.c +++ /dev/null @@ -1,58 +0,0 @@ -// shared_ptr-examples.cpp -// based on https://docs.microsoft.com/en-us/cpp/cpp/how-to-create-and-use-shared-ptr-instances?view=msvc-160 - -#include - -struct Song -{ - cstr artist; - cstr title; -} typedef Song; - -Song Song_new(const char* artist, const char* title) - { return (Song){cstr_from(artist), cstr_from(title)}; } - -void Song_drop(Song* s) { - printf("drop: %s\n", s->title.str); - c_drop(cstr, &s->artist, &s->title); -} - -#define i_type SongPtr -#define i_val Song -#define i_drop Song_drop -#define i_opt c_no_cmp -#include - -#define i_type SongVec -#define i_val_sptr SongPtr -#include - -void example3() -{ - c_auto (SongVec, vec, vec2) - { - c_apply(v, SongVec_push_back(&vec, v), SongPtr, { - SongPtr_from(Song_new("Bob Dylan", "The Times They Are A Changing")), - SongPtr_from(Song_new("Aretha Franklin", "Bridge Over Troubled Water")), - SongPtr_from(Song_new("Thalia", "Entre El Mar y Una Estrella")) - }); - - c_foreach (s, SongVec, vec) - if (!cstr_equals(s.ref->get->artist, "Bob Dylan")) - SongVec_push_back(&vec2, SongPtr_clone(*s.ref)); - - c_apply(v, SongVec_push_back(&vec2, v), SongPtr, { - SongPtr_from(Song_new("Michael Jackson", "Billie Jean")), - SongPtr_from(Song_new("Rihanna", "Stay")), - }); - - c_foreach (s, SongVec, vec2) - printf("%s - %s: refs %lu\n", s.ref->get->artist.str, s.ref->get->title.str, - *s.ref->use_count); - } -} - -int main() -{ - example3(); -} diff --git a/examples/sptr_threads.c b/examples/sptr_threads.c deleted file mode 100644 index a31c2662..00000000 --- a/examples/sptr_threads.c +++ /dev/null @@ -1,62 +0,0 @@ -// example based on https://en.cppreference.com/w/cpp/memory/shared_ptr - -#include -#include -#include -#include - -struct Base -{ - int value; -} typedef Base; - -#define i_type BaseRc -#define i_val Base -#define i_valdrop(x) printf("Drop Base: %d\n", (x)->value) -#define i_opt c_no_cmp -#include - -mtx_t mtx; - -void* thr(BaseRc* lp) -{ - sleep(1); - c_autoscope (mtx_lock(&mtx), mtx_unlock(&mtx)) - { - printf("local pointer in a thread:\n" - " p.get() = %p, p.use_count() = %ld\n", (void*)lp->get, *lp->use_count); - /* safe to modify base here */ - lp->get->value += 1; - } - /* atomically decrease ref. */ - BaseRc_drop(lp); - return NULL; -} - -int main() -{ - BaseRc p = BaseRc_from((Base){0}); - - mtx_init(&mtx, mtx_plain); - printf("Created a Base\n" - " p.get() = %p, p.use_count() = %ld\n", (void*)p.get, *p.use_count); - enum {N = 3}; - thrd_t t[N]; - BaseRc c[N]; - c_forrange (i, N) { - c[i] = BaseRc_clone(p); - thrd_create(&t[i], (thrd_start_t)thr, &c[i]); - } - - printf("Shared ownership between %d threads and released\n" - "ownership from main:\n" - " p.get() = %p, p.use_count() = %ld\n", N, (void*)p.get, *p.use_count); - BaseRc_reset(&p); - - c_forrange (i, N) thrd_join(t[i], NULL); - printf("All threads completed, the last one deleted Base\n"); -} - -#ifdef STC_TINYCTHREAD_H_ -#include "../src/threads.c" -#endif diff --git a/examples/sptr_to_maps.c b/examples/sptr_to_maps.c deleted file mode 100644 index 0873d297..00000000 --- a/examples/sptr_to_maps.c +++ /dev/null @@ -1,75 +0,0 @@ -// Create a stack and a list of shared pointers to maps, -// and demonstrate sharing and cloning of maps. -#define i_type Map -#define i_key_str // strings -#define i_val int -#define i_keydrop(p) (printf("drop name: %s\n", (p)->str), cstr_drop(p)) -#include - -#define i_type Arc // (atomic) ref. counted type -#define i_val Map -#define i_drop(p) (printf("drop Arc:\n"), Map_drop(p)) -// no need for atomic ref. count in single thread: -// no compare function available for csmap: -#define i_opt c_no_atomic|c_no_cmp -#include - -#define i_type Stack -#define i_val_sptr Arc // define i_val_bind for carc/cbox value (not i_val) -#include - -#define i_type List -#define i_val_sptr Arc // as above -#include - -int main() -{ - c_auto (Stack, stack) - c_auto (List, list) - { - // POPULATE stack with shared pointers to Maps: - Map *map; - map = Stack_push(&stack, Arc_from(Map_init()))->get; - c_apply(v, Map_emplace(map, c_pair(v)), Map_raw, { - {"Joey", 1990}, {"Mary", 1995}, {"Joanna", 1992} - }); - map = Stack_push(&stack, Arc_from(Map_init()))->get; - c_apply(v, Map_emplace(map, c_pair(v)), Map_raw, { - {"Rosanna", 2001}, {"Brad", 1999}, {"Jack", 1980} - }); - - // POPULATE list: - map = List_push_back(&list, Arc_from(Map_init()))->get; - c_apply(v, Map_emplace(map, c_pair(v)), Map_raw, { - {"Steve", 1979}, {"Rick", 1974}, {"Tracy", 2003} - }); - - // Share two Maps from the stack with the list using emplace (clone the carc): - List_push_back(&list, Arc_clone(stack.data[0])); - List_push_back(&list, Arc_clone(stack.data[1])); - - // Clone (deep copy) a Map from the stack to the list - // List will contain two shared and two unshared maps. - map = List_push_back(&list, Arc_from(Map_clone(*stack.data[1].get)))->get; - - // Add one more element to the cloned map: - Map_emplace_or_assign(map, "CLONED", 2021); - - // Add one more element to the shared map: - Map_emplace_or_assign(stack.data[1].get, "SHARED", 2021); - - - puts("STACKS"); - c_foreach (i, Stack, stack) { - c_forpair (name, year, Map, *i.ref->get) - printf(" %s:%d", _.name.str, _.year); - puts(""); - } - puts("LIST"); - c_foreach (i, List, list) { - c_forpair (name, year, Map, *i.ref->get) - printf(" %s:%d", _.name.str, _.year); - puts(""); - } - } -} diff --git a/examples/threads_demo.c b/examples/threads_demo.c new file mode 100644 index 00000000..a31c2662 --- /dev/null +++ b/examples/threads_demo.c @@ -0,0 +1,62 @@ +// example based on https://en.cppreference.com/w/cpp/memory/shared_ptr + +#include +#include +#include +#include + +struct Base +{ + int value; +} typedef Base; + +#define i_type BaseRc +#define i_val Base +#define i_valdrop(x) printf("Drop Base: %d\n", (x)->value) +#define i_opt c_no_cmp +#include + +mtx_t mtx; + +void* thr(BaseRc* lp) +{ + sleep(1); + c_autoscope (mtx_lock(&mtx), mtx_unlock(&mtx)) + { + printf("local pointer in a thread:\n" + " p.get() = %p, p.use_count() = %ld\n", (void*)lp->get, *lp->use_count); + /* safe to modify base here */ + lp->get->value += 1; + } + /* atomically decrease ref. */ + BaseRc_drop(lp); + return NULL; +} + +int main() +{ + BaseRc p = BaseRc_from((Base){0}); + + mtx_init(&mtx, mtx_plain); + printf("Created a Base\n" + " p.get() = %p, p.use_count() = %ld\n", (void*)p.get, *p.use_count); + enum {N = 3}; + thrd_t t[N]; + BaseRc c[N]; + c_forrange (i, N) { + c[i] = BaseRc_clone(p); + thrd_create(&t[i], (thrd_start_t)thr, &c[i]); + } + + printf("Shared ownership between %d threads and released\n" + "ownership from main:\n" + " p.get() = %p, p.use_count() = %ld\n", N, (void*)p.get, *p.use_count); + BaseRc_reset(&p); + + c_forrange (i, N) thrd_join(t[i], NULL); + printf("All threads completed, the last one deleted Base\n"); +} + +#ifdef STC_TINYCTHREAD_H_ +#include "../src/threads.c" +#endif -- cgit v1.2.3