summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
-rw-r--r--include/stc/csptr.h192
-rw-r--r--include/stc/forward.h4
-rw-r--r--include/stc/test_new_csptr.c45
3 files changed, 146 insertions, 95 deletions
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 <stc/csptr.h>
#include <stc/cstr.h>
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 <stc/csptr.h>
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 <stc/cstr.h>
+
+#include <stc/forward.h>
+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 <stc/csptr.h>
+
+#define i_val int
+#include <stc/csptr.h>
+
+#define i_tag iptr
+#define i_key csptr_int
+#define i_cmp csptr_int_compare
+#include <stc/csset.h>
+
+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