From b578aade0c44e215b8338db6eef15a74c09a2f24 Mon Sep 17 00:00:00 2001 From: Tyge Løvset Date: Fri, 17 Sep 2021 00:17:25 +0200 Subject: Added shared pointer csptr support + test. --- include/stc/csptr.h | 192 ++++++++++++++++++++++--------------------- include/stc/forward.h | 4 +- include/stc/test_new_csptr.c | 45 ++++++++++ 3 files changed, 146 insertions(+), 95 deletions(-) create mode 100644 include/stc/test_new_csptr.c diff --git a/include/stc/csptr.h b/include/stc/csptr.h index e7dd2485..14352c00 100644 --- a/include/stc/csptr.h +++ b/include/stc/csptr.h @@ -20,14 +20,8 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE * SOFTWARE. */ -#ifndef CSPTR_H_INCLUDED -#define CSPTR_H_INCLUDED - -#include "ccommon.h" /* csptr: shared_ptr type - -#include #include typedef struct { cstr name, last; } Person; @@ -40,7 +34,10 @@ void Person_del(Person* p) { c_del(cstr, &p->name, &p->last); } -using_csptr(person, Person, c_no_compare, Person_del); +#define i_tag person +#define i_val Person +#define i_valdel Person_del +#include int main() { csptr_person p = csptr_person_make(Person_init("John", "Smiths")); @@ -50,6 +47,12 @@ int main() { c_del(csptr_person, &p, &q); } */ + +#ifndef CSPTR_H_INCLUDED +#define CSPTR_H_INCLUDED +#include "ccommon.h" +#include "forward.h" + typedef long atomic_count_t; #if defined(__GNUC__) || defined(__clang__) #define c_atomic_increment(v) (void)__atomic_add_fetch(v, 1, __ATOMIC_SEQ_CST) @@ -68,93 +71,96 @@ typedef long atomic_count_t; } #endif -#define forward_csptr(X, i_val) _csptr_types(csptr_##X, i_val) #define csptr_null {NULL, NULL} +#endif // CSPTR_H_INCLUDED +#ifndef i_prefix +#define i_prefix csptr_ +#endif +#include "template.h" - defTypes( _csptr_types(Self, i_val); ) \ - struct cx_memb(_rep_) {atomic_count_t cnt; cx_value_t val; }; \ -\ - STC_INLINE Self \ - cx_memb(_init)() { return c_make(Self){NULL, NULL}; } \ -\ - STC_INLINE atomic_count_t \ - cx_memb(_use_count)(Self ptr) { return ptr.use_count ? *ptr.use_count : 0; } \ -\ - STC_INLINE Self \ - cx_memb(_from)(cx_value_t* p) { \ - Self ptr = {p}; \ - if (p) *(ptr.use_count = c_new(atomic_count_t)) = 1; \ - return ptr; \ - } \ -\ - STC_INLINE Self \ - cx_memb(_make)(cx_value_t val) { \ - Self ptr; struct cx_memb(_rep_) *rep = c_new(struct cx_memb(_rep_)); \ - *(ptr.use_count = &rep->cnt) = 1; \ - *(ptr.get = &rep->val) = val; \ - return ptr; \ - } \ -\ - STC_INLINE Self \ - cx_memb(_clone)(Self ptr) { \ - if (ptr.use_count) c_atomic_increment(ptr.use_count); \ - return ptr; \ - } \ -\ - STC_INLINE Self \ - cx_memb(_move)(Self* self) { \ - Self ptr = *self; \ - self->get = NULL, self->use_count = NULL; \ - return ptr; \ - } \ -\ - STC_INLINE void \ - cx_memb(_del)(Self* self) { \ - if (self->use_count && c_atomic_decrement(self->use_count) == 0) { \ - i_valdel(self->get); \ - if (self->get != &((struct cx_memb(_rep_)*)self->use_count)->val) c_free(self->get); \ - c_free(self->use_count); \ - } \ - } \ -\ - STC_INLINE void \ - cx_memb(_reset)(Self* self) { \ - cx_memb(_del)(self); \ - self->use_count = NULL, self->get = NULL; \ - } \ -\ - STC_INLINE cx_value_t* \ - cx_memb(_reset_with)(Self* self, cx_value_t* p) { \ - cx_memb(_del)(self); \ - *self = cx_memb(_from)(p); \ - return self->get; \ - } \ -\ - STC_INLINE cx_value_t* \ - cx_memb(_reset_make)(Self* self, cx_value_t val) { \ - cx_memb(_del)(self); \ - *self = cx_memb(_make)(val); \ - return self->get; \ - } \ -\ - STC_INLINE cx_value_t* \ - cx_memb(_copy)(Self* self, Self ptr) { \ - cx_memb(_del)(self); \ - *self = ptr; \ - if (self->use_count) c_atomic_increment(self->use_count); \ - return self->get; \ - } \ -\ - STC_INLINE int \ - cx_memb(_compare)(const Self* x, const Self* y) { \ - return i_cmp(x->get, y->get); \ - } \ -\ - STC_INLINE bool \ - cx_memb(_equals)(const Self* x, const Self* y) { \ - return i_cmp(x->get, y->get) == 0; \ - } \ - struct stc_trailing_semicolon - +#ifndef i_fwd +cx_deftypes(_c_csptr_types, Self, i_val); #endif +#define cx_csptr_rep struct cx_memb(_rep_) +cx_csptr_rep { atomic_count_t cnt; cx_value_t val; }; + +STC_INLINE Self +cx_memb(_init)(void) { return c_make(Self){NULL, NULL}; } + +STC_INLINE atomic_count_t +cx_memb(_use_count)(Self ptr) { return ptr.use_count ? *ptr.use_count : 0; } + +STC_INLINE Self +cx_memb(_from)(cx_value_t* p) { + Self ptr = {p}; + if (p) *(ptr.use_count = c_new(atomic_count_t)) = 1; + return ptr; +} + +STC_INLINE Self +cx_memb(_make)(cx_value_t val) { + Self ptr; cx_csptr_rep *rep = c_new(cx_csptr_rep); + *(ptr.use_count = &rep->cnt) = 1; + *(ptr.get = &rep->val) = val; + return ptr; +} + +STC_INLINE Self +cx_memb(_clone)(Self ptr) { + if (ptr.use_count) c_atomic_increment(ptr.use_count); + return ptr; +} + +STC_INLINE Self +cx_memb(_move)(Self* self) { + Self ptr = *self; + self->get = NULL, self->use_count = NULL; + return ptr; +} + +STC_INLINE void +cx_memb(_del)(Self* self) { + if (self->use_count && c_atomic_decrement(self->use_count) == 0) { + i_valdel(self->get); + if (self->get != &((cx_csptr_rep*)self->use_count)->val) + c_free(self->get); + c_free(self->use_count); + } +} + +STC_INLINE void +cx_memb(_reset)(Self* self) { + cx_memb(_del)(self); + self->use_count = NULL, self->get = NULL; +} + +STC_INLINE cx_value_t* +cx_memb(_reset_with)(Self* self, cx_value_t* p) { + cx_memb(_del)(self); + *self = cx_memb(_from)(p); + return self->get; +} + +STC_INLINE cx_value_t* +cx_memb(_reset_make)(Self* self, cx_value_t val) { + cx_memb(_del)(self); + *self = cx_memb(_make)(val); + return self->get; +} + +STC_INLINE cx_value_t* +cx_memb(_copy)(Self* self, Self ptr) { + cx_memb(_del)(self); + *self = ptr; + if (self->use_count) c_atomic_increment(self->use_count); + return self->get; +} + +STC_INLINE int +cx_memb(_compare)(const Self* x, const Self* y) { + return i_cmp(x->get, y->get); +} + +#undef cx_csptr_rep +#include "template.h" \ No newline at end of file diff --git a/include/stc/forward.h b/include/stc/forward.h index 5877d390..d524d088 100644 --- a/include/stc/forward.h +++ b/include/stc/forward.h @@ -33,7 +33,7 @@ #define forward_csmap(TAG, KEY, VAL) _c_aatree_types(csmap_##TAG, KEY, VAL, c_true, c_false) #define forward_cset(TAG, KEY) _c_chash_types(cset_##TAG, cset, KEY, KEY, c_false, c_true) #define forward_csset(TAG, KEY) _c_aatree_types(csset_##TAG, KEY, KEY, c_false, c_true) -#define forward_csptr(TAG, VAL) _csptr_types(csptr_##TAG, VAL) +#define forward_csptr(TAG, VAL) _c_csptr_types(csptr_##TAG, VAL) #define forward_cpque(TAG, VAL) _c_cpque_types(cpque_##TAG, VAL) #define forward_cstack(TAG, VAL) _c_cstack_types(cstack_##TAG, VAL) #define forward_cqueue(TAG, VAL) _c_cdeq_types(cqueue_##TAG, VAL) @@ -125,7 +125,7 @@ SELF##_node_t *nodes; \ } SELF -#define _csptr_types(SELF, VAL) \ +#define _c_csptr_types(SELF, VAL) \ typedef VAL SELF##_value_t; \ \ typedef struct { \ diff --git a/include/stc/test_new_csptr.c b/include/stc/test_new_csptr.c new file mode 100644 index 00000000..2ef31790 --- /dev/null +++ b/include/stc/test_new_csptr.c @@ -0,0 +1,45 @@ +#include + +#include +forward_csptr(person, struct Person); + +struct Person { cstr name, last; } typedef Person; + +Person Person_init(const char* name, const char* last) { + return (Person){.name = cstr_from(name), .last = cstr_from(last)}; +} +void Person_del(Person* p) { + printf("del: %s %s\n", p->name.str, p->last.str); + c_del(cstr, &p->name, &p->last); +} + +#define F_tag person +#define i_val Person +#define i_valdel Person_del +#define i_cmp c_no_compare +#include + +#define i_val int +#include + +#define i_tag iptr +#define i_key csptr_int +#define i_cmp csptr_int_compare +#include + +int main(void) { + c_forvar (csptr_person p = csptr_person_make(Person_init("John", "Smiths")), csptr_person_del(&p)) + c_forvar (csptr_person q = csptr_person_clone(p), csptr_person_del(&q)) // share the pointer + { + printf("%s %s. uses: %zu\n", q.get->name.str, q.get->last.str, *q.use_count); + + c_forauto (csset_iptr, map) { + csset_iptr_insert(&map, csptr_int_make(2021)); + csset_iptr_insert(&map, csptr_int_make(2033)); + + c_foreach (i, csset_iptr, map) + printf(" %d", *i.ref->get); + puts(""); + } + } +} \ No newline at end of file -- cgit v1.2.3