From 79c83eba7933f49e766dbeb85f9c40ee17e06edf Mon Sep 17 00:00:00 2001 From: Tyge Løvset Date: Wed, 22 Dec 2021 12:35:36 +0100 Subject: 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. --- include/stc/carc.h | 201 +++++++++++++++++++++++++++++++++++++++++++++++++ include/stc/ccommon.h | 2 +- include/stc/csptr.h | 201 ------------------------------------------------- include/stc/forward.h | 4 +- include/stc/template.h | 16 ++-- 5 files changed, 212 insertions(+), 212 deletions(-) create mode 100644 include/stc/carc.h delete mode 100644 include/stc/csptr.h (limited to 'include') diff --git a/include/stc/carc.h b/include/stc/carc.h new file mode 100644 index 00000000..505b47d9 --- /dev/null +++ b/include/stc/carc.h @@ -0,0 +1,201 @@ +/* MIT License + * + * Copyright (c) 2021 Tyge Løvset, NORCE, www.norceresearch.no + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +/* carc: atomic reference counted shared_ptr +#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)}; +} +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_tag person +#define i_val Person +#define i_valdrop Person_drop +#include + +int main() { + 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(carc_person, &p, &q); +} +*/ + +#ifndef CARC_H_INCLUDED +#define CARC_H_INCLUDED +#include "ccommon.h" +#include "forward.h" +#include + +#if defined(__GNUC__) || defined(__clang__) + #define c_atomic_inc(v) (void)__atomic_add_fetch(v, 1, __ATOMIC_SEQ_CST) + #define c_atomic_dec_and_test(v) !__atomic_sub_fetch(v, 1, __ATOMIC_SEQ_CST) +#elif defined(_MSC_VER) + #include + #define c_atomic_inc(v) (void)_InterlockedIncrement(v) + #define c_atomic_dec_and_test(v) !_InterlockedDecrement(v) +#else + #include + #define c_atomic_inc(v) (void)atomic_fetch_add(v, 1) + #define c_atomic_dec_and_test(v) (atomic_fetch_sub(v, 1) == 1) +#endif + +#define carc_null {NULL, NULL} +#define _cx_carc_rep struct _cx_memb(_rep_) +#endif // CARC_H_INCLUDED + +#ifndef _i_prefix +#define _i_prefix carc_ +#endif +#define _i_has_internal_clone +#include "template.h" +typedef i_valraw _cx_raw; + +#if !c_option(c_no_atomic) + #define _i_atomic_inc(v) c_atomic_inc(v) + #define _i_atomic_dec_and_test(v) c_atomic_dec_and_test(v) +#else + #define _i_atomic_inc(v) (void)(++*(v)) + #define _i_atomic_dec_and_test(v) !(--*(v)) +#endif +#if !c_option(c_is_fwd) +_cx_deftypes(_c_carc_types, _cx_self, i_val); +#endif +_cx_carc_rep { long counter; i_val value; }; + +STC_INLINE _cx_self +_cx_memb(_init)(void) { return c_make(_cx_self){NULL, NULL}; } + +STC_INLINE long +_cx_memb(_use_count)(_cx_self ptr) { return ptr.use_count ? *ptr.use_count : 0; } + +STC_INLINE _cx_self +_cx_memb(_from_ptr)(_cx_value* p) { + _cx_self ptr = {p}; + if (p) *(ptr.use_count = c_alloc(long)) = 1; + return ptr; +} + +STC_INLINE _cx_self +_cx_memb(_from)(i_val val) { + _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; +} + +STC_INLINE i_val _cx_memb(_toraw)(const _cx_self* self) { + return *self->get; +} + +STC_INLINE _cx_self +_cx_memb(_move)(_cx_self* self) { + _cx_self ptr = *self; + self->get = NULL, self->use_count = NULL; + return ptr; +} + +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_carc_rep *)self->use_count)->value) + c_free(self->get); + c_free(self->use_count); + } +} + +STC_INLINE void +_cx_memb(_reset)(_cx_self* self) { + _cx_memb(_drop)(self); + self->use_count = NULL, self->get = NULL; +} + +STC_INLINE void +_cx_memb(_reset_from)(_cx_self* self, i_val val) { + _cx_memb(_drop)(self); + *self = _cx_memb(_from)(val); +} + +#if !c_option(c_no_clone) && !defined _i_valraw_default + STC_INLINE _cx_self _cx_memb(_new)(i_valraw raw) { + return _cx_memb(_from)(i_valfrom(raw)); + } +#endif + +// does not use i_valfrom, so we can bypass c_no_clone +STC_INLINE _cx_self +_cx_memb(_clone)(_cx_self ptr) { + if (ptr.use_count) _i_atomic_inc(ptr.use_count); + return ptr; +} + +STC_INLINE void +_cx_memb(_copy)(_cx_self* self, _cx_self ptr) { + if (ptr.use_count) _i_atomic_inc(ptr.use_count); + _cx_memb(_drop)(self); + *self = ptr; +} + +STC_INLINE void +_cx_memb(_take)(_cx_self* self, _cx_self ptr) { + if (self->get != ptr.get) _cx_memb(_drop)(self); + *self = ptr; +} + +STC_INLINE uint64_t +_cx_memb(_value_hash)(const _cx_value* x, size_t n) { + #if c_option(c_no_cmp) && UINTPTR_MAX == UINT64_MAX + return c_hash64(&x, 8); + #elif c_option(c_no_cmp) + return c_hash32(&x, 4); + #else + i_valraw rx = i_valto(x); + return i_hash(&rx, sizeof rx); + #endif +} + +STC_INLINE int +_cx_memb(_value_cmp)(const _cx_value* x, const _cx_value* y) { + #if c_option(c_no_cmp) + return c_default_cmp(&x, &y); + #else + i_valraw rx = i_valto(x), ry = i_valto(x); + return i_cmp(&rx, &ry); + #endif +} + +STC_INLINE bool +_cx_memb(_value_eq)(const _cx_value* x, const _cx_value* y) { + return !_cx_memb(_value_cmp)(x, y); +} +#undef _i_atomic_inc +#undef _i_atomic_dec_and_test +#include "template.h" 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/csptr.h b/include/stc/csptr.h deleted file mode 100644 index 0718a4cc..00000000 --- a/include/stc/csptr.h +++ /dev/null @@ -1,201 +0,0 @@ -/* MIT License - * - * Copyright (c) 2021 Tyge Løvset, NORCE, www.norceresearch.no - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -/* csptr: shared_ptr 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)}; -} -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_tag person -#define i_val Person -#define i_valdrop Person_drop -#include - -int main() { - csptr_person p = csptr_person_new(Person_new("John", "Smiths")); - csptr_person q = csptr_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); -} -*/ - -#ifndef CSPTR_H_INCLUDED -#define CSPTR_H_INCLUDED -#include "ccommon.h" -#include "forward.h" -#include - -#if defined(__GNUC__) || defined(__clang__) - #define c_atomic_inc(v) (void)__atomic_add_fetch(v, 1, __ATOMIC_SEQ_CST) - #define c_atomic_dec_and_test(v) !__atomic_sub_fetch(v, 1, __ATOMIC_SEQ_CST) -#elif defined(_MSC_VER) - #include - #define c_atomic_inc(v) (void)_InterlockedIncrement(v) - #define c_atomic_dec_and_test(v) !_InterlockedDecrement(v) -#else - #include - #define c_atomic_inc(v) (void)atomic_fetch_add(v, 1) - #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 - -#ifndef _i_prefix -#define _i_prefix csptr_ -#endif -#define _i_has_internal_clone -#include "template.h" -typedef i_valraw _cx_raw; - -#if !c_option(c_no_atomic) - #define _i_atomic_inc(v) c_atomic_inc(v) - #define _i_atomic_dec_and_test(v) c_atomic_dec_and_test(v) -#else - #define _i_atomic_inc(v) (void)(++*(v)) - #define _i_atomic_dec_and_test(v) !(--*(v)) -#endif -#if !c_option(c_is_fwd) -_cx_deftypes(_c_csptr_types, _cx_self, i_val); -#endif -_cx_csptr_rep { long counter; i_val value; }; - -STC_INLINE _cx_self -_cx_memb(_init)(void) { return c_make(_cx_self){NULL, NULL}; } - -STC_INLINE long -_cx_memb(_use_count)(_cx_self ptr) { return ptr.use_count ? *ptr.use_count : 0; } - -STC_INLINE _cx_self -_cx_memb(_from_ptr)(_cx_value* p) { - _cx_self ptr = {p}; - if (p) *(ptr.use_count = c_alloc(long)) = 1; - return ptr; -} - -STC_INLINE _cx_self -_cx_memb(_from)(i_val val) { - _cx_self ptr; _cx_csptr_rep *rep = c_alloc(_cx_csptr_rep); - *(ptr.use_count = &rep->counter) = 1; - *(ptr.get = &rep->value) = val; - return ptr; -} - -STC_INLINE i_val _cx_memb(_toraw)(const _cx_self* self) { - return *self->get; -} - -STC_INLINE _cx_self -_cx_memb(_move)(_cx_self* self) { - _cx_self ptr = *self; - self->get = NULL, self->use_count = NULL; - return ptr; -} - -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) - c_free(self->get); - c_free(self->use_count); - } -} - -STC_INLINE void -_cx_memb(_reset)(_cx_self* self) { - _cx_memb(_drop)(self); - self->use_count = NULL, self->get = NULL; -} - -STC_INLINE void -_cx_memb(_reset_from)(_cx_self* self, i_val val) { - _cx_memb(_drop)(self); - *self = _cx_memb(_from)(val); -} - -#if !c_option(c_no_clone) && !defined _i_valraw_default - STC_INLINE _cx_self _cx_memb(_new)(i_valraw raw) { - return _cx_memb(_from)(i_valfrom(raw)); - } -#endif - -// does not use i_valfrom, so we can bypass c_no_clone -STC_INLINE _cx_self -_cx_memb(_clone)(_cx_self ptr) { - if (ptr.use_count) _i_atomic_inc(ptr.use_count); - return ptr; -} - -STC_INLINE void -_cx_memb(_copy)(_cx_self* self, _cx_self ptr) { - if (ptr.use_count) _i_atomic_inc(ptr.use_count); - _cx_memb(_drop)(self); - *self = ptr; -} - -STC_INLINE void -_cx_memb(_take)(_cx_self* self, _cx_self ptr) { - if (self->get != ptr.get) _cx_memb(_drop)(self); - *self = ptr; -} - -STC_INLINE uint64_t -_cx_memb(_value_hash)(const _cx_value* x, size_t n) { - #if c_option(c_no_cmp) && UINTPTR_MAX == UINT64_MAX - return c_hash64(&x, 8); - #elif c_option(c_no_cmp) - return c_hash32(&x, 4); - #else - i_valraw rx = i_valto(x); - return i_hash(&rx, sizeof rx); - #endif -} - -STC_INLINE int -_cx_memb(_value_cmp)(const _cx_value* x, const _cx_value* y) { - #if c_option(c_no_cmp) - return c_default_cmp(&x, &y); - #else - i_valraw rx = i_valto(x), ry = i_valto(x); - return i_cmp(&rx, &ry); - #endif -} - -STC_INLINE bool -_cx_memb(_value_eq)(const _cx_value* x, const _cx_value* y) { - return !_cx_memb(_value_cmp)(x, y); -} -#undef _i_atomic_inc -#undef _i_atomic_dec_and_test -#include "template.h" 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 -- cgit v1.2.3