You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@qpid.apache.org by rh...@apache.org on 2014/09/15 21:19:24 UTC

svn commit: r1625120 - in /qpid/proton/trunk/proton-c: include/proton/cproton.i include/proton/object.h src/messenger/messenger.c src/object/object.c src/tests/object.c

Author: rhs
Date: Mon Sep 15 19:19:24 2014
New Revision: 1625120

URL: http://svn.apache.org/r1625120
Log:
revised class system to be more extensible

Modified:
    qpid/proton/trunk/proton-c/include/proton/cproton.i
    qpid/proton/trunk/proton-c/include/proton/object.h
    qpid/proton/trunk/proton-c/src/messenger/messenger.c
    qpid/proton/trunk/proton-c/src/object/object.c
    qpid/proton/trunk/proton-c/src/tests/object.c

Modified: qpid/proton/trunk/proton-c/include/proton/cproton.i
URL: http://svn.apache.org/viewvc/qpid/proton/trunk/proton-c/include/proton/cproton.i?rev=1625120&r1=1625119&r2=1625120&view=diff
==============================================================================
--- qpid/proton/trunk/proton-c/include/proton/cproton.i (original)
+++ qpid/proton/trunk/proton-c/include/proton/cproton.i Mon Sep 15 19:19:24 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/trunk/proton-c/include/proton/object.h
URL: http://svn.apache.org/viewvc/qpid/proton/trunk/proton-c/include/proton/object.h?rev=1625120&r1=1625119&r2=1625120&view=diff
==============================================================================
--- qpid/proton/trunk/proton-c/include/proton/object.h (original)
+++ qpid/proton/trunk/proton-c/include/proton/object.h Mon Sep 15 19:19:24 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/trunk/proton-c/src/messenger/messenger.c
URL: http://svn.apache.org/viewvc/qpid/proton/trunk/proton-c/src/messenger/messenger.c?rev=1625120&r1=1625119&r2=1625120&view=diff
==============================================================================
--- qpid/proton/trunk/proton-c/src/messenger/messenger.c (original)
+++ qpid/proton/trunk/proton-c/src/messenger/messenger.c Mon Sep 15 19:19:24 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/trunk/proton-c/src/object/object.c
URL: http://svn.apache.org/viewvc/qpid/proton/trunk/proton-c/src/object/object.c?rev=1625120&r1=1625119&r2=1625120&view=diff
==============================================================================
--- qpid/proton/trunk/proton-c/src/object/object.c (original)
+++ qpid/proton/trunk/proton-c/src/object/object.c Mon Sep 15 19:19:24 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/trunk/proton-c/src/tests/object.c
URL: http://svn.apache.org/viewvc/qpid/proton/trunk/proton-c/src/tests/object.c?rev=1625120&r1=1625119&r2=1625120&view=diff
==============================================================================
--- qpid/proton/trunk/proton-c/src/tests/object.c (original)
+++ qpid/proton/trunk/proton-c/src/tests/object.c Mon Sep 15 19:19:24 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-unsubscribe@qpid.apache.org
For additional commands, e-mail: commits-help@qpid.apache.org