Page 1 of 1

Patch: User data with deleter

Posted: Wed Sep 07, 2011 03:54
by Garthy
Here is a simple patch to CEGUI 0.7.5 that extends setUserData for CEGUI Windows so that you can also specify an optional deleter function. This lets you specify user data safe in the knowledge that it will be cleaned up whenever the user data is reset or the Window destructor is called.

Using this deleter, you can attach user data that requires destruction, and know that the deleter will be called when the data is no longer needed. This lets you do things such as attaching a custom structure (that needs deletion), a shared pointer, or boost::any, knowing that it will be properly cleaned up when it is no longer needed.

Works under Linux and it should be good under Windows too (just finished building it on Windows now- haven't tested it though).

I hope it is useful. :)

PS. Can't attach the patch as a file, including it inline.

Code: Select all

diff -Naur old/cegui/include/CEGUIWindow.h new/cegui/include/CEGUIWindow.h
--- old/cegui/include/CEGUIWindow.h   2010-11-19 11:19:03.000000000 +0000
+++ new/cegui/include/CEGUIWindow.h   2011-09-06 02:15:03.000000000 +0000
@@ -58,6 +58,9 @@
 // Start of CEGUI namespace section
 namespace CEGUI
 {

+  typedef void (*UserDataDeleteFunction)(void *);

 /*!
 \brief
     Enumerated type used when specifying vertical alignments.
@@ -1186,6 +1189,15 @@
 
     /*!
     \brief
+        Return the user data delete function set for this Window.
+
+    \return
+        pointer to the user data delete function that is currently set for this window.
+    */
+    UserDataDeleteFunction getUserDataDelete(void) const   {return d_userDataDelete;}
+
+    /*!
+    \brief
         Return whether this window is set to restore old input capture when it
         loses input capture.
 
@@ -2203,10 +2215,14 @@
     \param user_data
         pointer to the user data that is to be set for this window.
 
+    \param user_data_delete
+        pointer to a function that will be used to "delete" the data each time
+        a new value is set, or upon Window destruction.
+
     \return
         Nothing.
     */
-    void setUserData(void* user_data)   {d_userData = user_data;}
+    void setUserData(void* user_data, UserDataDeleteFunction user_data_delete=0);
 
     /*!
     \brief
@@ -4265,6 +4281,8 @@
     uint d_ID;
     //! Holds pointer to some user assigned data.
     void* d_userData;
+    //! Function that deletes user data.
+    UserDataDeleteFunction d_userDataDelete;
     //! Holds a collection of named user string values.
     UserStringMap d_userStrings;
 
diff -Naur old/cegui/src/CEGUIWindow.cpp new/cegui/src/CEGUIWindow.cpp
--- old/cegui/src/CEGUIWindow.cpp   2010-11-19 11:19:12.000000000 +0000
+++ new/cegui/src/CEGUIWindow.cpp   2011-09-06 02:16:23.000000000 +0000
@@ -237,6 +237,7 @@
     // user specific data
     d_ID(0),
     d_userData(0),
+    d_userDataDelete(0),
 
     // z-order related options
     d_alwaysOnTop(false),
@@ -302,11 +303,23 @@
 {
     // most cleanup actually happened earlier in Window::destroy.
 
+    // Clear user data, triggering the delete function.
+    setUserData(0);
     System::getSingleton().getRenderer()->destroyGeometryBuffer(*d_geometry);
     delete d_bidiVisualMapping;
 }
 
 //----------------------------------------------------------------------------//
+void Window::setUserData(void* user_data, UserDataDeleteFunction user_data_delete)
+{
+    // Trigger any delete function if needed.
+    if (d_userDataDelete)
+      d_userDataDelete(d_userData);
+    d_userData = user_data;
+    d_userDataDelete = user_data_delete;
+}
+
+//----------------------------------------------------------------------------//
 const String& Window::getType(void) const
 {
     return d_falagardType.empty() ? d_type : d_falagardType;

Re: Patch: User data with deleter

Posted: Fri Sep 09, 2011 20:10
by Jamarr
Hi Garthy. Initially this sounds like a good addition, however there is already a mechanism by which clients can manage the destruction of the client-data pointer. You can subscribe to the Window::EventDestructionStarted event and have your event-handler destroy the client-data pointer as appropriate. I believe the existing event-based approach is a bit more robust since 1) it minimizes overhead (no additional memory needed if not used) and 2) the event-handler can be either a free-function or a member-function of an object.

That said, we do appreciate the concern and effort you put into extending CEGUI to better accommodate your own needs. I hope this reply will not discourage you from making further improvements to CEGUI, because we could certainly use the help ;)

Re: Patch: User data with deleter

Posted: Sun Sep 11, 2011 07:15
by Garthy
Hi Jamarr,

Jamarr wrote:Hi Garthy. Initially this sounds like a good addition, however there is already a mechanism by which clients can manage the destruction of the client-data pointer. You can subscribe to the Window::EventDestructionStarted event and have your event-handler destroy the client-data pointer as appropriate. I believe the existing event-based approach is a bit more robust since 1) it minimizes overhead (no additional memory needed if not used) and 2) the event-handler can be either a free-function or a member-function of an object.


Ah. I didn't know there was an existing means to catch Window destruction like this. Good to know. :)

Jamarr wrote:That said, we do appreciate the concern and effort you put into extending CEGUI to better accommodate your own needs. I hope this reply will not discourage you from making further improvements to CEGUI, because we could certainly use the help ;)


Not a problem, don't worry, it won't discourage me from making occasional random tweaks and sharing the results.

Garthy