summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorArmin Burgmeier <armin@openismus.com>2007-03-23 17:16:49 +0000
committerMurray Cumming <murrayc@src.gnome.org>2007-03-23 17:16:49 +0000
commitcef5b2298a6ddb131176bbfc590b5e2af38daea2 (patch)
tree2b631b2cdc0958a9b0bdc46aa990f7f2d75a31de
parent5e45fe282faa2a59a0744fd28804aef630bd3be0 (diff)
downloadglibmm-cef5b2298a6ddb131176bbfc590b5e2af38daea2.tar.gz
Use static_cast in vfuncs and signal handlers to cast the wrapper object
2007-03-17 Armin Burgmeier <armin@openismus.com> * tools/m4/signal.m4: * tools/m4/vfunc.m4: Use static_cast in vfuncs and signal handlers to cast the wrapper object to ObjectBase*. This is enough to check whether the object is from a derived type or not. A slow dynamic_cast has only to be performed if it is derived, and the C++ vfunc needs to be called. * glib/glibmm/objectbase.h: This requires ObjectBase::is_derived_ to be public, because it is called on a ObjectBase* rather than the actual type. This causes a slight speed up of vfuncs and default signal handler invokation. Also added commented-out inline versions of ObjectBase::_get_current_wrapper() and ObjectBase::is_derived(), which could be used in the generated code if we find that this has significant performance benefits. Note that these methods must be additional to the non-inline methods, because inline methods are not usually exported in the shared library. svn path=/branches/glibmm-2-12/; revision=384
-rw-r--r--ChangeLog18
-rw-r--r--glib/glibmm/objectbase.h35
-rw-r--r--tools/m4/signal.m453
-rw-r--r--tools/m4/vfunc.m467
4 files changed, 118 insertions, 55 deletions
diff --git a/ChangeLog b/ChangeLog
index c454edfc..0f1e9365 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,21 @@
+2007-03-17 Armin Burgmeier <armin@openismus.com>
+
+ * tools/m4/signal.m4:
+ * tools/m4/vfunc.m4:
+ Use static_cast in vfuncs and signal handlers to cast the
+ wrapper object to ObjectBase*. This is enough to check whether the object is
+ from a derived type or not. A slow dynamic_cast has only to be performed if it
+ is derived, and the C++ vfunc needs to be called.
+ * glib/glibmm/objectbase.h: This requires ObjectBase::is_derived_ to be public,
+ because it is called on a ObjectBase* rather than the actual type.
+ This causes a slight speed up of vfuncs and default signal handler invokation.
+
+ Also added commented-out inline versions of ObjectBase::_get_current_wrapper() and
+ ObjectBase::is_derived(), which could be used in the generated code if we find
+ that this has significant performance benefits. Note that these methods must be
+ additional to the non-inline methods, because inline methods are not usually exported in the
+ shared library.
+
2.12.7:
2007-03-03 Murray Cumming <murrayc@murrayc.com>
diff --git a/glib/glibmm/objectbase.h b/glib/glibmm/objectbase.h
index 2ad6e650..2ea5a041 100644
--- a/glib/glibmm/objectbase.h
+++ b/glib/glibmm/objectbase.h
@@ -25,6 +25,7 @@
#include <glibmm/propertyproxy.h>
#include <glibmm/ustring.h>
#include <glibmm/value.h>
+#include <glibmm/quark.h>
#include <sigc++/trackable.h>
#include <typeinfo>
#include <glibmmconfig.h>
@@ -134,7 +135,24 @@ public:
GObject* gobj_copy() const;
#ifndef DOXYGEN_SHOULD_SKIP_THIS
- static ObjectBase* _get_current_wrapper(GObject* object);
+
+ /// This is for use by gtkmm wrappers only, and not by applications.
+ static ObjectBase* _get_current_wrapper(GObject* object); //We keep this non-inline version, to preserve ABI.
+
+ // This is commented-out because it's not clear yet whether it's a worthwhile optimization.
+ /// This is for use by gtkmm wrappers only, and not by applications.
+ //
+ //inline static ObjectBase* _get_current_wrapper_inline(GObject* object)
+ //{
+ // // This is what g_object_get_qdata does internally. However,
+ // // g_object_get_qdata does an addition G_IS_OBJECT(object) check that
+ // // needs three times as much time as the actual lookup.
+ // if(object)
+ // return static_cast<ObjectBase*>(g_datalist_id_get_data(&object->qdata, Glib::quark_));
+ // else
+ // return 0;
+ //}
+
bool _cpp_destruction_is_in_progress() const;
#endif //DOXYGEN_SHOULD_SKIP_THIS
@@ -146,8 +164,21 @@ protected:
bool cpp_destruction_in_progress_;
bool is_anonymous_custom_() const;
- bool is_derived_() const;
+public: // is_derived_() must be public, so that overridden vfuncs and signal handlers can call it via ObjectBase.
+
+ /// This is for use by gtkmm wrappers only, and not by applications.
+ bool is_derived_() const; //We keep this non-inline version, to preserve ABI.
+
+ //This is commented-out because it's not clear yet whether it's a worthwhile optimization.
+ //
+ /// This is for use by gtkmm wrappers only, and not by applications.
+ //inline bool is_derived_inline_() const
+ //{
+ // return (custom_type_name_ != 0);
+ //}
+
+protected:
static void destroy_notify_callback_(void* data);
virtual void destroy_notify_();
diff --git a/tools/m4/signal.m4 b/tools/m4/signal.m4
index 952975f5..3ca9a920 100644
--- a/tools/m4/signal.m4
+++ b/tools/m4/signal.m4
@@ -161,10 +161,10 @@ ifelse(`$9',,,`#ifdef $9'
)dnl
$4 __CPPNAME__`'_Class::$2_callback`'($5)
{
-dnl We cast twice to allow for multiple-inheritance casts, which might
-dnl change the value. We have to use a dynamic_cast because we do not
-dnl know the actual type from which to cast up.
- CppObjectType *const obj = dynamic_cast<CppObjectType*>(
+dnl First, do a simple cast to ObjectBase. We will have to do a dynamic_cast
+dnl eventually, but it is not necessary to check whether we need to call
+dnl the vfunc.
+ Glib::ObjectBase *const obj_base = static_cast<Glib::ObjectBase*>(
Glib::ObjectBase::_get_current_wrapper`'((GObject*)$8));
_IMPORT(SECTION_CHECK)
@@ -173,29 +173,35 @@ _IMPORT(SECTION_CHECK)
// generated classes can use this optimisation, which avoids the unnecessary
// parameter conversions if there is no possibility of the virtual function
// being overridden:
- if(obj && obj->is_derived_())
+ if(obj_base && obj_base->is_derived_())
{
- #ifdef GLIBMM_EXCEPTIONS_ENABLED
- try // Trap C++ exceptions which would normally be lost because this is a C callback.
+dnl We need to do a dynamic cast to get the real object type, to call the
+dnl C++ vfunc on it.
+ CppObjectType *const obj = dynamic_cast<CppObjectType* const>(obj_base);
+ if(obj) // This can be NULL during destruction.
{
- #endif //GLIBMM_EXCEPTIONS_ENABLED
- // Call the virtual member method, which derived classes might override.
+ #ifdef GLIBMM_EXCEPTIONS_ENABLED
+ try // Trap C++ exceptions which would normally be lost because this is a C callback.
+ {
+ #endif //GLIBMM_EXCEPTIONS_ENABLED
+ // Call the virtual member method, which derived classes might override.
ifelse($4,void,`dnl
- obj->on_$1`'($7);
+ obj->on_$1`'($7);
+ return;
',`dnl
- return _CONVERT($3,$4,`obj->on_$1`'($7)');
+ return _CONVERT($3,$4,`obj->on_$1`'($7)');
')dnl
- #ifdef GLIBMM_EXCEPTIONS_ENABLED
- }
- catch(...)
- {
- Glib::exception_handlers_invoke`'();
+ #ifdef GLIBMM_EXCEPTIONS_ENABLED
+ }
+ catch(...)
+ {
+ Glib::exception_handlers_invoke`'();
+ }
+ #endif //GLIBMM_EXCEPTIONS_ENABLED
}
- #endif //GLIBMM_EXCEPTIONS_ENABLED
}
- else
- {
- BaseClassType *const base = static_cast<BaseClassType*>(
+
+ BaseClassType *const base = static_cast<BaseClassType*>(
ifdef(`__BOOL_IS_INTERFACE__',`dnl
_IFACE_PARENT_FROM_OBJECT($8)dnl
',`dnl
@@ -203,10 +209,9 @@ ifdef(`__BOOL_IS_INTERFACE__',`dnl
') );
dnl g_assert(base != 0);
- // Call the original underlying C function:
- if(base && base->$2)
- ifelse($4,void,,`return ')(*base->$2)`'($6);
- }
+ // Call the original underlying C function:
+ if(base && base->$2)
+ ifelse($4,void,,`return ')(*base->$2)`'($6);
ifelse($4,void,,`dnl
typedef $4 RType;
diff --git a/tools/m4/vfunc.m4 b/tools/m4/vfunc.m4
index dc3eba10..67cc2f11 100644
--- a/tools/m4/vfunc.m4
+++ b/tools/m4/vfunc.m4
@@ -23,16 +23,19 @@ dnl _VFUNC_PCC(cppname,gtkname,cpprettype,crettype,
dnl $5 $6 $7 $8 $9 $10
dnl `<cargs and names>',`<cnames>',`<cpparg names>',firstarg, refreturn_ctype, ifdef)
dnl
+dnl Note: _get_current_wrapper_inline() could be used throughout for performance instead of _get_current_wrapper(),
+dnl and is_derived_() instead of is_derived_(),
+dnl but it is not yet clear whether that would be a worthwhile performance optimization.
define(`_VFUNC_PCC',`dnl
_PUSH(SECTION_PCC_VFUNCS)
ifelse(`$10',,,`#ifdef $10'
)dnl
$4 __CPPNAME__`'_Class::$2_vfunc_callback`'($5)
{
-dnl We cast twice to allow for multiple-inheritance casts, which might
-dnl change the value. We have to use a dynamic_cast because we do not
-dnl know the actual type from which to cast up.
- CppObjectType *const obj = dynamic_cast<CppObjectType*>(
+dnl First, do a simple cast to ObjectBase. We will have to do a dynamic_cast
+dnl eventually, but it is not necessary to check whether we need to call
+dnl the vfunc.
+ Glib::ObjectBase *const obj_base = static_cast<Glib::ObjectBase*>(
Glib::ObjectBase::_get_current_wrapper`'((GObject*)$8));
_IMPORT(SECTION_CHECK)
@@ -41,44 +44,50 @@ _IMPORT(SECTION_CHECK)
// generated classes can use this optimisation, which avoids the unnecessary
// parameter conversions if there is no possibility of the virtual function
// being overridden:
- if(obj && obj->is_derived_())
+ if(obj_base && obj_base->is_derived_())
{
- #ifdef GLIBMM_EXCEPTIONS_ENABLED
- try // Trap C++ exceptions which would normally be lost because this is a C callback.
+dnl We need to do a dynamic cast to get the real object type, to call the
+dnl C++ vfunc on it.
+ CppObjectType *const obj = dynamic_cast<CppObjectType* const>(obj_base);
+ if(obj) // This can be NULL during destruction.
{
- #endif //GLIBMM_EXCEPTIONS_ENABLED
- // Call the virtual member method, which derived classes might override.
+ #ifdef GLIBMM_EXCEPTIONS_ENABLED
+ try // Trap C++ exceptions which would normally be lost because this is a C callback.
+ {
+ #endif //GLIBMM_EXCEPTIONS_ENABLED
+ // Call the virtual member method, which derived classes might override.
ifelse($4,void,`dnl
- obj->$1`'($7);
+ obj->$1`'($7);
+ return;
',`dnl
ifelse($9,refreturn_ctype,`dnl Assume Glib::unwrap_copy() is correct if refreturn_ctype is requested.
- return Glib::unwrap_copy`'(`obj->$1'($7));
+ return Glib::unwrap_copy`'(`obj->$1'($7));
',`dnl
- return _CONVERT($3,$4,`obj->$1`'($7)');
+ return _CONVERT($3,$4,`obj->$1`'($7)');
')dnl
')dnl
- #ifdef GLIBMM_EXCEPTIONS_ENABLED
+ #ifdef GLIBMM_EXCEPTIONS_ENABLED
+ }
+ catch(...)
+ {
+ Glib::exception_handlers_invoke`'();
+ }
+ #endif //GLIBMM_EXCEPTIONS_ENABLED
}
- catch(...)
- {
- Glib::exception_handlers_invoke`'();
- }
- #endif //GLIBMM_EXCEPTIONS_ENABLED
}
- else
- {
- BaseClassType *const base = static_cast<BaseClassType*>(
+
+ BaseClassType *const base = static_cast<BaseClassType*>(
ifdef(`__BOOL_IS_INTERFACE__',`dnl
- _IFACE_PARENT_FROM_OBJECT($8)dnl
+ _IFACE_PARENT_FROM_OBJECT($8)dnl
',`dnl
- _PARENT_GCLASS_FROM_OBJECT($8)dnl
-') );
-dnl g_assert(base != 0);
+ _PARENT_GCLASS_FROM_OBJECT($8)dnl
+') );
+dnl g_assert(base != 0);
+
+ // Call the original underlying C function:
+ if(base && base->$2)
+ ifelse($4,void,,`return ')(*base->$2)`'($6);
- // Call the original underlying C function:
- if(base && base->$2)
- ifelse($4,void,,`return ')(*base->$2)`'($6);
- }
ifelse($4,void,,`dnl
typedef $4 RType;