summaryrefslogtreecommitdiffhomepage
path: root/docs
diff options
context:
space:
mode:
authorTyge Løvset <[email protected]>2021-12-12 21:33:22 +0100
committerTyge Løvset <[email protected]>2021-12-12 21:33:22 +0100
commitd57b9bb7666753c7cf7ab5a0da6d7d11f303c2af (patch)
tree258690df4a5ab62055261579967d6dfffaf5b0fd /docs
parent9cd20ebfc4f1e10153ff814085499223265ef902 (diff)
downloadSTC-modified-d57b9bb7666753c7cf7ab5a0da6d7d11f303c2af.tar.gz
STC-modified-d57b9bb7666753c7cf7ab5a0da6d7d11f303c2af.zip
- Added **cbox** type: container of one element: similar to std::unique_ptr / Rust Box.
- Replaced example for **csptr** in docs. - Added [**c_forpair**](docs/ccommon_api.md) macro: for-loop with "structural binding" as in c++. - Deprecated *csptr_X_make()*. Renamed to *csptr_X_new()*. Corresponding **cbox** method is *cbox_X_new()*. - Deprecated *c_default_fromraw(raw)*. Renamed to *c_default_clone(raw)*. - Deprecated `i_key_csptr` / `i_val_csptr`. Use `i_key_ref` / `i_val_ref` when specifying containers with **csptr** or **cbox** elements. - Deprecated `i_cnt`. Use `i_type` instead to define the full container type name. - Bugfixes and docs updates.
Diffstat (limited to 'docs')
-rw-r--r--docs/carray_api.md35
-rw-r--r--docs/cbox_api.md136
-rw-r--r--docs/ccommon_api.md41
-rw-r--r--docs/csptr_api.md208
4 files changed, 302 insertions, 118 deletions
diff --git a/docs/carray_api.md b/docs/carray_api.md
index eb5123b3..5e26f658 100644
--- a/docs/carray_api.md
+++ b/docs/carray_api.md
@@ -90,29 +90,30 @@ int main()
// Ex1
int xd = 30, yd = 20, zd = 10;
// define arr3[30][20][10], initialized with zeros.
- carr3_f arr3 = carr3_f_with_values(xd, yd, zd, 0.0f);
- arr3.data[5][4][3] = 3.14f;
+ c_autovar (carr3_f arr3 = carr3_f_with_values(xd, yd, zd, 0.0f),
+ carr3_f_del(&arr3)) {
+ arr3.data[5][4][3] = 3.14f;
- float *arr1 = arr3.data[5][4];
- float **arr2 = arr3.data[5];
+ float *arr1 = arr3.data[5][4];
+ float **arr2 = arr3.data[5];
- printf("%f\n", arr1[3]); // 3.14
- printf("%f\n", arr2[4][3]); // 3.14
- printf("%f\n", arr3.data[5][4][3]); // 3.14
- carr3_f_del(&arr3); // free array
+ printf("%f\n", arr1[3]); // 3.14
+ printf("%f\n", arr2[4][3]); // 3.14
+ printf("%f\n", arr3.data[5][4][3]); // 3.14
+ }
// Ex2
int w = 256, h = 128;
- carr2_i image = carr2_i_init(w, h);
- int n = 0;
- c_foreach (i, carr2_i, image) {
- uint32_t t = n++ % 256;
- *i.ref = t | t << 8 | t << 16 | 255;
+ c_autovar (carr2_i image = carr2_i_init(w, h), carr2_i_del(&image)) {
+ int n = 0;
+ c_foreach (i, carr2_i, image) {
+ uint32_t t = n++ % 256;
+ *i.ref = t | t << 8 | t << 16 | 255;
+ }
+
+ for (int y = 0; y < image.ydim; ++y)
+ image.data[y][y] = 0xffffffff;
}
-
- for (int y = 0; y < image.ydim; ++y)
- image.data[y][y] = 0xffffffff;
- carr2_i_del(&image);
}
```
Output:
diff --git a/docs/cbox_api.md b/docs/cbox_api.md
new file mode 100644
index 00000000..7c632919
--- /dev/null
+++ b/docs/cbox_api.md
@@ -0,0 +1,136 @@
+# STC [cbox](../include/stc/cbox.h): Shared Pointers
+
+**cbox** is a container for one heap allocated object. A **cbox** is empty by default.
+The *cbox_X_compare()*, *cbox_X_del()* methods are defined based on the `i_cmp`
+and `i_valdel` macros specified. Use *cbox_X_clone(p)* to make a deep copy, which
+uses the `i_valfrom` macro if defined.
+
+When declaring a container with cbox elements, define `i_val_ref` as the cbox type, see example.
+
+For containers, make sure to pass the result of create functions like *cbox_X_new()* **only** to
+*insert()*, *push_back()*, and *push()* functions. Use *emplace()* functions to deep clone
+already existing/owned cbox elements.
+
+See similar c++ class [std::unique_ptr](https://en.cppreference.com/w/cpp/memory/unique_ptr) for a functional reference, or Rust [std::boxed::Box](https://doc.rust-lang.org/std/boxed/struct.Box.html)
+
+## Header file and declaration
+
+```c
+#define i_val // value: REQUIRED
+#define i_cmp // three-way compare two i_val* : REQUIRED IF i_val is a non-integral type
+#define i_del // destroy value func - defaults to empty destruct
+#define i_tag // defaults to i_val
+#include <stc/cbox.h>
+```
+`X` should be replaced by the value of `i_tag` in all of the following documentation.
+
+## Methods
+```c
+cbox_X cbox_X_init(); // return an empty cbox
+cbox_X cbox_X_new(i_val val); // allocate new heap object with val. Take ownership of val.
+cbox_X cbox_X_from(i_rawval raw); // like cbox_X_new(), but create owned value from raw.
+cbox_X cbox_X_with(i_val* p); // create a cbox from a pointer. Takes ownership of p.
+
+cbox_X cbox_X_clone(cbox_X other); // return deep copied clone
+cbox_X cbox_X_move(cbox_X* self); // transfer ownership to another cbox.
+void cbox_X_take(cbox_X* self, cbox_X other); // take ownership of other.
+void cbox_X_copy(cbox_X* self, cbox_X other); // deep copy to self
+
+void cbox_X_del(cbox_X* self); // destruct the contained object and free's it.
+
+void cbox_X_reset(cbox_X* self);
+void cbox_X_reset_new(cbox_X* self, i_val val); // assign new cbox with value. Takes ownership of val.
+void cbox_X_reset_from(cbox_X* self, i_rawval raw); // make and assign new cbox from raw value.
+void cbox_X_reset_with(cbox_X* self, i_val* p); // create cbox with pointer p. Takes ownership of p.
+
+int cbox_X_compare(const cbox_X* x, const cbox_X* y); // compares pointer addresses if 'i_opt c_no_compare'
+ // is defined. Otherwise uses 'i_cmp' or default compare.
+```
+## Types and constants
+
+| Type name | Type definition | Used to represent... |
+|:-------------------|:--------------------------------|:------------------------|
+| `cbox_null` | `{NULL}` | Init nullptr const |
+| `cbox_X` | `struct { cbox_X_value* get; }` | The cbox type |
+| `cbox_X_value` | `i_val` | The cbox element type |
+
+## Example
+
+```c
+#include <stdio.h>
+#include <string.h>
+
+void int_del(int* x) {
+ printf("del: %d\n", *x);
+}
+
+// When 'i_del' is defined, you are also forced to define a clone function with
+// 'i_valfrom', as it is normally required when i_del destroys resources.
+//
+// If cloning is not needed, define 'i_opt c_no_clone' instead of 'i_valfrom'
+// both for the cbox type and the container of cbox elements. It will also
+// disable emplace container functions.
+//
+// This applies to all container types, except those with csptr elements, as they
+// define cloning internally.
+
+#define i_val int
+#define i_del int_del // optional func, just to display elements destroyed
+#define i_valfrom c_default_clone
+#include <stc/cbox.h> // cbox_int
+
+#define i_key_ref cbox_int // note: use i_key_ref instead of i_key
+#define i_tag int // tag otherwise defaults to 'ref'
+#include <stc/csset.h> // csset_int (like: std::set<std::unique_ptr<int>>)
+
+#define i_val_ref cbox_int // note: use i_val_ref instead of i_val
+#define i_tag int // tag otherwise defaults to 'ref'
+#include <stc/cvec.h> // cvec_int (like: std::vector<std::unique_ptr<int>>)
+
+int main()
+{
+ c_auto (cvec_int, vec) // declare and init vec, call del at scope exit
+ c_auto (csset_int, set) // declare and init set, call del at scope exit
+ {
+ c_apply(cvec_int, push_back, &vec, {
+ cbox_int_new(2021),
+ cbox_int_new(2012),
+ cbox_int_new(2022),
+ cbox_int_new(2015),
+ });
+ printf("vec:");
+ c_foreach (i, cvec_int, vec) printf(" %d", *i.ref->get);
+ puts("");
+
+ // add odd numbers from vec to set
+ c_foreach (i, cvec_int, vec)
+ if (*i.ref->get & 1)
+ csset_int_emplace(&set, *i.ref); // deep copy (clones) *i.ref object
+
+ // erase the two last elements in vec
+ cvec_int_pop_back(&vec);
+ cvec_int_pop_back(&vec);
+
+ printf("vec:");
+ c_foreach (i, cvec_int, vec) printf(" %d", *i.ref->get);
+
+ printf("\nset:");
+ c_foreach (i, csset_int, set) printf(" %d", *i.ref->get);
+
+ puts("\nDone");
+ }
+}
+```
+Output:
+```
+vec: 2021 2012 2022 2015
+del: 2015
+del: 2022
+vec: 2021 2012
+set: 2015 2021
+Done
+del: 2021
+del: 2015
+del: 2021
+del: 2012
+```
diff --git a/docs/ccommon_api.md b/docs/ccommon_api.md
index 3d353e6c..8c749e8e 100644
--- a/docs/ccommon_api.md
+++ b/docs/ccommon_api.md
@@ -79,26 +79,33 @@ int main()
}
```
-### c_foreach
+### c_foreach, c_forpair
-| Usage | Description |
-|:-------------------------------------|:-----------------------------|
-| `c_foreach (it, ctype, container)` | Iteratate all elements |
-| `c_foreach (it, ctype, it1, it2)` | Iterate the range [it1, it2) |
+| Usage | Description |
+|:-------------------------------------------|:--------------------------------|
+| `c_foreach (it, ctype, container)` | Iteratate all elements |
+| `c_foreach (it, ctype, it1, it2)` | Iterate the range [it1, it2) |
+| `c_forpair (key, value, ctype, container)` | Iterate with structural binding |
```c
-#define i_tag x
#define i_key int
-#include <stc/csset.h>
+#define i_val int
+#define i_tag ii
+#include <stc/csmap.h>
...
-c_apply(csset_x, insert, &set, {23, 3, 7, 5, 12});
-c_foreach (i, csset_x, set)
- printf(" %d", *i.ref);
-// 3 5 7 12 23
-csset_x_iter it = csset_x_find(&set, 7);
-c_foreach (i, csset_x, it, csset_x_end(&set))
- printf(" %d", *i.ref);
-// 7 12 23
+c_apply_pair(csmap_ii, insert, &map, {{23,1}, {3,2}, {7,3}, {5,4}, {12,5}});
+c_foreach (i, csmap_ii, map)
+ printf(" %d", i.ref->first);
+// out: 3 5 7 12 23
+
+csmap_ii_iter it = csmap_ii_find(&map, 7);
+c_foreach (i, csmap_ii, it, csmap_ii_end(&map))
+ printf(" %d", i.ref->first);
+// out: 7 12 23
+
+c_forpair (id, count, csmap_ii, map)
+ printf(" (%d %d)", _.id, _.count);
+// out: (3 2) (5 4) (7 3) (12 5) (23 1)
```
### c_forrange
@@ -124,7 +131,7 @@ c_forrange (i, int, 30, 0, -5) printf(" %d", i);
```
### c_apply, c_apply_pair, c_apply_n
-**c_apply** will apply a method on an existing container with the given array elements:
+**c_apply** will apply a method on a container with each of the elements in the given array:
```c
c_apply(cvec_i, push_back, &vec, {1, 2, 3}); // apply multiple push_backs
c_apply_pair(cmap_i, insert, &map, { {4, 5}, {6, 7} }); // inserts to existing map
@@ -158,7 +165,7 @@ c_del(cstr, &a, &b);
### General predefined template parameter functions
```
int c_default_compare(const Type*, const Type*);
-Type c_default_fromraw(Type val); // simple copy
+Type c_default_clone(Type val); // simple copy
Type c_default_toraw(const Type* val); // dereference val
void c_default_del(Type* val); // does nothing
diff --git a/docs/csptr_api.md b/docs/csptr_api.md
index ba85ba8c..ca1e8893 100644
--- a/docs/csptr_api.md
+++ b/docs/csptr_api.md
@@ -13,124 +13,164 @@ All **csptr** functions can be called by multiple threads on different instances
additional synchronization even if these instances are copies and share ownership of the same object.
**csptr** uses thread-safe atomic reference counting, through the *csptr_X_clone()* and *csptr_X_del()* methods.
-When declaring a container with shared pointers, define the `i_val_csptr` with the full csptr type.
-See example.
+When declaring a container with shared pointers, define `i_val_ref` as the csptr type, see example.
-Also for containers, make sure to pass the result of *csptr_X_make()* to *insert*, *push_back*,
-or *push*, and not an *emplace* function. The *csptr_X_make()* method creates a **csptr** with
-use-count 1, and *emplace* will ***clone*** it and increase the count, causing a memory leak. Use
-*emplace* functions when sharing **csptr**s between containers or other existing shared pointers.
+For containers, make sure to pass the result of create functions *csptr_X_new()* **only** to *insert()*,
+*push_back()*, and *push()* functions. Use *emplace()* method for sharing existing **csptr**s between
+containers or other existing shared pointers, as they internally clone/share the input.
-See the c++ classes [std::shared_ptr](https://en.cppreference.com/w/cpp/memory/shared_ptr) for a functional reference.
+See similar c++ class [std::shared_ptr](https://en.cppreference.com/w/cpp/memory/shared_ptr) for a functional reference, or Rust [std::sync::Arc](https://doc.rust-lang.org/std/sync/struct.Arc.html) / [std::rc::Rc](https://doc.rust-lang.org/std/rc/struct.Rc.html).
## Header file and declaration
```c
-#define i_val // value: REQUIRED
-#define i_cmp // three-way compare two i_val* : REQUIRED IF i_val is a non-integral type
-#define i_del // destroy value func - defaults to empty destruct
-#define i_tag // defaults to i_val
+#define i_val // value: REQUIRED
+#define i_cmp // three-way compare two i_val* : REQUIRED IF i_val is a non-integral type
+#define i_del // destroy value func - defaults to empty destruct
+#define i_tag // defaults to i_val
+#define i_opt c_no_atomic // Non-atomic reference counting, like Rust Rc.
#include <stc/csptr.h>
```
`X` should be replaced by the value of `i_tag` in all of the following documentation.
## Methods
```c
-csptr_X csptr_X_init(); // empty constructor
-csptr_X csptr_X_make(i_val val); // make_shared constructor, like std::make_shared()
-csptr_X csptr_X_from(i_val* p); // construct from raw pointer
-csptr_X csptr_X_clone(csptr_X ptr); // return ptr with increased use count
-csptr_X csptr_X_move(csptr_X* self); // transfer ownership to another sptr.
-void csptr_X_take(csptr_X* self, csptr_X other); // take a new-created or moved csptr
-void csptr_X_copy(csptr_X* self, csptr_X other); // copy shared (increase use count)
-
-void csptr_X_del(csptr_X* self); // destruct (decrease use count, free at 0)
-long csptr_X_use_count(csptr_X ptr);
-
-void csptr_X_reset(csptr_X* self);
-void csptr_X_reset_with(csptr_X* self, i_val val); // make and assign new csptr with value
-void csptr_X_reset_from(csptr_X* self, i_val* p); // create csptr from p.
-
-int csptr_X_compare(const csptr_X* x, const csptr_X* y);
+csptr_X csptr_X_init(); // empty shared pointer
+csptr_X csptr_X_new(i_val val); // create new heap allocated object. Take ownership of val.
+csptr_X csptr_X_from(i_rawval raw); // like csptr_X_new(), but construct owned value from raw.
+csptr_X csptr_X_with(i_val* p); // create a csptr from raw pointer. Takes ownership of p.
+
+csptr_X csptr_X_clone(csptr_X other); // return other with increased use count
+csptr_X csptr_X_move(csptr_X* self); // transfer ownership to another csptr.
+void csptr_X_take(csptr_X* self, csptr_X other); // take ownership of other.
+void csptr_X_copy(csptr_X* self, csptr_X other); // copy shared (increase use count)
+
+void csptr_X_del(csptr_X* self); // destruct (decrease use count, free at 0)
+long csptr_X_use_count(csptr_X ptr);
+
+void csptr_X_reset(csptr_X* self);
+void csptr_X_reset_new(csptr_X* self, i_val val); // assign new csptr with value. Takes ownership of val.
+void csptr_X_reset_from(csptr_X* self, i_rawval raw); // make and assign new csptr from raw value.
+void csptr_X_reset_with(csptr_X* self, i_val* p); // create csptr with pointer p. Takes ownership of p.
+
+int csptr_X_compare(const csptr_X* x, const csptr_X* y); // compares pointer addresses if 'i_opt c_no_compare'
+ // is defined. Otherwise uses 'i_cmp' or default compare.
```
## Types and constants
| Type name | Type definition | Used to represent... |
-|:--------------------|:--------------------------------------------------------------|:-------------------------|
-| `csptr_null` | `{NULL, NULL}` | Init nullptr const |
-| `csptr_X` | `struct { csptr_X_value* get; atomic_count_t* use_count; }` | The csptr type |
-| `csptr_X_value` | `i_val` | The csptr element type |
-| `atomic_count_t` | `long` | The reference counter |
+|:--------------------|:--------------------------------------------------|:-------------------------|
+| `csptr_null` | `{NULL, NULL}` | Init nullptr const |
+| `csptr_X` | `struct { csptr_X_value* get; long* use_count; }` | The csptr type |
+| `csptr_X_value` | `i_val` | The csptr element type |
## Example
```c
-#include <stdio.h>
-
-void int_del(int* x) {
- printf("del: %d\n", *x);
-}
-
+// 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_valdel int_del // optional func to display elements destroyed
-#include <stc/csptr.h> // csptr_int
+#define i_keydel(p) (printf("del name: %s\n", (p)->str), cstr_del(p))
+#include <stc/csmap.h>
+
+#define i_type Arc // (atomic) ref. counted type
+#define i_val Map
+#define i_from Map_clone
+#define i_del(p) (printf("del Arc:\n"), Map_del(p))
+// no comparison of Maps needed (or available), and
+// no need for atomic ref. count in single thread:
+#define i_opt c_no_compare|c_no_atomic
+#include <stc/csptr.h>
-#define i_key_csptr csptr_int
-#define i_tag int
-#include <stc/csset.h> // csset_int: csset<csptr_int>
+#define i_type Stack
+#define i_val_ref Arc // define i_val_ref for csptr / cbox value, not i_val
+#include <stc/cstack.h>
-#define i_val_csptr csptr_int
-#define i_tag int
-#include <stc/cvec.h> // cvec_int: cvec<csptr_int>
+#define i_type List
+#define i_val_ref Arc // as above
+#include <stc/clist.h>
int main()
{
- c_auto (cvec_int, vec) // declare and init vec, call del at scope exit
- c_auto (csset_int, set) // declare and init set, call del at scope exit
+ c_auto (Stack, stack)
+ c_auto (List, list)
{
- c_apply(cvec_int, push_back, &vec, {
- csptr_int_make(2021)),
- csptr_int_make(2012)),
- csptr_int_make(2022)),
- csptr_int_make(2015)),
+ // POPULATE the stack with shared pointers to Map:
+ Map *map;
+ map = Stack_push(&stack, Arc_new(Map_init()))->get;
+ c_apply_pair (Map, emplace, map, {
+ {"Joey", 1990}, {"Mary", 1995}, {"Joanna", 1992}
+ });
+ map = Stack_push(&stack, Arc_new(Map_init()))->get;
+ c_apply_pair (Map, emplace, map, {
+ {"Rosanna", 2001}, {"Brad", 1999}, {"Jack", 1980}
});
- printf("vec:");
- c_foreach (i, cvec_int, vec) printf(" %d", *i.ref->get);
- puts("");
-
- // add odd numbers from vec to set
- c_foreach (i, cvec_int, vec)
- if (*i.ref->get & 1)
- csset_int_emplace(&set, *i.ref); // copy shared pointer => increments counter.
-
- // erase the two last elements in vec
- cvec_int_pop_back(&vec);
- cvec_int_pop_back(&vec);
-
- printf("vec:");
- c_foreach (i, cvec_int, vec) printf(" %d", *i.ref->get);
-
- printf("\nset:");
- c_foreach (i, csset_int, set) printf(" %d", *i.ref->get);
- c_autovar (csptr_int p = csptr_int_clone(vec.data[0]), csptr_int_del(&p)) {
- printf("\n%d is now owned by %zu objects\n", *p.get, *p.use_count);
+ // POPULATE the list:
+ map = List_push_back(&list, Arc_new(Map_init()))->get;
+ c_apply_pair (Map, emplace, map, {
+ {"Steve", 1979}, {"Rick", 1974}, {"Tracy", 2003}
+ });
+
+ // Share two Maps from the stack with the list using emplace (clones the csptr):
+ List_emplace_back(&list, stack.data[0]);
+ List_emplace_back(&list, 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_new(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, _.year);
+ puts("");
+ }
+ puts("LIST");
+ c_foreach (i, List, list) {
+ c_forpair (name, year, Map, *i.ref->get)
+ printf(" %s:%d", _.name, _.year);
+ puts("");
}
-
- puts("\nDone");
}
}
```
Output:
```
-vec: 2021 2012 2022 2015
-del: 2022
-vec: 2021 2012
-set: 2015 2021
-2021 is now owned by 3 objects
-Done
-del: 2015
-del: 2021
-del: 2012
+STACKS
+ Joanna:1992 Joey:1990 Mary:1995
+ Brad:1999 Jack:1980 Rosanna:2001 SHARED:2021
+LIST
+ Rick:1974 Steve:1979 Tracy:2003
+ Joanna:1992 Joey:1990 Mary:1995
+ Brad:1999 Jack:1980 Rosanna:2001 SHARED:2021
+ Brad:1999 CLONED:2021 Jack:1980 Rosanna:2001
+del Arc:
+del name: Rick
+del name: Tracy
+del name: Steve
+del Arc:
+del name: CLONED
+del name: Brad
+del name: Rosanna
+del name: Jack
+del Arc:
+del name: Brad
+del name: SHARED
+del name: Rosanna
+del name: Jack
+del Arc:
+del name: Joanna
+del name: Mary
+del name: Joey
```