This is an automated email from the ASF dual-hosted git repository.

astitcher pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/qpid-proton.git

commit 3755d074619e026fefad0ecef1c8a10bfa7783fb
Author: Andrew Stitcher <[email protected]>
AuthorDate: Fri Apr 29 10:49:53 2022 -0400

    PROTON-2542: Simplify pn_class_t handling
    
    Allow every vtable entry to be NULL and have a good default behaviour.
    This allows a lot of devirtualization as the majority of the entries are
    now NULL and are handled without an indirect jump. It also reduces the
    number of symbols needed to be exported to be in the pn_class_t tables.
---
 c/include/proton/object.h  |  40 +++++------
 c/src/core/engine.c        |  24 +++----
 c/src/core/object/object.c | 164 ++++++++++++++++++++++++++++-----------------
 c/src/core/transport.c     |   8 +--
 cpp/src/contexts.cpp       |   2 +-
 5 files changed, 137 insertions(+), 101 deletions(-)

diff --git a/c/include/proton/object.h b/c/include/proton/object.h
index fb8236db..d89dd927 100644
--- a/c/include/proton/object.h
+++ b/c/include/proton/object.h
@@ -70,18 +70,20 @@ PN_EXTERN extern const pn_class_t PN_OBJECT[];
 PN_EXTERN extern const pn_class_t PN_VOID[];
 PN_EXTERN extern const pn_class_t PN_WEAKREF[];
 
+PN_EXTERN void pn_object_incref(void *object);
+
 #define PN_CLASSCLASS(PREFIX) PREFIX ## __class
 
 #define PN_CLASS(PREFIX) {                      \
     #PREFIX,                                    \
     CID_ ## PREFIX,                             \
-    pn_object_new,                              \
+    NULL,                                       \
     PREFIX ## _initialize,                      \
-    pn_object_incref,                           \
-    pn_object_decref,                           \
-    pn_object_refcount,                         \
+    NULL,                                       \
+    NULL,                                       \
+    NULL,                                       \
     PREFIX ## _finalize,                        \
-    pn_object_free,                             \
+    NULL,                                       \
     PREFIX ## _hashcode,                        \
     PREFIX ## _compare,                         \
     PREFIX ## _inspect                          \
@@ -102,6 +104,11 @@ PN_EXTERN extern const pn_class_t PN_WEAKREF[];
     PREFIX ## _inspect                          \
 }
 
+PN_EXTERN void *pn_void_new(const pn_class_t *clazz, size_t size);
+PN_EXTERN void pn_void_incref(void *object);
+PN_EXTERN void pn_void_decref(void *object);
+PN_EXTERN int pn_void_refcount(void *object);
+
 /* Class to identify a plain C struct in a pn_event_t. No refcounting or 
memory management. */
 #define PN_STRUCT_CLASSDEF(PREFIX)                  \
 const pn_class_t PN_CLASSCLASS(PREFIX)[] = {{       \
@@ -123,12 +130,6 @@ PN_EXTERN pn_cid_t pn_class_id(const pn_class_t *clazz);
 PN_EXTERN const char *pn_class_name(const pn_class_t *clazz);
 PN_EXTERN void *pn_class_new(const pn_class_t *clazz, size_t size);
 
-/* pn_incref, pn_decref and pn_refcount are for internal use by the proton
-   library, the should not be called by application code. Application code
-   should use the appropriate pn_*_free function (pn_link_free, pn_session_free
-   etc.) when it is finished with a proton value. Proton values should only be
-   used when handling a pn_event_t that refers to them.
-*/
 PN_EXTERN void *pn_class_incref(const pn_class_t *clazz, void *object);
 PN_EXTERN int pn_class_refcount(const pn_class_t *clazz, void *object);
 PN_EXTERN int pn_class_decref(const pn_class_t *clazz, void *object);
@@ -139,17 +140,12 @@ 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 int pn_class_inspect(const pn_class_t *clazz, void *object, 
pn_string_t *dst);
 
-PN_EXTERN void *pn_void_new(const pn_class_t *clazz, size_t size);
-PN_EXTERN void pn_void_incref(void *object);
-PN_EXTERN void pn_void_decref(void *object);
-PN_EXTERN int pn_void_refcount(void *object);
-
-PN_EXTERN void *pn_object_new(const pn_class_t *clazz, size_t size);
-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_incref, pn_decref and pn_refcount are for internal use by the proton
+ *   library, the should not be called by application code. Application code
+ *   should use the appropriate pn_*_free function (pn_link_free, 
pn_session_free
+ *   etc.) when it is finished with a proton value. Proton values should only 
be
+ *   used when handling a pn_event_t that refers to them.
+ */
 PN_EXTERN void *pn_incref(void *object);
 PN_EXTERN int pn_decref(void *object);
 PN_EXTERN int pn_refcount(void *object);
diff --git a/c/src/core/engine.c b/c/src/core/engine.c
index 1f25aadd..b03d64eb 100644
--- a/c/src/core/engine.c
+++ b/c/src/core/engine.c
@@ -977,9 +977,9 @@ static void pn_session_finalize(void *object)
   }
 }
 
-#define pn_session_new pn_object_new
-#define pn_session_refcount pn_object_refcount
-#define pn_session_decref pn_object_decref
+#define pn_session_new NULL
+#define pn_session_refcount NULL
+#define pn_session_decref NULL
 #define pn_session_initialize NULL
 #define pn_session_hashcode NULL
 #define pn_session_compare NULL
@@ -988,7 +988,7 @@ static void pn_session_finalize(void *object)
 pn_session_t *pn_session(pn_connection_t *conn)
 {
   assert(conn);
-#define pn_session_free pn_object_free
+#define pn_session_free NULL
   static const pn_class_t clazz = PN_METACLASS(pn_session);
 #undef pn_session_free
   pn_session_t *ssn = (pn_session_t *) pn_class_new(&clazz, 
sizeof(pn_session_t));
@@ -1146,8 +1146,8 @@ static void pn_link_finalize(void *object)
   pn_free(link->remote_properties);
 }
 
-#define pn_link_refcount pn_object_refcount
-#define pn_link_decref pn_object_decref
+#define pn_link_refcount NULL
+#define pn_link_decref NULL
 #define pn_link_initialize NULL
 #define pn_link_hashcode NULL
 #define pn_link_compare NULL
@@ -1155,8 +1155,8 @@ static void pn_link_finalize(void *object)
 
 pn_link_t *pn_link_new(int type, pn_session_t *session, const char *name)
 {
-#define pn_link_new pn_object_new
-#define pn_link_free pn_object_free
+#define pn_link_new NULL
+#define pn_link_free NULL
   static const pn_class_t clazz = PN_METACLASS(pn_link);
 #undef pn_link_new
 #undef pn_link_free
@@ -1507,10 +1507,10 @@ static void pn_disposition_clear(pn_disposition_t *ds)
   pn_condition_clear(&ds->condition);
 }
 
-#define pn_delivery_new pn_object_new
-#define pn_delivery_refcount pn_object_refcount
-#define pn_delivery_decref pn_object_decref
-#define pn_delivery_free pn_object_free
+#define pn_delivery_new NULL
+#define pn_delivery_refcount NULL
+#define pn_delivery_decref NULL
+#define pn_delivery_free NULL
 #define pn_delivery_initialize NULL
 #define pn_delivery_hashcode NULL
 #define pn_delivery_compare NULL
diff --git a/c/src/core/object/object.c b/c/src/core/object/object.c
index 040f4113..86707c48 100644
--- a/c/src/core/object/object.c
+++ b/c/src/core/object/object.c
@@ -67,10 +67,91 @@ pn_cid_t pn_class_id(const pn_class_t *clazz)
   return clazz->cid;
 }
 
+static inline void *pni_default_new(const pn_class_t *clazz, size_t size)
+{
+  void *object = NULL;
+  pni_head_t *head = (pni_head_t *) pni_mem_zallocate(clazz, 
sizeof(pni_head_t) + size);
+  if (head != NULL) {
+    object = head + 1;
+    head->clazz = clazz;
+    head->refcount = 1;
+  }
+  return object;
+}
+
+static inline void pni_default_incref(void *object) {
+  if (object) {
+    pni_head(object)->refcount++;
+  }
+}
+
+static inline int pni_default_refcount(void *object)
+{
+  assert(object);
+  return pni_head(object)->refcount;
+}
+
+static inline void pni_default_decref(void *object)
+{
+  pni_head_t *head = pni_head(object);
+  assert(head->refcount > 0);
+  head->refcount--;
+}
+
+static inline void pni_default_free(void *object)
+{
+  pni_head_t *head = pni_head(object);
+  pni_mem_deallocate(head->clazz, head);
+}
+
+void pn_object_incref(void *object) {
+  pni_default_incref(object);
+}
+
+static inline void *pni_class_new(const pn_class_t *clazz, size_t size) {
+  if (clazz->newinst) {
+    return clazz->newinst(clazz, size);
+  } else {
+    return pni_default_new(clazz, size);
+  }
+}
+
+static inline void pni_class_incref(const pn_class_t *clazz, void *object) {
+  if (clazz->incref) {
+    clazz->incref(object);
+  } else {
+    pni_default_incref(object);
+  }
+}
+
+static inline void pni_class_decref(const pn_class_t *clazz, void *object) {
+  if (clazz->decref) {
+    clazz->decref(object);
+  } else {
+    pni_default_decref(object);
+  }
+}
+
+static inline int pni_class_refcount(const pn_class_t *clazz, void *object) {
+  if (clazz->refcount) {
+    return clazz->refcount(object);
+  } else {
+    return pni_default_refcount(object);
+  }
+}
+
+static inline void pni_class_free(const pn_class_t *clazz, void *object) {
+  if (clazz->free) {
+    clazz->free(object);
+  } else {
+    pni_default_free(object);
+  }
+}
+
 void *pn_class_new(const pn_class_t *clazz, size_t size)
 {
   assert(clazz);
-  void *object = clazz->newinst(clazz, size);
+  void *object = pni_class_new(clazz, size);
   if (object && clazz->initialize) {
     clazz->initialize(object);
   }
@@ -83,8 +164,7 @@ void *pn_class_incref(const pn_class_t *clazz, void *object)
     if (clazz==PN_OBJECT) {
       clazz = pni_head(object)->clazz;
     }
-
-    clazz->incref(object);
+    pni_class_incref(clazz, object);
   }
   return object;
 }
@@ -95,7 +175,7 @@ int pn_class_refcount(const pn_class_t *clazz, void *object)
     clazz = pn_class(object);
   }
 
-  return clazz->refcount(object);
+  return pni_class_refcount(clazz, object);
 }
 
 int pn_class_decref(const pn_class_t *clazz, void *object)
@@ -104,18 +184,17 @@ int pn_class_decref(const pn_class_t *clazz, void *object)
     if (clazz==PN_OBJECT) {
       clazz = pni_head(object)->clazz;
     }
-
-    clazz->decref(object);
-    int rc = clazz->refcount(object);
+    pni_class_decref(clazz, object);
+    int rc = pni_class_refcount(clazz, object);
     if (rc == 0) {
       if (clazz->finalize) {
         clazz->finalize(object);
         // check the refcount again in case the finalizer created a
         // new reference
-        rc = clazz->refcount(object);
+        rc = pni_class_refcount(clazz, object);
       }
       if (rc == 0) {
-        clazz->free(object);
+        pni_class_free(clazz, object);
         return 0;
       }
     } else {
@@ -133,7 +212,7 @@ void pn_class_free(const pn_class_t *clazz, void *object)
       clazz = pni_head(object)->clazz;
     }
 
-    int rc = clazz->refcount(object);
+    int rc = pni_class_refcount(clazz, object);
     assert(rc == 1 || rc == -1);
     if (rc == 1) {
       rc = pn_class_decref(clazz, object);
@@ -142,7 +221,7 @@ void pn_class_free(const pn_class_t *clazz, void *object)
       if (clazz->finalize) {
         clazz->finalize(object);
       }
-      clazz->free(object);
+      pni_class_free(clazz, object);
     }
   }
 }
@@ -186,50 +265,11 @@ int pn_class_inspect(const pn_class_t *clazz, void 
*object, pn_string_t *dst)
   return pn_string_addf(dst, "%s<%p>", name, object);
 }
 
-void *pn_object_new(const pn_class_t *clazz, size_t size)
-{
-  void *object = NULL;
-  pni_head_t *head = (pni_head_t *) pni_mem_zallocate(clazz, 
sizeof(pni_head_t) + size);
-  if (head != NULL) {
-    object = head + 1;
-    head->clazz = clazz;
-    head->refcount = 1;
-  }
-  return object;
-}
-
-
-void pn_object_incref(void *object)
-{
-  if (object) {
-    pni_head(object)->refcount++;
-  }
-}
-
-int pn_object_refcount(void *object)
-{
-  assert(object);
-  return pni_head(object)->refcount;
-}
-
-void pn_object_decref(void *object)
-{
-  pni_head_t *head = pni_head(object);
-  assert(head->refcount > 0);
-  head->refcount--;
-}
-
-void pn_object_free(void *object)
-{
-  pni_head_t *head = pni_head(object);
-  pni_mem_deallocate(head->clazz, head);
-}
-
 void *pn_incref(void *object)
 {
   if (object) {
     const pn_class_t *clazz = pni_head(object)->clazz;
-    clazz->incref(object);
+    pni_class_incref(clazz, object);
   }
   return object;
 }
@@ -238,17 +278,17 @@ int pn_decref(void *object)
 {
   if (object) {
     const pn_class_t *clazz = pni_head(object)->clazz;
-    clazz->decref(object);
-    int rc = clazz->refcount(object);
+    pni_class_decref(clazz, object);
+    int rc = pni_class_refcount(clazz, object);
     if (rc == 0) {
       if (clazz->finalize) {
         clazz->finalize(object);
         // check the refcount again in case the finalizer created a
         // new reference
-        rc = clazz->refcount(object);
+        rc = pni_class_refcount(clazz, object);
       }
       if (rc == 0) {
-        clazz->free(object);
+        pni_class_free(clazz, object);
         return 0;
       }
     } else {
@@ -262,29 +302,29 @@ int pn_refcount(void *object)
 {
   assert(object);
   const pn_class_t *clazz = pni_head(object)->clazz;
-  return clazz->refcount(object);
+  return pni_class_refcount(clazz, object);
 }
 
 void pn_free(void *object)
 {
   if (object) {
     const pn_class_t *clazz = pni_head(object)->clazz;
-    int rc = clazz->refcount(object);
+    int rc = pni_class_refcount(clazz, object);
     assert(rc == 1 || rc == -1);
     if (rc == 1) {
-      clazz->decref(object);
-      assert(clazz->refcount(object) == 0);
+      pni_class_decref(clazz, object);
+      assert(pni_class_refcount(clazz, object) == 0);
       if (clazz->finalize) {
         clazz->finalize(object);
       }
-      if (clazz->refcount(object) == 0) {
-        clazz->free(object);
+      if (pni_class_refcount(clazz, object) == 0) {
+        pni_class_free(clazz, object);
       }
     } else {
       if (clazz->finalize) {
         clazz->finalize(object);
       }
-      clazz->free(object);
+      pni_class_free(clazz, object);
     }
   }
 }
diff --git a/c/src/core/transport.c b/c/src/core/transport.c
index 0e101982..1fad3773 100644
--- a/c/src/core/transport.c
+++ b/c/src/core/transport.c
@@ -535,16 +535,16 @@ static void pn_transport_incref(void *object)
 }
 
 static void pn_transport_finalize(void *object);
-#define pn_transport_new pn_object_new
-#define pn_transport_refcount pn_object_refcount
-#define pn_transport_decref pn_object_decref
+#define pn_transport_new NULL
+#define pn_transport_refcount NULL
+#define pn_transport_decref NULL
 #define pn_transport_hashcode NULL
 #define pn_transport_compare NULL
 #define pn_transport_inspect NULL
 
 pn_transport_t *pn_transport(void)
 {
-#define pn_transport_free pn_object_free
+#define pn_transport_free NULL
   static const pn_class_t clazz = PN_METACLASS(pn_transport);
 #undef pn_transport_free
   pn_transport_t *transport =
diff --git a/cpp/src/contexts.cpp b/cpp/src/contexts.cpp
index f6b78228..7bc6c3f0 100644
--- a/cpp/src/contexts.cpp
+++ b/cpp/src/contexts.cpp
@@ -64,7 +64,7 @@ T* get_context(pn_record_t* record, pn_handle_t handle) {
 
 context::~context() {}
 
-void *context::alloc(size_t n) { return pn_object_new(&cpp_context_class, n); }
+void *context::alloc(size_t n) { return pn_class_new(&cpp_context_class, n); }
 
 pn_class_t* context::pn_class() { return &cpp_context_class; }
 


---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to