Author: gsim Date: Fri Oct 10 12:48:35 2014 New Revision: 1630811 URL: http://svn.apache.org/r1630811 Log: revised class system to be more extensible
Modified: qpid/proton/branches/examples/proton-c/include/proton/cproton.i qpid/proton/branches/examples/proton-c/include/proton/object.h qpid/proton/branches/examples/proton-c/src/messenger/messenger.c qpid/proton/branches/examples/proton-c/src/object/object.c qpid/proton/branches/examples/proton-c/src/tests/object.c Modified: qpid/proton/branches/examples/proton-c/include/proton/cproton.i URL: http://svn.apache.org/viewvc/qpid/proton/branches/examples/proton-c/include/proton/cproton.i?rev=1630811&r1=1630810&r2=1630811&view=diff ============================================================================== --- qpid/proton/branches/examples/proton-c/include/proton/cproton.i (original) +++ qpid/proton/branches/examples/proton-c/include/proton/cproton.i Fri Oct 10 12:48:35 2014 @@ -53,6 +53,8 @@ typedef long long int int64_t; %include "proton/types.h" %ignore pn_string_vformat; %ignore pn_string_vaddf; +%immutable PN_OBJECT; +%immutable PN_VOID; %include "proton/object.h" %ignore pn_error_format; Modified: qpid/proton/branches/examples/proton-c/include/proton/object.h URL: http://svn.apache.org/viewvc/qpid/proton/branches/examples/proton-c/include/proton/object.h?rev=1630811&r1=1630810&r2=1630811&view=diff ============================================================================== --- qpid/proton/branches/examples/proton-c/include/proton/object.h (original) +++ qpid/proton/branches/examples/proton-c/include/proton/object.h Fri Oct 10 12:48:35 2014 @@ -35,31 +35,82 @@ extern "C" { typedef uintptr_t pn_handle_t; typedef intptr_t pn_shandle_t; +typedef struct pn_class_t pn_class_t; +typedef struct pn_string_t pn_string_t; typedef struct pn_list_t pn_list_t; typedef struct pn_map_t pn_map_t; typedef struct pn_hash_t pn_hash_t; -typedef struct pn_string_t pn_string_t; typedef void *(*pn_iterator_next_t)(void *state); typedef struct pn_iterator_t pn_iterator_t; -typedef struct { +struct pn_class_t { const char *name; + void *(*newinst)(const pn_class_t *, size_t); void (*initialize)(void *); + void (*incref)(void *); + void (*decref)(void *); + int (*refcount)(void *); void (*finalize)(void *); + void (*free)(void *); + const pn_class_t *(*reify)(void *); uintptr_t (*hashcode)(void *); intptr_t (*compare)(void *, void *); int (*inspect)(void *, pn_string_t *); -} pn_class_t; +}; + +extern const pn_class_t *PN_OBJECT; +extern const pn_class_t *PN_VOID; #define PN_CLASS(PREFIX) { \ #PREFIX, \ + pn_object_new, \ + PREFIX ## _initialize, \ + pn_object_incref, \ + pn_object_decref, \ + pn_object_refcount, \ + PREFIX ## _finalize, \ + pn_object_free, \ + pn_object_reify, \ + PREFIX ## _hashcode, \ + PREFIX ## _compare, \ + PREFIX ## _inspect \ +} + +#define PN_METACLASS(PREFIX) { \ + #PREFIX, \ + PREFIX ## _new, \ PREFIX ## _initialize, \ + PREFIX ## _incref, \ + PREFIX ## _decref, \ + PREFIX ## _refcount, \ PREFIX ## _finalize, \ + PREFIX ## _free, \ + PREFIX ## _reify, \ PREFIX ## _hashcode, \ PREFIX ## _compare, \ PREFIX ## _inspect \ } +PN_EXTERN void *pn_class_new(const pn_class_t *clazz, size_t size); +PN_EXTERN void *pn_class_incref(const pn_class_t *clazz, void *object); +PN_EXTERN void pn_class_decref(const pn_class_t *clazz, void *object); +PN_EXTERN void pn_class_free(const pn_class_t *clazz, void *object); +PN_EXTERN int pn_class_refcount(const pn_class_t *clazz, void *object); +PN_EXTERN const pn_class_t *pn_class_reify(const pn_class_t *clazz, void *object); +PN_EXTERN uintptr_t pn_class_hashcode(const pn_class_t *clazz, void *object); +PN_EXTERN intptr_t pn_class_compare(const pn_class_t *clazz, void *a, void *b); +PN_EXTERN bool pn_class_equals(const pn_class_t *clazz, void *a, void *b); + +PN_EXTERN void *pn_object_new(const pn_class_t *clazz, size_t size); +PN_EXTERN const pn_class_t *pn_object_reify(void *object); +PN_EXTERN void pn_object_incref(void *object); +PN_EXTERN int pn_object_refcount(void *object); +PN_EXTERN void pn_object_decref(void *object); +PN_EXTERN void pn_object_free(void *object); +PN_EXTERN uintptr_t pn_object_hashcode(void *object); +PN_EXTERN intptr_t pn_object_compare(void *a, void *b); +PN_EXTERN int pn_object_inspect(void *object, pn_string_t *dst); + PN_EXTERN void *pn_new(size_t size, const pn_class_t* clazz); PN_EXTERN void *pn_new2(size_t size, const pn_class_t* clazz, void *from); PN_EXTERN void pn_initialize(void *object, const pn_class_t *clazz); Modified: qpid/proton/branches/examples/proton-c/src/messenger/messenger.c URL: http://svn.apache.org/viewvc/qpid/proton/branches/examples/proton-c/src/messenger/messenger.c?rev=1630811&r1=1630810&r2=1630811&view=diff ============================================================================== --- qpid/proton/branches/examples/proton-c/src/messenger/messenger.c (original) +++ qpid/proton/branches/examples/proton-c/src/messenger/messenger.c Fri Oct 10 12:48:35 2014 @@ -375,7 +375,7 @@ static pn_listener_ctx_t *pn_listener_ct return NULL; } - pn_listener_ctx_t *ctx = (pn_listener_ctx_t *) pn_new(sizeof(pn_listener_ctx_t), NULL); + pn_listener_ctx_t *ctx = (pn_listener_ctx_t *) pn_new(sizeof(pn_listener_ctx_t), PN_OBJECT); ctx->messenger = messenger; ctx->domain = pn_ssl_domain(PN_SSL_MODE_SERVER); if (messenger->certificate) { Modified: qpid/proton/branches/examples/proton-c/src/object/object.c URL: http://svn.apache.org/viewvc/qpid/proton/branches/examples/proton-c/src/object/object.c?rev=1630811&r1=1630810&r2=1630811&view=diff ============================================================================== --- qpid/proton/branches/examples/proton-c/src/object/object.c (original) +++ qpid/proton/branches/examples/proton-c/src/object/object.c Fri Oct 10 12:48:35 2014 @@ -28,6 +28,103 @@ #include <assert.h> #include <ctype.h> +#define pn_object_initialize NULL +#define pn_object_finalize NULL + +const pn_class_t PNI_OBJECT = PN_CLASS(pn_object); +const pn_class_t *PN_OBJECT = &PNI_OBJECT; + +#define pn_void_initialize NULL +static void *pn_void_new(const pn_class_t *clazz, size_t size) { return malloc(size); } +static void pn_void_incref(void *object) {} +static void pn_void_decref(void *object) {} +static int pn_void_refcount(void *object) { return -1; } +#define pn_void_finalize NULL +static void pn_void_free(void *object) { free(object); } +static const pn_class_t *pn_void_reify(void *object) { return PN_VOID; } +static uintptr_t pn_void_hashcode(void *object) { return (uintptr_t) object; } +static intptr_t pn_void_compare(void *a, void *b) { return (intptr_t) b - (intptr_t) a; } +static int pn_void_inspect(void *object, pn_string_t *dst) { return pn_string_addf(dst, "%p", object); } + +const pn_class_t PNI_VOID = PN_METACLASS(pn_void); +const pn_class_t *PN_VOID = &PNI_VOID; + +void *pn_class_new(const pn_class_t *clazz, size_t size) +{ + assert(clazz); + return clazz->newinst(clazz, size); +} + +void *pn_class_incref(const pn_class_t *clazz, void *object) +{ + assert(clazz); + clazz = clazz->reify(object); + clazz->incref(object); + return object; +} + +int pn_class_refcount(const pn_class_t *clazz, void *object) +{ + assert(clazz); + clazz = clazz->reify(object); + return clazz->refcount(object); +} + +void pn_class_decref(const pn_class_t *clazz, void *object) +{ + assert(clazz); + clazz = clazz->reify(object); + clazz->decref(object); +} + +void pn_class_free(const pn_class_t *clazz, void *object) +{ + assert(clazz); + clazz = clazz->reify(object); + clazz->free(object); +} + +const pn_class_t *pn_class_reify(const pn_class_t *clazz, void *object) +{ + assert(clazz); + return clazz->reify(object); +} + +uintptr_t pn_class_hashcode(const pn_class_t *clazz, void *object) +{ + assert(clazz); + + if (!object) return 0; + + clazz = clazz->reify(object); + + if (clazz->hashcode) { + return clazz->hashcode(object); + } else { + return (uintptr_t) object; + } +} + +intptr_t pn_class_compare(const pn_class_t *clazz, void *a, void *b) +{ + assert(clazz); + + if (a == b) return 0; + + clazz = clazz->reify(a); + + if (a && b && clazz->compare) { + return clazz->compare(a, b); + } else { + return (intptr_t) b - (intptr_t) a; + } +} + +bool pn_class_equals(const pn_class_t *clazz, void *a, void *b) +{ + return pn_class_compare(clazz, a, b) == 0; +} + typedef struct { const pn_class_t *clazz; int refcount; @@ -36,8 +133,58 @@ typedef struct { #define pni_head(PTR) \ (((pni_head_t *) (PTR)) - 1) +void *pn_object_new(const pn_class_t *clazz, size_t size) +{ + return pn_new(size, clazz); +} + +const pn_class_t *pn_object_reify(void *object) +{ + if (object) { + return pni_head(object)->clazz; + } else { + return PN_OBJECT; + } +} + +void pn_object_incref(void *object) +{ + pn_incref(object); +} + +int pn_object_refcount(void *object) +{ + return pn_refcount(object); +} + +void pn_object_decref(void *object) +{ + pn_decref(object); +} + +void pn_object_free(void *object) +{ + pn_free(object); +} + +uintptr_t pn_object_hashcode(void *object) +{ + return (uintptr_t) object; +} + +intptr_t pn_object_compare(void *a, void *b) +{ + return (intptr_t) b - (intptr_t) a; +} + +int pn_object_inspect(void *object, pn_string_t *dst) +{ + return pn_inspect(object, dst); +} + void *pn_new(size_t size, const pn_class_t *clazz) { + assert(clazz); return pn_new2(size, clazz, NULL); } @@ -136,20 +283,7 @@ uintptr_t pn_hashcode(void *object) intptr_t pn_compare(void *a, void *b) { - if (a == b) return 0; - if (a && b) { - pni_head_t *ha = pni_head(a); - pni_head_t *hb = pni_head(b); - - if (ha->clazz && hb->clazz && ha->clazz == hb->clazz) { - const pn_class_t *clazz = ha->clazz; - if (clazz->compare) { - return clazz->compare(a, b); - } - } - } - - return (intptr_t) b - (intptr_t) a; + return pn_class_compare(PN_OBJECT, a, b); } bool pn_equals(void *a, void *b) Modified: qpid/proton/branches/examples/proton-c/src/tests/object.c URL: http://svn.apache.org/viewvc/qpid/proton/branches/examples/proton-c/src/tests/object.c?rev=1630811&r1=1630810&r2=1630811&view=diff ============================================================================== --- qpid/proton/branches/examples/proton-c/src/tests/object.c (original) +++ qpid/proton/branches/examples/proton-c/src/tests/object.c Fri Oct 10 12:48:35 2014 @@ -95,9 +95,46 @@ static intptr_t delta(void *a, void *b) static pn_class_t null_class = {0}; -static pn_class_t noop_class = {NULL, noop, noop, zero, delta}; +#define noop_initialize noop +#define noop_finalize noop +#define noop_hashcode zero +#define noop_compare delta +#define noop_inspect NULL -static void test_new(size_t size, pn_class_t *clazz) +static const pn_class_t noop_class = PN_CLASS(noop); + +static void test_class(const pn_class_t *clazz, size_t size) +{ + void *a = pn_class_new(clazz, size); + void *b = pn_class_new(clazz, size); + + assert(!pn_class_equals(clazz, a, b)); + assert(pn_class_equals(clazz, a, a)); + assert(pn_class_equals(clazz, b, b)); + assert(!pn_class_equals(clazz, a, NULL)); + assert(!pn_class_equals(clazz, NULL, a)); + + int rca = pn_class_refcount(clazz, a); + int rcb = pn_class_refcount(clazz, b); + + assert(rca == -1 || rca == 1); + assert(rcb == -1 || rcb == 1); + + pn_class_incref(clazz, a); + + rca = pn_class_refcount(clazz, a); + assert(rca == -1 || rca == 2); + + pn_class_decref(clazz, a); + + rca = pn_class_refcount(clazz, a); + assert(rca == -1 || rca == 1); + + pn_class_free(clazz, a); + pn_class_free(clazz, b); +} + +static void test_new(size_t size, const pn_class_t *clazz) { void *obj = pn_new(size, clazz); assert(obj); @@ -117,9 +154,15 @@ static void finalizer(void *object) (**called)++; } +#define finalizer_initialize NULL +#define finalizer_finalize finalizer +#define finalizer_hashcode NULL +#define finalizer_compare NULL +#define finalizer_inspect NULL + static void test_finalize(void) { - static pn_class_t clazz = {NULL, NULL, finalizer}; + static pn_class_t clazz = PN_CLASS(finalizer); int **obj = (int **) pn_new(sizeof(int **), &clazz); assert(obj); @@ -139,9 +182,15 @@ static void test_free(void) static uintptr_t hashcode(void *obj) { return (uintptr_t) obj; } +#define hashcode_initialize NULL +#define hashcode_finalize NULL +#define hashcode_compare NULL +#define hashcode_hashcode hashcode +#define hashcode_inspect NULL + static void test_hashcode(void) { - static pn_class_t clazz = {NULL, NULL, NULL, hashcode}; + static pn_class_t clazz = PN_CLASS(hashcode); void *obj = pn_new(0, &clazz); assert(obj); assert(pn_hashcode(obj) == (uintptr_t) obj); @@ -149,9 +198,15 @@ static void test_hashcode(void) pn_free(obj); } +#define compare_initialize NULL +#define compare_finalize NULL +#define compare_compare delta +#define compare_hashcode NULL +#define compare_inspect NULL + static void test_compare(void) { - static pn_class_t clazz = {NULL, NULL, NULL, NULL, delta}; + static pn_class_t clazz = PN_CLASS(compare); void *a = pn_new(0, &clazz); assert(a); @@ -181,7 +236,7 @@ static void test_compare(void) static void test_refcounting(int refs) { - void *obj = pn_new(0, NULL); + void *obj = pn_new(0, PN_OBJECT); assert(pn_refcount(obj) == 1); @@ -224,10 +279,10 @@ static void test_list(size_t capacity) static void test_list_refcount(size_t capacity) { - void *one = pn_new(0, NULL); - void *two = pn_new(0, NULL); - void *three = pn_new(0, NULL); - void *four = pn_new(0, NULL); + void *one = pn_new(0, PN_OBJECT); + void *two = pn_new(0, PN_OBJECT); + void *three = pn_new(0, PN_OBJECT); + void *four = pn_new(0, PN_OBJECT); pn_list_t *list = pn_list(0, PN_REFCOUNT); assert(!pn_list_add(list, one)); @@ -395,9 +450,9 @@ static void test_build_map_odd(void) static void test_map(void) { - void *one = pn_new(0, NULL); - void *two = pn_new(0, NULL); - void *three = pn_new(0, NULL); + void *one = pn_new(0, PN_OBJECT); + void *two = pn_new(0, PN_OBJECT); + void *three = pn_new(0, PN_OBJECT); pn_map_t *map = pn_map(4, 0.75, PN_REFCOUNT); assert(pn_map_size(map) == 0); @@ -458,9 +513,9 @@ static void test_map(void) static void test_hash(void) { - void *one = pn_new(0, NULL); - void *two = pn_new(0, NULL); - void *three = pn_new(0, NULL); + void *one = pn_new(0, PN_OBJECT); + void *two = pn_new(0, PN_OBJECT); + void *three = pn_new(0, PN_OBJECT); pn_hash_t *hash = pn_hash(4, 0.75, PN_REFCOUNT); pn_hash_put(hash, 0, NULL); @@ -639,8 +694,8 @@ static void test_map_iteration(int n) { pn_list_t *pairs = pn_list(2*n, PN_REFCOUNT); for (int i = 0; i < n; i++) { - void *key = pn_new(0, NULL); - void *value = pn_new(0, NULL); + void *key = pn_new(0, PN_OBJECT); + void *value = pn_new(0, PN_OBJECT); pn_list_add(pairs, key); pn_list_add(pairs, value); pn_decref(key); @@ -746,9 +801,9 @@ void test_list_compare(void) assert(pn_equals(a, b)); - void *one = pn_new(0, NULL); - void *two = pn_new(0, NULL); - void *three = pn_new(0, NULL); + void *one = pn_new(0, PN_OBJECT); + void *two = pn_new(0, PN_OBJECT); + void *three = pn_new(0, PN_OBJECT); pn_list_add(a, one); assert(!pn_equals(a, b)); @@ -811,7 +866,13 @@ void test_iterator(void) int main(int argc, char **argv) { for (size_t i = 0; i < 128; i++) { - test_new(i, NULL); + test_class(PN_OBJECT, i); + test_class(PN_VOID, i); + test_class(&noop_class, i); + } + + for (size_t i = 0; i < 128; i++) { + test_new(i, PN_OBJECT); test_new(i, &null_class); test_new(i, &noop_class); } --------------------------------------------------------------------- To unsubscribe, e-mail: commits-unsubscr...@qpid.apache.org For additional commands, e-mail: commits-h...@qpid.apache.org