diff options
| author | Tyge Løvset <[email protected]> | 2021-12-22 12:35:36 +0100 |
|---|---|---|
| committer | Tyge Løvset <[email protected]> | 2021-12-22 12:35:36 +0100 |
| commit | 79c83eba7933f49e766dbeb85f9c40ee17e06edf (patch) | |
| tree | e43a84d18b79956a8e22b9403358811b6865f344 | |
| parent | 7a30e2853792870a1d85087861e46a1ae1ca6b0e (diff) | |
| download | STC-modified-79c83eba7933f49e766dbeb85f9c40ee17e06edf.tar.gz STC-modified-79c83eba7933f49e766dbeb85f9c40ee17e06edf.zip | |
Renamed csptr to carc. i_key/val_ref renamed to i_key/val_sptr. Change inspired by Rust Arc/Rc. cbox name is taken from Rust Box type.
| -rw-r--r-- | README.md | 73 | ||||
| -rw-r--r-- | docs/cbox_api.md | 10 | ||||
| -rw-r--r-- | docs/csptr_api.md | 96 | ||||
| -rw-r--r-- | examples/box.c | 3 | ||||
| -rw-r--r-- | examples/box2.c | 8 | ||||
| -rw-r--r-- | examples/new_sptr.c | 16 | ||||
| -rw-r--r-- | examples/sptr.c | 4 | ||||
| -rw-r--r-- | examples/sptr_demo.c | 10 | ||||
| -rw-r--r-- | examples/sptr_erase.c | 8 | ||||
| -rw-r--r-- | examples/sptr_music.c | 4 | ||||
| -rw-r--r-- | examples/sptr_pthread.c | 20 | ||||
| -rw-r--r-- | examples/sptr_to_maps.c | 8 | ||||
| -rw-r--r-- | include/stc/carc.h (renamed from include/stc/csptr.h) | 30 | ||||
| -rw-r--r-- | include/stc/ccommon.h | 2 | ||||
| -rw-r--r-- | include/stc/forward.h | 4 | ||||
| -rw-r--r-- | include/stc/template.h | 16 |
16 files changed, 164 insertions, 148 deletions
@@ -5,19 +5,20 @@ STC - Smart Template Containers for C News ---- -### Version 3.0 released -There are new general `i_key_bind` / `i_val_bind` template parameters which auto-binds a set of functions -to the type specified, and can be used in place of `i_key` / `i_val`. Use the `_bind` variant for elements +### Version 3 released +A lot of enhancements, additions and bugfixes. There are also a number of breaking changes (mostly renamings), +see migrate guide below. + +Added are new general `i_key_bind`/`i_val_bind` template parameters which auto-binds a set of functions +to the type specified, and may be used in place of `i_key`/`i_val`. Use the `_bind` variant for elements of Type which have following functions defined: *Type_cmp*, *Type_clone*, *Type_drop*, *Type_hash*, and *Type_eq*. Only the functions required by the particular container needs to be defined. e.g. **cmap** -and **cset** are the only types that requires *Type_hash* and *Type_eq* to be defined. -You may override these by defining `i_cmp`, `i_drop`, etc. Template parameters with `i_val` / `i_key` may -still be defined as before, which is often easier for simple element types. +and **cset** are the only types that require *Type_hash* and *Type_eq* to be defined. -Migration guide from version 2 to 3. Replace (regular expresion) in VS Code: +### Migration guide from version 2 to 3. +Replace (regular expression) in VS Code: - `_del\b` → `_drop` - `_compare\b` → `_cmp` -- `csptr` → `cref` - `_rawvalue\b` → `_raw` - `_equ\b` → `_eq` @@ -26,24 +27,25 @@ Replace (whole word + match case): - `i_valdel` → `i_valdrop` - `i_cnt` → `i_type` - `cstr_lit` → `cstr_new` -- `csptr_X_make` → `csptr_X_new` +- `csptr_X_make` → `carc_X_from` - `i_key_csptr` → `i_key_sptr` - `i_val_csptr` → `i_val_sptr` - `c_apply` → `c_apply_OLD` // replaced by new `c_apply` - `c_apply_pair` → `c_apply_pair_OLD` // replaced by new `c_apply` -### Final version 2.1 +Non-regex, global match case replace: +- `csptr` → `carc` + +### Brief summary of changes - Strings: Renamed constructor *cstr_lit()* to `cstr_new(lit)`. Renamed *cstr_assign_fmt()* to `cstr_printf()`. -- Added [**cbox**](docs/cbox_api.md) type: container of one element, similar to [std::unique_ptr](https://en.cppreference.com/w/cpp/memory/unique_ptr) -- Added [example for **csptr**](examples/sptr_to_maps.c). +- Added [**cbox**](docs/cbox_api.md) type: smart pointer, similar to [std::unique_ptr](https://en.cppreference.com/w/cpp/memory/unique_ptr). Also renamed `csptr` to `carc` (atomic reference counted) smart pointer. +- Added [example for **carc**](examples/sptr_to_maps.c). - Added [**c_forpair**](docs/ccommon_api.md) macro: for-loop with "structured binding". -- Renamed: *csptr_X_make()* to *csptr_X_new()*. Corresponding **cbox** method is *cbox_X_new()*. +- Renamed: *csptr_X_make()* to *carc_X_from()*. Corresponding **cbox** method is *cbox_X_from()*. - Renamed: *c_default_fromraw(raw)* to *c_default_clone(raw)*. -- Renamed: `i_key_csptr` / `i_val_csptr`. Use `i_key_sptr` / `i_val_sptr` for **csptr** and **cbox**. +- Renamed: `i_key_csptr`/`i_val_csptr` to `i_key_sptr`/`i_val_sptr` for both **carc** and **cbox** values in containers. - Renamed: `i_cnt` to `i_type` for defining the complete container type name. - Added `i_opt` template parameter: compile-time options: `c_no_cmp`, `c_no_clone`, `c_no_atomic`, `c_is_fwd`; may be combined with `|` - -### Version 2.0. Two main breaking changes from V1.X. - Uses a different way to instantiate templated containers, which is incompatible with v1.X. Introduction @@ -67,7 +69,7 @@ which by the compiler is seen as different code because of macro name substituti - [***clist*** - **std::forward_list** alike type](docs/clist_api.md) - [***cmap*** - **std::unordered_map** alike type](docs/cmap_api.md) - [***cpque*** - **std::priority_queue** alike type](docs/cpque_api.md) -- [***csptr*** - **std::shared_ptr** alike support](docs/csptr_api.md) +- [***carc*** - **std::shared_ptr** alike support](docs/carc_api.md) - [***cqueue*** - **std::queue** alike type](docs/cqueue_api.md) - [***cset*** - **std::unordered_set** alike type](docs/cset_api.md) - [***csmap*** - **std::map** sorted map alike type](docs/csmap_api.md) @@ -87,7 +89,7 @@ Highlights - **User friendly** - Just include the headers and you are good. The API and functionality is very close to c++ STL, and is fully listed in the docs. - **Templates** - Use `#define i_{arg}` to specify container template arguments. There are templates for element-*type*, -*comparison*, -*destruction*, -*cloning*, -*conversion types*, and more. - **Unparalleled performance** - Some containers are much faster than the c++ STL containers, the rest are about equal in speed. -- **Fully memory managed** - All containers will destruct keys/values via destructor defined as macro parameters before including the container header. Also, shared pointers are supported and can be stored in containers, see ***csptr***. +- **Fully memory managed** - All containers will destruct keys/values via destructor defined as macro parameters before including the container header. Also, shared pointers are supported and can be stored in containers, see ***carc***. - **Fully type safe** - Because of templating, it avoids error-prone casting of container types and elements back and forth from the containers. - **Uniform, easy-to-learn API** - Methods to ***construct***, ***initialize***, ***iterate*** and ***destruct*** have uniform and intuitive usage across the various containers. - **Small footprint** - Small source code and generated executables. The executable from the example below with six different containers is *22 kb in size* compiled with gcc -Os on linux. @@ -114,19 +116,30 @@ The usage of the containers is similar to the c++ standard containers in STL, so are familiar with them. All containers are generic/templated, except for **cstr** and **cbits**. No casting is used, so containers are type-safe like templates in c++. A basic usage example: ```c -#define i_val float -#include <stc/cvec.h> +#define i_type FVec // if not defined, vector type would be cvec_float +#define i_val float // element type +#include <stc/cvec.h> // defines the FVec type int main(void) { - cvec_float vec = cvec_float_init(); - cvec_float_push_back(&vec, 10.f); - cvec_float_push_back(&vec, 20.f); - cvec_float_push_back(&vec, 30.f); - - c_foreach (i, cvec_float, vec) - printf(" %g", *i.ref); + FVec vec = FVec_init(); + FVec_push_back(&vec, 10.f); + FVec_push_back(&vec, 20.f); + FVec_push_back(&vec, 30.f); + + for (size_t i = 0; i < FVec_size(vec); ++i) + printf(" %g", vec.data[i]); + FVec_drop(&vec); // free memory +} +``` +However, a "better" way to write the same is: +```c +int main(void) { + c_auto (FVec, vec) { // RAII + c_apply(v, FVec_push_back(&vec, v), float, {10.f, 20.f, 30.f}); - cvec_float_drop(&vec); + c_foreach (i, FVec, vec) // generic iteration and element access + printf(" %g", *i.ref); + } } ``` In order to include two **cvec**s with different element types, include cvec.h twice. For struct, a `i_cmp` @@ -195,7 +208,7 @@ int main(void) { { // add some elements to each container c_apply(v, cset_int_insert(&set, v), int, {10, 20, 30}); - c_apply(v, cvec_pnt_push_back(&vec, v), int, { {10, 1}, {20, 2}, {30, 3} }); + c_apply(v, cvec_pnt_push_back(&vec, v), cvec_pnt_raw, { {10, 1}, {20, 2}, {30, 3} }); c_apply(v, cdeq_int_push_back(&deq, v), int, {10, 20, 30}); c_apply(v, clist_int_push_back(&lst, v), int, {10, 20, 30}); c_apply(v, cstack_int_push(&stk, v), int, {10, 20, 30}); @@ -440,4 +453,4 @@ Memory efficiency - **cmap**: Type size: 4 pointers. *cmap* uses one table of keys+value, and one table of precomputed hash-value/used bucket, which occupies only one byte per bucket. The closed hashing has a default max load factor of 85%, and hash table scales by 1.6x when reaching that. - **csmap**: Type size: 1 pointer. *csmap* manages its own array of tree-nodes for allocation efficiency. Each node uses only two 32-bit ints for child nodes, and one byte for `level`. - **carr2**, **carr3**: Type size: 1 pointer plus dimension variables. Arrays are allocated as one contiguous block of heap memory, and one allocation for pointers of indices to the array. -- **csptr**: Type size: 2 pointers, one for the data and one for the reference counter. +- **carc**: Type size: 2 pointers, one for the data and one for the reference counter. diff --git a/docs/cbox_api.md b/docs/cbox_api.md index 011beea2..e05e69f0 100644 --- a/docs/cbox_api.md +++ b/docs/cbox_api.md @@ -1,4 +1,4 @@ -# STC [cbox](../include/stc/cbox.h): (Boxed) Heap Allocated Objects +# STC [cbox](../include/stc/cbox.h): Smart Pointer (Boxed object) **cbox** is a A box is a smart pointer to a heap allocated value of type X. A **cbox** can be empty. The *cbox_X_cmp()*, *cbox_X_drop()* methods are defined based on the `i_cmp` @@ -21,7 +21,7 @@ See similar c++ class [std::unique_ptr](https://en.cppreference.com/w/cpp/memory #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_drop // destroy value func - defaults to empty destruct -#define i_from // create from raw/clone func - REQUIRED if i_drop is defined, +#define i_from // create from raw/clone func - REQUIRED if i_drop is defined, // unless 'i_opt c_no_clone' is defined. #define i_tag // type name tag, defaults to i_val #include <stc/cbox.h> @@ -76,7 +76,7 @@ void int_drop(int* x) { // 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 +// This applies to all container types, except those with carc elements, as they // define cloning internally. #define i_val int @@ -84,11 +84,11 @@ void int_drop(int* x) { #define i_from c_default_clone #include <stc/cbox.h> // cbox_int -#define i_key_bind cbox_int // note: use i_key_bind instead of i_key +#define i_key_sptr cbox_int // note: use i_key_sptr 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_bind cbox_int // note: use i_val_bind instead of i_val +#define i_val_sptr cbox_int // note: use i_val_sptr 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>>) diff --git a/docs/csptr_api.md b/docs/csptr_api.md index 95575417..e33bf410 100644 --- a/docs/csptr_api.md +++ b/docs/csptr_api.md @@ -1,23 +1,24 @@ -# STC [csptr](../include/stc/csptr.h): Atomic Reference Counted +# STC [carc](../include/stc/carc.h): Atomic Reference Counted Smart Pointer -**csptr** is a smart pointer that retains shared ownership of an object through a pointer. -Several **csptr** objects may own the same object. The object is destroyed and its memory -deallocated when the last remaining **csptr** owning the object is destroyed with *csptr_X_drop()*; +**carc** is a smart pointer that retains shared ownership of an object through a pointer. +Several **carc** objects may own the same object. The object is destroyed and its memory +deallocated when the last remaining **carc** owning the object is destroyed with *carc_X_drop()*; -The object is destroyed using *csptr_X_drop()*. A **csptr** may also own no objects, in which -case it is called empty. The *csptr_X_cmp()*, *csptr_X_drop()* methods are defined based on -the `i_cmp` and `i_valdrop` macros specified. Use *csptr_X_clone(p)* when sharing ownership of +The object is destroyed using *carc_X_drop()*. A **carc** may also own no objects, in which +case it is called empty. The *carc_X_cmp()*, *carc_X_drop()* methods are defined based on +the `i_cmp` and `i_valdrop` macros specified. Use *carc_X_clone(p)* when sharing ownership of the pointed-to object. -All **csptr** functions can be called by multiple threads on different instances of **csptr** without +All **carc** functions can be called by multiple threads on different instances of **carc** without 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_drop()* methods. +**carc** uses thread-safe atomic reference counting, through the *carc_X_clone()* and *carc_X_drop()* methods. -When declaring a container with shared pointers, define `i_val_bind` as the csptr type, see example. +When declaring a container with shared pointers, define `i_val_bind` as the carc type, see example. -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. +Make sure to pass the result of create functions like *carc_X_from()* **only** to *insert()*, +*push_back()*, and *push()* functions, as it is *moved* into the container. Use *emplace()* +method for sharing existing **carc**s between containers or other existing shared pointers, +as they clone/share the input internally. 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). @@ -29,41 +30,42 @@ See similar c++ class [std::shared_ptr](https://en.cppreference.com/w/cpp/memory #define i_drop // 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> +#include <stc/carc.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 shared pointer -csptr_X csptr_X_new(i_valraw raw); // like csptr_X_from(), but construct owned value from raw. -csptr_X csptr_X_from(i_val val); // create new heap allocated object. Take ownership of val. -csptr_X csptr_X_from_ptr(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_drop(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_from(csptr_X* self, i_val val); // assign new csptr with value. Takes ownership of val. - -uint64_t csptr_X_value_hash(const i_val* x, size_t n); // hash value -int csptr_X_value_cmp(const i_val* x, const i_val* y); // compares pointer addresses if 'i_opt c_no_cmp' - // is defined. Otherwise uses 'i_cmp' or default compare. -bool csptr_X_value_eq(const i_val* x, const i_val* y); // cbox_X_value_cmp == 0 +carc_X carc_X_init(); // empty shared pointer +carc_X carc_X_new(i_valraw raw); // like carc_X_from(), but construct owned value from raw. +carc_X carc_X_from(i_val val); // create new heap allocated object. Take ownership of val. +carc_X carc_X_from_ptr(i_val* p); // create a carc from raw pointer. Takes ownership of p. + +carc_X carc_X_clone(carc_X other); // return other with increased use count +carc_X carc_X_move(carc_X* self); // transfer ownership to another carc. +void carc_X_take(carc_X* self, carc_X other); // take ownership of other. +void carc_X_copy(carc_X* self, carc_X other); // copy shared (increase use count) + +void carc_X_drop(carc_X* self); // destruct (decrease use count, free at 0) +long carc_X_use_count(carc_X ptr); + +void carc_X_reset(carc_X* self); +void carc_X_reset_from(carc_X* self, i_val val); // assign new carc with value. Takes ownership of val. + +uint64_t carc_X_value_hash(const i_val* x, size_t n); // hash value +int carc_X_value_cmp(const i_val* x, const i_val* y); // compares pointer addresses if 'i_opt c_no_cmp' + // is defined. Otherwise uses 'i_cmp' or default compare. +bool carc_X_value_eq(const i_val* x, const i_val* y); // cbox_X_value_cmp == 0 ``` ## Types and constants -| Type name | Type definition | Used to represent... | -|:-------------------|:---------------------------------------------------|:------------------------| -| `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 | +| Type name | Type definition | Used to represent... | +|:------------------|:--------------------------------------------------|:-----------------------| +| `carc_null` | `{NULL, NULL}` | Init nullptr const | +| `carc_X` | `struct { carc_X_value* get; long* use_count; }` | The carc type | +| `carc_X_value` | `i_val` | The carc element type | +| `carc_X_raw` | `i_valraw` | Convertion type | ## Example @@ -83,14 +85,14 @@ bool csptr_X_value_eq(const i_val* x, const i_val* y); // cbox_X_value // no comparison of Maps needed (or available), and // no need for atomic ref. count in single thread: #define i_opt c_no_cmp|c_no_atomic -#include <stc/csptr.h> +#include <stc/carc.h> #define i_type Stack -#define i_val_bind Arc // define i_val_bind for csptr / cbox value, not i_val +#define i_val_sptr Arc // define i_val_sptr for carc/cbox value, not i_val or i_val_bind #include <stc/cstack.h> #define i_type List -#define i_val_bind Arc // as above +#define i_val_sptr Arc // as above #include <stc/clist.h> int main() @@ -100,28 +102,28 @@ int main() { // POPULATE the stack with shared pointers to Map: Map *map; - map = Stack_push(&stack, Arc_new(Map_init()))->get; + 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_new(Map_init()))->get; + 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 the list: - map = List_push_back(&list, Arc_new(Map_init()))->get; + 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 (clones the csptr): + // Share two Maps from the stack with the list using emplace (clones the carc): 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; + 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); diff --git a/examples/box.c b/examples/box.c index ae10a89f..d97545b6 100644 --- a/examples/box.c +++ b/examples/box.c @@ -28,10 +28,9 @@ void Person_drop(Person* p) { #include <stc/cbox.h>
#define i_type Persons
-#define i_val_ref PBox // binds PBox_cmp, ...
+#define i_val_sptr PBox // informs that PBox is a smart pointer.
#include <stc/cvec.h>
-
int main()
{
c_auto (Persons, vec)
diff --git a/examples/box2.c b/examples/box2.c index 5549dade..d79ea32d 100644 --- a/examples/box2.c +++ b/examples/box2.c @@ -26,8 +26,8 @@ struct { #include <stc/cbox.h> // cbox_Rectangle
// Box in box:
-#define i_val_bind cbox_Point // NB: adviced to use i_val_arc when value is a cbox or csptr!
- // it will auto-set i_drop, i_from, i_cmp for you.
+#define i_val_sptr cbox_Point // NB: adviced to use i_val_sptr when value is a cbox or carc!
+ // it will auto-set i_drop, i_from, i_cmp for you.
#define i_opt c_no_cmp
#define i_tag BoxPoint
#include <stc/cbox.h> // cbox_BoxPoint
@@ -62,10 +62,10 @@ int main(void) { });
// The output of functions can be boxed
- boxed_point = cbox_Point_new(origin());
+ boxed_point = cbox_Point_from(origin());
// Double indirection
- box_in_a_box = cbox_BoxPoint_new(boxed_origin());
+ box_in_a_box = cbox_BoxPoint_from(boxed_origin());
printf("Point occupies %zu bytes on the stack\n",
sizeof(point));
diff --git a/examples/new_sptr.c b/examples/new_sptr.c index ce31478e..045eef77 100644 --- a/examples/new_sptr.c +++ b/examples/new_sptr.c @@ -14,29 +14,29 @@ void Person_drop(Person* p) { #define i_drop Person_drop
#define i_opt c_no_cmp
#define i_tag person
-#include <stc/csptr.h>
+#include <stc/carc.h>
// ...
#define i_val int
#define i_drop(x) printf("drop: %d\n", *(x))
-#include <stc/csptr.h>
+#include <stc/carc.h>
-#define i_val_bind csptr_int
+#define i_val_bind carc_int
#define i_tag iptr
#include <stc/cstack.h>
int main(void) {
- c_autovar (csptr_person p = csptr_person_from(Person_new("John", "Smiths")), csptr_person_drop(&p))
- c_autovar (csptr_person q = csptr_person_clone(p), csptr_person_drop(&q)) // share the pointer
+ c_autovar (carc_person p = carc_person_from(Person_new("John", "Smiths")), carc_person_drop(&p))
+ c_autovar (carc_person q = carc_person_clone(p), carc_person_drop(&q)) // share the pointer
{
printf("%s %s. uses: %lu\n", q.get->name.str, q.get->last.str, *q.use_count);
}
c_auto (cstack_iptr, stk) {
- cstack_iptr_push(&stk, csptr_int_from(10));
- cstack_iptr_push(&stk, csptr_int_from(20));
- cstack_iptr_push(&stk, csptr_int_from(30));
+ cstack_iptr_push(&stk, carc_int_from(10));
+ cstack_iptr_push(&stk, carc_int_from(20));
+ cstack_iptr_push(&stk, carc_int_from(30));
cstack_iptr_emplace(&stk, *cstack_iptr_top(&stk));
cstack_iptr_emplace(&stk, *cstack_iptr_begin(&stk).ref);
diff --git a/examples/sptr.c b/examples/sptr.c index e1d734e0..0c22bd68 100644 --- a/examples/sptr.c +++ b/examples/sptr.c @@ -25,10 +25,10 @@ void Person_drop(Person* p) { #define i_type PSPtr
#define i_val_bind Person // binds Person_cmp, ...
-#include <stc/csptr.h>
+#include <stc/carc.h>
#define i_type Persons
-#define i_val_ref PSPtr // binds PSPtr_cmp, ...
+#define i_val_sptr PSPtr // binds PSPtr_cmp, ...
#include <stc/cvec.h>
diff --git a/examples/sptr_demo.c b/examples/sptr_demo.c index a5c642b0..8626e2d4 100644 --- a/examples/sptr_demo.c +++ b/examples/sptr_demo.c @@ -5,18 +5,18 @@ void int_drop(int* x) { printf("drop: %d\n", *x);
}
-// csptr implements its own clone method using reference counting,
+// 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 'csptr_int')
+#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 <stc/csptr.h> // iref
+#include <stc/carc.h> // iref
-#define i_key_ref iref // note: use i_key_bind instead of i_key for csptr/cbox elements
+#define i_key_sptr iref // note: use i_key_bind instead of i_key for carc/cbox elements
#include <stc/csset.h> // csset_iref (like: std::set<std::shared_ptr<int>>)
-#define i_val_ref iref // note: as above.
+#define i_val_sptr iref // note: as above.
#include <stc/cvec.h> // cvec_iref (like: std::vector<std::shared_ptr<int>>)
int main()
diff --git a/examples/sptr_erase.c b/examples/sptr_erase.c index fbb141b4..d40d8fe7 100644 --- a/examples/sptr_erase.c +++ b/examples/sptr_erase.c @@ -5,14 +5,14 @@ void show_drop(int* x) { printf("drop: %d\n", *x); } #define i_type Arc
#define i_val int
#define i_drop show_drop
-// csptr/cbox will use pointer address comparison of i_val
+// 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 twodifferences by
+// to compare object values. See the two differences by
// commenting out the next line.
-#include <stc/csptr.h> // Shared pointer to int
+#include <stc/carc.h> // Shared pointer to int
#define i_type Vec
-#define i_val_ref Arc
+#define i_val_sptr Arc
#include <stc/cvec.h> // Vec: cvec<Arc>
diff --git a/examples/sptr_music.c b/examples/sptr_music.c index 1d58cc46..42bb3455 100644 --- a/examples/sptr_music.c +++ b/examples/sptr_music.c @@ -21,10 +21,10 @@ void Song_drop(Song* s) { #define i_val Song
#define i_drop Song_drop
#define i_opt c_no_cmp
-#include <stc/csptr.h>
+#include <stc/carc.h>
#define i_type SongVec
-#define i_val_ref SongPtr
+#define i_val_sptr SongPtr
#include <stc/cvec.h>
void example3()
diff --git a/examples/sptr_pthread.c b/examples/sptr_pthread.c index d71ce97d..d81d9810 100644 --- a/examples/sptr_pthread.c +++ b/examples/sptr_pthread.c @@ -11,13 +11,13 @@ struct Base int value;
} typedef Base;
+#define i_type BaseRc
#define i_val Base
-#define i_drop(x) printf("Base::~Base()\n")
-#define i_tag base
+#define i_valdrop(x) printf("Drop Base: %d\n", (x)->value)
#define i_opt c_no_cmp
-#include <stc/csptr.h>
+#include <stc/carc.h>
-void* thr(csptr_base* lp)
+void* thr(BaseRc* lp)
{
sleep(1);
static pthread_mutex_t mtx = PTHREAD_MUTEX_INITIALIZER;
@@ -25,30 +25,32 @@ void* thr(csptr_base* lp) {
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. */
- csptr_base_drop(lp);
+ BaseRc_drop(lp);
return NULL;
}
int main()
{
- csptr_base p = csptr_base_from((Base){42});
+ BaseRc p = BaseRc_from((Base){0});
printf("Created a Base\n"
" p.get() = %p, p.use_count() = %ld\n", (void*)p.get, *p.use_count);
enum {N = 3};
pthread_t t[N];
- csptr_base c[N];
+ BaseRc c[N];
c_forrange (i, N) {
- c[i] = csptr_base_clone(p);
+ c[i] = BaseRc_clone(p);
pthread_create(&t[i], NULL, (void*(*)(void*))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);
- csptr_base_reset(&p);
+ BaseRc_reset(&p);
c_forrange (i, N) pthread_join(t[i], NULL);
printf("All threads completed, the last one deleted Base\n");
diff --git a/examples/sptr_to_maps.c b/examples/sptr_to_maps.c index 64866ba3..0873d297 100644 --- a/examples/sptr_to_maps.c +++ b/examples/sptr_to_maps.c @@ -12,14 +12,14 @@ // 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 <stc/csptr.h>
+#include <stc/carc.h>
#define i_type Stack
-#define i_val_ref Arc // define i_val_bind for csptr/cbox value (not i_val)
+#define i_val_sptr Arc // define i_val_bind for carc/cbox value (not i_val)
#include <stc/cstack.h>
#define i_type List
-#define i_val_ref Arc // as above
+#define i_val_sptr Arc // as above
#include <stc/clist.h>
int main()
@@ -44,7 +44,7 @@ int main() {"Steve", 1979}, {"Rick", 1974}, {"Tracy", 2003}
});
- // Share two Maps from the stack with the list using emplace (clone the csptr):
+ // 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]));
diff --git a/include/stc/csptr.h b/include/stc/carc.h index 0718a4cc..505b47d9 100644 --- a/include/stc/csptr.h +++ b/include/stc/carc.h @@ -21,7 +21,7 @@ * SOFTWARE.
*/
-/* csptr: shared_ptr type
+/* carc: atomic reference counted shared_ptr
#include <stc/cstr.h>
typedef struct { cstr name, last; } Person;
@@ -37,19 +37,19 @@ void Person_drop(Person* p) { #define i_tag person
#define i_val Person
#define i_valdrop Person_drop
-#include <stc/csptr.h>
+#include <stc/carc.h>
int main() {
- csptr_person p = csptr_person_new(Person_new("John", "Smiths"));
- csptr_person q = csptr_person_clone(p); // share the pointer
+ carc_person p = carc_person_from(Person_new("John", "Smiths"));
+ carc_person q = carc_person_clone(p); // share the pointer
printf("%s %s. uses: %zu\n", q.get->name.str, q.get->last.str, *q.use_count);
- c_drop(csptr_person, &p, &q);
+ c_drop(carc_person, &p, &q);
}
*/
-#ifndef CSPTR_H_INCLUDED
-#define CSPTR_H_INCLUDED
+#ifndef CARC_H_INCLUDED
+#define CARC_H_INCLUDED
#include "ccommon.h"
#include "forward.h"
#include <stdlib.h>
@@ -67,12 +67,12 @@ int main() { #define c_atomic_dec_and_test(v) (atomic_fetch_sub(v, 1) == 1)
#endif
-#define csptr_null {NULL, NULL}
-#define _cx_csptr_rep struct _cx_memb(_rep_)
-#endif // CSPTR_H_INCLUDED
+#define carc_null {NULL, NULL}
+#define _cx_carc_rep struct _cx_memb(_rep_)
+#endif // CARC_H_INCLUDED
#ifndef _i_prefix
-#define _i_prefix csptr_
+#define _i_prefix carc_
#endif
#define _i_has_internal_clone
#include "template.h"
@@ -86,9 +86,9 @@ typedef i_valraw _cx_raw; #define _i_atomic_dec_and_test(v) !(--*(v))
#endif
#if !c_option(c_is_fwd)
-_cx_deftypes(_c_csptr_types, _cx_self, i_val);
+_cx_deftypes(_c_carc_types, _cx_self, i_val);
#endif
-_cx_csptr_rep { long counter; i_val value; };
+_cx_carc_rep { long counter; i_val value; };
STC_INLINE _cx_self
_cx_memb(_init)(void) { return c_make(_cx_self){NULL, NULL}; }
@@ -105,7 +105,7 @@ _cx_memb(_from_ptr)(_cx_value* p) { STC_INLINE _cx_self
_cx_memb(_from)(i_val val) {
- _cx_self ptr; _cx_csptr_rep *rep = c_alloc(_cx_csptr_rep);
+ _cx_self ptr; _cx_carc_rep *rep = c_alloc(_cx_carc_rep);
*(ptr.use_count = &rep->counter) = 1;
*(ptr.get = &rep->value) = val;
return ptr;
@@ -126,7 +126,7 @@ STC_INLINE void _cx_memb(_drop)(_cx_self* self) {
if (self->use_count && _i_atomic_dec_and_test(self->use_count)) {
i_valdrop(self->get);
- if (self->get != &((_cx_csptr_rep *)self->use_count)->value)
+ if (self->get != &((_cx_carc_rep *)self->use_count)->value)
c_free(self->get);
c_free(self->use_count);
}
diff --git a/include/stc/ccommon.h b/include/stc/ccommon.h index ac6e9d31..4e2ee97d 100644 --- a/include/stc/ccommon.h +++ b/include/stc/ccommon.h @@ -199,7 +199,7 @@ STC_INLINE uint64_t c_default_hash(const void* key, size_t len) { for (size_t index = 0; index < _n; ++index) \
{ const T v = _c_arr[index]; method; } \
} while (0)
-#define c_apply_it(v, method, C, ...) do { \
+#define c_apply_cnt(v, method, C, ...) do { \
size_t index = 0; \
c_foreach (_it, C, __VA_ARGS__) \
{ const C##_value v = *_it.ref; method; ++index; } \
diff --git a/include/stc/forward.h b/include/stc/forward.h index bf2ba698..9a37297e 100644 --- a/include/stc/forward.h +++ b/include/stc/forward.h @@ -34,7 +34,7 @@ #define forward_cset(CX, KEY) _c_chash_types(CX, cset, KEY, KEY, c_false, c_true)
#define forward_csset(CX, KEY) _c_aatree_types(CX, KEY, KEY, c_false, c_true)
#define forward_cbox(CX, VAL) _c_cbox_types(CX, VAL)
-#define forward_csptr(CX, VAL) _c_csptr_types(CX, VAL)
+#define forward_carc(CX, VAL) _c_carc_types(CX, VAL)
#define forward_cpque(CX, VAL) _c_cpque_types(CX, VAL)
#define forward_cstack(CX, VAL) _c_cstack_types(CX, VAL)
#define forward_cqueue(CX, VAL) _c_cdeq_types(CX, VAL)
@@ -132,7 +132,7 @@ SELF##_value* get; \
} SELF
-#define _c_csptr_types(SELF, VAL) \
+#define _c_carc_types(SELF, VAL) \
typedef VAL SELF##_value; \
\
typedef struct { \
diff --git a/include/stc/template.h b/include/stc/template.h index 1d1551fa..5efe3772 100644 --- a/include/stc/template.h +++ b/include/stc/template.h @@ -61,9 +61,9 @@ #ifndef i_tag
#define i_tag str
#endif
-#elif defined i_key_ref
- #define i_key_bind i_key_ref
- #define i_keyraw c_PASTE(i_key_ref, _value)
+#elif defined i_key_sptr
+ #define i_key_bind i_key_sptr
+ #define i_keyraw c_PASTE(i_key_sptr, _value)
#endif
#ifdef i_key_bind
@@ -120,9 +120,9 @@ #if !defined i_tag && !defined i_key
#define i_tag str
#endif
-#elif defined i_val_ref
- #define i_val_bind i_val_ref
- #define i_valraw c_PASTE(i_val_ref, _value)
+#elif defined i_val_sptr
+ #define i_val_bind i_val_sptr
+ #define i_valraw c_PASTE(i_val_sptr, _value)
#endif
#ifdef i_val_bind
@@ -219,7 +219,7 @@ #undef i_val
#undef i_val_str
-#undef i_val_ref
+#undef i_val_sptr
#undef i_val_bind
#undef i_valraw
#undef i_valfrom
@@ -228,7 +228,7 @@ #undef i_key
#undef i_key_str
-#undef i_key_ref
+#undef i_key_sptr
#undef i_key_bind
#undef i_keyraw
#undef i_keyfrom
|
