From cef5b2298a6ddb131176bbfc590b5e2af38daea2 Mon Sep 17 00:00:00 2001 From: Armin Burgmeier Date: Fri, 23 Mar 2007 17:16:49 +0000 Subject: Use static_cast in vfuncs and signal handlers to cast the wrapper object 2007-03-17 Armin Burgmeier * 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 --- ChangeLog | 18 +++++++++++++ glib/glibmm/objectbase.h | 35 +++++++++++++++++++++++-- tools/m4/signal.m4 | 53 +++++++++++++++++++++----------------- tools/m4/vfunc.m4 | 67 +++++++++++++++++++++++++++--------------------- 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 + + * 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 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 #include #include +#include #include #include #include @@ -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(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( +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::_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(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 *const base = static_cast( 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 `',`',`',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( +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::_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(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 *const base = static_cast( 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; -- cgit v1.2.1