From 31ec9ba3359864a780ac64f53acee33fb5cb2b5a Mon Sep 17 00:00:00 2001 From: Tyge Løvset Date: Wed, 23 Sep 2020 22:18:51 +0200 Subject: Some internal restructuring. Added shared_ptr like struct type: csptr.h --- examples/benchmark.c | 25 ++++++------ stc/carray.h | 12 +++--- stc/cdefs.h | 3 +- stc/clist.h | 4 +- stc/cmap.h | 4 +- stc/cpqueue.h | 2 +- stc/cqueue.h | 2 +- stc/csptr.h | 113 +++++++++++++++++++++++++++++++++++++++++++++++++++ stc/cstack.h | 2 +- stc/cvec.h | 4 +- 10 files changed, 143 insertions(+), 28 deletions(-) create mode 100644 stc/csptr.h diff --git a/examples/benchmark.c b/examples/benchmark.c index 691d585b..d1167eb4 100644 --- a/examples/benchmark.c +++ b/examples/benchmark.c @@ -151,8 +151,8 @@ int rr = RR; erased += M##_ERASE(X, RAND(rr)); \ } \ difference = clock() - before; \ - printf(#M ": size: %zu, buckets: %8zu, time: %5.02f, sum: %zu, erased %zu\n", \ - (size_t) M##_SIZE(X), (size_t) M##_BUCKETS(X), (float) difference / CLOCKS_PER_SEC, checksum, erased); \ + printf(#M ": time: %5.02f, sum: %zu, erased %zu, size: %zu, buckets: %8zu\n", \ + (float) difference / CLOCKS_PER_SEC, checksum, erased, (size_t) M##_SIZE(X), (size_t) M##_BUCKETS(X)); \ M##_CLEAR(X); \ } @@ -166,8 +166,8 @@ int rr = RR; for (size_t i = 0; i < N2; ++i) \ erased += M##_ERASE(X, i); \ difference = clock() - before; \ - printf(#M ": size: %zu, buckets: %8zu, time: %5.02f, erased %zu\n", \ - (size_t) M##_SIZE(X), (size_t) M##_BUCKETS(X), (float) difference / CLOCKS_PER_SEC, erased); \ + printf(#M ": time: %5.02f, erased %zu, size: %zu, buckets: %8zu\n", \ + (float) difference / CLOCKS_PER_SEC, erased, (size_t) M##_SIZE(X), (size_t) M##_BUCKETS(X)); \ M##_CLEAR(X); \ } @@ -183,8 +183,8 @@ int rr = RR; for (size_t i = 0; i < N3; ++i) \ erased += M##_ERASE(X, RAND(rr)); \ difference = clock() - before; \ - printf(#M ": size: %zu, buckets: %8zu, time: %5.02f, erased %zu\n", \ - (size_t) M##_SIZE(X), (size_t) M##_BUCKETS(X), (float) difference / CLOCKS_PER_SEC, erased); \ + printf(#M ": time: %5.02f, erased %zu, size: %zu, buckets: %8zu\n", \ + (float) difference / CLOCKS_PER_SEC, erased, (size_t) M##_SIZE(X), (size_t) M##_BUCKETS(X)); \ M##_CLEAR(X); \ } @@ -199,21 +199,22 @@ int rr = RR; for (int k=0; k<5; k++) M##_FOR (X, i) \ sum += M##_ITEM(X, i); \ difference = clock() - before; \ - printf(#M ": size: %zu, buckets: %8zu, time: %5.02f, sum %zu\n", \ - (size_t) M##_SIZE(X), (size_t) M##_BUCKETS(X), (float) difference / CLOCKS_PER_SEC, sum); \ + printf(#M ": time: %5.02f, sum %zu, size: %zu, buckets: %8zu\n", \ + (float) difference / CLOCKS_PER_SEC, sum, (size_t) M##_SIZE(X), (size_t) M##_BUCKETS(X)); \ M##_CLEAR(X); \ } - -#ifndef __cplusplus -#define RUN_TEST(n) MAP_TEST##n(CMAP, ii) /*MAP_TEST##n(KMAP, ii)*/ -#else +#ifdef __cplusplus #define RUN_TEST(n) MAP_TEST##n(CMAP, ii) MAP_TEST##n(KMAP, ii) MAP_TEST##n(UMAP, ii) MAP_TEST##n(SMAP, ii) \ MAP_TEST##n(BMAP, ii) MAP_TEST##n(FMAP, ii) MAP_TEST##n(RMAP, ii) MAP_TEST##n(HMAP, ii) #define RUNX_TEST(n) MAP_TEST##n(CMAP, ii) /*MAP_TEST##n(KMAP, ii)*/ MAP_TEST##n(UMAP, ii) MAP_TEST##n(SMAP, ii) \ MAP_TEST##n(BMAP, ii) MAP_TEST##n(FMAP, ii) /*MAP_TEST##n(RMAP, ii)*/ MAP_TEST##n(HMAP, ii) +#else +#define RUN_TEST(n) MAP_TEST##n(CMAP, ii) MAP_TEST##n(KMAP, ii) +#define RUNX_TEST(n) MAP_TEST##n(CMAP, ii) #endif + int main(int argc, char* argv[]) { rr = argc == 2 ? atoi(argv[1]) : RR; diff --git a/stc/carray.h b/stc/carray.h index 4e164f42..3fd7f532 100644 --- a/stc/carray.h +++ b/stc/carray.h @@ -101,20 +101,20 @@ STC_INLINE size_t _carray3_size(const size_t* zdim) { typedef Value carray1##X##_value_t; \ typedef carray1##X##_value_t carray2##X##_value_t, carray3##X##_value_t; \ \ - typedef struct carray1##X { \ + typedef struct { \ Value *data; \ size_t _xdim; \ - } carray1##X; \ + } carray1##X, carray1##X##_t; \ \ - typedef struct carray2##X { \ + typedef struct { \ Value *data; \ size_t _xdim, _yxdim; \ - } carray2##X; \ + } carray2##X, carray2##X##_t; \ \ - typedef struct carray3##X { \ + typedef struct { \ Value *data; \ size_t _xdim, _yxdim, _zdim; \ - } carray3##X; \ + } carray3##X, carray3##X##_t; \ \ using_carray_common(1, X, Value, valueDestroy) \ using_carray_common(2, X, Value, valueDestroy) \ diff --git a/stc/cdefs.h b/stc/cdefs.h index 7b06f74d..7034f304 100644 --- a/stc/cdefs.h +++ b/stc/cdefs.h @@ -77,6 +77,7 @@ enum {_c_max_buffer = 512}; #define c_default_from_raw(x) (x) #define c_default_to_raw(ptr) (*(ptr)) #define c_default_del(ptr) ((void) (ptr)) +#define c_pointer_del(pptr) free(*(pptr)) #define c_foreach(...) c_MACRO_OVERLOAD(c_foreach, __VA_ARGS__) #define c_foreach_3(it, ctype, cnt) \ @@ -98,7 +99,7 @@ enum {_c_max_buffer = 512}; } while (0) #define c_del(ctype, ...) do { \ - struct ctype* __arr[] = {__VA_ARGS__}; \ + ctype##_t* __arr[] = {__VA_ARGS__}; \ for (size_t i=0; i */ \ \ - typedef struct ctype cpqueue_##X; \ + typedef ctype##_t cpqueue_##X, cpqueue_##X##_t; \ typedef ctype##_value_t cpqueue_##X##_value_t; \ typedef ctype##_rawvalue_t cpqueue_##X##_rawvalue_t; \ typedef ctype##_input_t cpqueue_##X##_input_t; \ diff --git a/stc/cqueue.h b/stc/cqueue.h index 27346de6..9ccb69f1 100644 --- a/stc/cqueue.h +++ b/stc/cqueue.h @@ -60,7 +60,7 @@ #define using_cqueue(X, ctype) \ \ - typedef struct ctype cqueue_##X; \ + typedef ctype##_t cqueue_##X, cqueue_##X##_t; \ typedef ctype##_value_t cqueue_##X##_value_t; \ typedef ctype##_rawvalue_t cqueue_##X##_rawvalue_t; \ typedef ctype##_input_t cqueue_##X##_input_t; \ diff --git a/stc/csptr.h b/stc/csptr.h new file mode 100644 index 00000000..8e09f36e --- /dev/null +++ b/stc/csptr.h @@ -0,0 +1,113 @@ +/* MIT License + * + * Copyright (c) 2020 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. + */ +#ifndef CSPTR__H__ +#define CSPTR__H__ + +#include "cdefs.h" + +/* csptr: std::shared_ptr -like type: */ +/* +#include +#include + +typedef struct { cstr_t name, last; } Person; + +void Person_del(Person* p) { + printf("del: %s\n", p->name.str); + c_del(cstr, &p->name, &p->last); +} + +using_csptr(pe, Person, Person_del); + +int main() { + csptr_pe p = csptr_pe_make(c_new(Person)); + p.get->name = cstr("Joe"); + p.get->last = cstr("Jordan"); + + csptr_pe q = csptr_pe_ref(p); // share the pointer + printf("%s %s: %d\n", q.get->name.str, q.get->last.str, *q.use_count); + + c_del(csptr_pe, &p, &q); +} +*/ +typedef int atomic_count_t; +#if defined(__i386__) || defined(__x86_64__) + static inline atomic_count_t atomic_exchange_and_add(atomic_count_t* pw, int dv) { + int r; + __asm__ __volatile__ ( + "lock\n\t" + "xadd %1, %0": + "=m"( *pw ), "=r"( r ): // int r = *pw; // outputs (%0, %1) + "m"( *pw ), "1"( dv ): // *pw += dv; // inputs (%2, %3 == %1) + "memory", "cc" // clobbers + ); + return r; + } + static inline void atomic_increment(atomic_count_t* pw) { + __asm__ ( + "lock\n\t" + "incl %0": + "=m"( *pw ): // ++*pw // output (%0) + "m"( *pw ): // input (%1) + "cc" // clobbers + ); + } + static inline atomic_count_t atomic_decrement(atomic_count_t* pw) { + return atomic_exchange_and_add(pw, -1) - 1; // (pw, 1) + 1; + } +#else + static inline void atomic_increment(atomic_count_t* pw) {++*pw;} + static inline atomic_count_t atomic_decrement(atomic_count_t* pw) {return --*pw;} +#endif + + +#define using_csptr(X, Value, valueDestroy) \ + typedef Value csptr_##X##_value_t; \ + typedef struct { csptr_##X##_value_t* get; atomic_count_t* use_count; } csptr_##X, csptr_##X##_t; \ +\ + STC_INLINE csptr_##X \ + csptr_##X##_make(csptr_##X##_value_t* p) { \ + csptr_##X ptr = {p}; \ + if (p) *(ptr.use_count = c_new(atomic_count_t)) = 1; \ + return ptr; \ + } \ +\ + STC_INLINE csptr_##X \ + csptr_##X##_ref(csptr_##X ptr) {if (ptr.get) atomic_increment(ptr.use_count); return ptr;} \ +\ + STC_INLINE void \ + csptr_##X##_del(csptr_##X* self) { \ + if (self->use_count && atomic_decrement(self->use_count) == 0) { \ + c_free(self->use_count); valueDestroy(self->get); c_free(self->get); \ + } \ + } \ +\ + STC_INLINE void \ + csptr_##X##_reset(csptr_##X* self, csptr_##X##_value_t* p) { \ + csptr_##X##_del(self); \ + *self = csptr_##X##_make(p); \ + } \ +\ + typedef int csptr_##X##_dud + +#endif diff --git a/stc/cstack.h b/stc/cstack.h index 0351a545..37e8f3f3 100644 --- a/stc/cstack.h +++ b/stc/cstack.h @@ -49,7 +49,7 @@ #define using_cstack(X, ctype) \ \ - typedef struct ctype cstack_##X; \ + typedef ctype##_t cstack_##X, cstack_##X##_t; \ typedef ctype##_value_t cstack_##X##_value_t; \ typedef ctype##_rawvalue_t cstack_##X##_rawvalue_t; \ typedef ctype##_input_t cstack_##X##_input_t; \ diff --git a/stc/cvec.h b/stc/cvec.h index 3754732d..082909fc 100644 --- a/stc/cvec.h +++ b/stc/cvec.h @@ -50,9 +50,9 @@ typedef cvec_##X##_rawvalue_t cvec_##X##_input_t; \ typedef struct { cvec_##X##_value_t *get; } cvec_##X##_iter_t; \ \ - typedef struct cvec_##X { \ + typedef struct { \ cvec_##X##_value_t* data; \ - } cvec_##X; \ + } cvec_##X, cvec_##X##_t; \ \ STC_INLINE cvec_##X \ cvec_##X##_init(void) {cvec_##X v = cvec_INIT; return v;} \ -- cgit v1.2.3