[gstreamermm] MiniObject derived classes: Correct wrapper memory leak.



commit 3a83d2215253a3099c1c521c84123bfed7849855
Author: Josà Alburquerque <jaalburqu svn gnome org>
Date:   Tue Sep 11 23:17:59 2012 -0400

    MiniObject derived classes: Correct wrapper memory leak.
    
    	* gstreamer/src/buffer.{ccg,hg}:
    	* gstreamer/src/bufferlist.{ccg,hg}:
    	* gstreamer/src/discovererinfo.{ccg,hg}: Add custom wrap_new()
    	functions to the Gst::MiniObject derived classes in these files so
    	that when the C objects are wrapped, a weak reference is added to the
    	miniobject and the newly created wrapper can be destroyed in the
    	specified callbacks.  Also add the callbacks that destroy the wrappers
    	on weak referencing notification.  Use the _CUSTOM_WRAP_NEW macro in
    	the class declarations to ensure that gmmproc knows that these classes
    	have custom wrap_new() functions.
    
    	* gstreamer/src/event.ccg:
    	* gstreamer/src/message.ccg:
    	* gstreamer/src/query.ccg: Modify the custom class wrap() methods to
    	add weak reference notification on the newly given GstMiniObject.  Add
    	the callbacks which destroy the wrapper on weak reference
    	notification.
    
    	* gstreamer/gstreamermm/miniobject.cc (~MiniObject): Ensure that the
    	destructor does not try to unreference an object that is being
    	destroyed because of a weak reference (when the reference is already
    	zero).
    
    	Bug #608702 (Massimiliano).

 ChangeLog                           |   29 +++++++++
 gstreamer/gstreamermm/miniobject.cc |    6 ++-
 gstreamer/src/buffer.ccg            |   26 ++++++++
 gstreamer/src/buffer.hg             |    1 +
 gstreamer/src/bufferlist.ccg        |   19 ++++++
 gstreamer/src/bufferlist.hg         |    1 +
 gstreamer/src/discovererinfo.ccg    |  110 +++++++++++++++++++++++++++++++++++
 gstreamer/src/discovererinfo.hg     |    5 ++
 gstreamer/src/event.ccg             |   22 +++++++
 gstreamer/src/message.ccg           |   22 +++++++
 gstreamer/src/query.ccg             |   22 +++++++
 11 files changed, 262 insertions(+), 1 deletions(-)
---
diff --git a/ChangeLog b/ChangeLog
index 4ecac22..eb5d694 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,32 @@
+2012-09-11  Josà Alburquerque  <jaalburquerque gmail com>
+
+	MiniObject derived classes: Correct wrapper memory leak.
+
+	* gstreamer/src/buffer.{ccg,hg}:
+	* gstreamer/src/bufferlist.{ccg,hg}:
+	* gstreamer/src/discovererinfo.{ccg,hg}: Add custom wrap_new()
+	functions to the Gst::MiniObject derived classes in these files so
+	that when the C objects are wrapped, a weak reference is added to the
+	miniobject and the newly created wrapper can be destroyed in the
+	specified callbacks.  Also add the callbacks that destroy the wrappers
+	on weak referencing notification.  Use the _CUSTOM_WRAP_NEW macro in
+	the class declarations to ensure that gmmproc knows that these classes
+	have custom wrap_new() functions.
+
+	* gstreamer/src/event.ccg:
+	* gstreamer/src/message.ccg:
+	* gstreamer/src/query.ccg: Modify the custom class wrap() methods to
+	add weak reference notification on the newly given GstMiniObject.  Add
+	the callbacks which destroy the wrapper on weak reference
+	notification.
+
+	* gstreamer/gstreamermm/miniobject.cc (~MiniObject): Ensure that the
+	destructor does not try to unreference an object that is being
+	destroyed because of a weak reference (when the reference is already
+	zero).
+
+	Bug #608702 (Massimiliano).
+
 2012-09-07  Josà Alburquerque  <jaalburquerque gmail com>
 
 	Query: Correct the docs usage example so that its lines compile.
diff --git a/gstreamer/gstreamermm/miniobject.cc b/gstreamer/gstreamermm/miniobject.cc
index d06ec97..aadfac8 100644
--- a/gstreamer/gstreamermm/miniobject.cc
+++ b/gstreamer/gstreamermm/miniobject.cc
@@ -78,7 +78,11 @@ GstMiniObject* MiniObject::gobj_copy()
 
 MiniObject::~MiniObject()
 {
-  if(gobject_)
+  // The value of the reference count is checked so that if this mini object is
+  // being destroyed as a result of weak reference notification no
+  // unreferencing is done and thus no error is issued on unreferencing a mini
+  // object with a reference of 0.
+  if(gobject_ && GST_MINI_OBJECT_REFCOUNT_VALUE(gobject_) > 0)
     gst_mini_object_unref(gobject_);
 }
 
diff --git a/gstreamer/src/buffer.ccg b/gstreamer/src/buffer.ccg
index 299281b..e6ea02c 100644
--- a/gstreamer/src/buffer.ccg
+++ b/gstreamer/src/buffer.ccg
@@ -23,6 +23,22 @@
 
 _PINCLUDE(gstreamermm/private/miniobject_p.h)
 
+namespace
+{
+
+extern "C"
+{
+
+static void Buffer_gstreamermm_callback_destroy(void* data,
+  GstMiniObject* /* where_the_object_was */)
+{
+  delete static_cast<Gst::Buffer*>(data);
+}
+
+}
+
+}
+
 namespace Gst
 {
 
@@ -36,4 +52,14 @@ Glib::RefPtr<Gst::Buffer> Buffer::create_writable()
   return Gst::wrap(gst_buffer_make_writable(gobj()));
 }
 
+Gst::MiniObject* Buffer_Class::wrap_new(GstMiniObject* object)
+{
+  // Use this wrap_new() method to ensure that the wrapper is destroyed
+  // when the miniobject loses its last reference.
+
+  Gst::Buffer* wrapper = new Gst::Buffer((GstBuffer*)(object));
+  gst_mini_object_weak_ref(object, &Buffer_gstreamermm_callback_destroy, wrapper);
+  return wrapper;
+}
+
 } // namespace Gst
diff --git a/gstreamer/src/buffer.hg b/gstreamer/src/buffer.hg
index ac0c0ec..a1bc2e4 100644
--- a/gstreamer/src/buffer.hg
+++ b/gstreamer/src/buffer.hg
@@ -45,6 +45,7 @@ _WRAP_ENUM(BufferCopyFlags, GstBufferCopyFlags)
 class Buffer : public MiniObject
 {
   _CLASS_GSTMINIOBJECT(Buffer, GstBuffer, GST_BUFFER, Gst::MiniObject, GstMiniObject)
+  _CUSTOM_WRAP_NEW
 
 public:
   _WRAP_METHOD(static Glib::RefPtr<Gst::Buffer> create(), gst_buffer_new)
diff --git a/gstreamer/src/bufferlist.ccg b/gstreamer/src/bufferlist.ccg
index 64f0f07..c414794 100644
--- a/gstreamer/src/bufferlist.ccg
+++ b/gstreamer/src/bufferlist.ccg
@@ -86,6 +86,12 @@ static GstBuffer* BufferListIterator_Process_gstreamermm_callback(GstBuffer* buf
   return 0;
 }
 
+static void BufferList_gstreamermm_callback_destroy(void* data,
+  GstMiniObject* /* where_the_object_was */)
+{
+  delete static_cast<Gst::BufferList*>(data);
+}
+
 } // extern "C"
 
 
@@ -118,6 +124,19 @@ void BufferList::iterate(BufferListIterator& result)
   result.set_gobject(gst_buffer_list_iterate(gobj()));
 }
 
+Gst::MiniObject* BufferList_Class::wrap_new(GstMiniObject* object)
+{
+  // Use this wrap_new() method to ensure that the wrapper is destroyed
+  // when the miniobject loses its last reference.
+
+  Gst::BufferList* wrapper = new Gst::BufferList((GstBufferList*)(object));
+
+  gst_mini_object_weak_ref(object, &BufferList_gstreamermm_callback_destroy,
+    wrapper);
+
+  return wrapper;
+}
+
 BufferListIterator::BufferListIterator()
 : gobject_(0),
   take_ownership(false)
diff --git a/gstreamer/src/bufferlist.hg b/gstreamer/src/bufferlist.hg
index 32570cc..18be604 100644
--- a/gstreamer/src/bufferlist.hg
+++ b/gstreamer/src/bufferlist.hg
@@ -50,6 +50,7 @@ class BufferListIterator;
 class BufferList : public MiniObject
 {
   _CLASS_GSTMINIOBJECT(BufferList, GstBufferList, GST_BUFFER_LIST, Gst::MiniObject, GstMiniObject)
+  _CUSTOM_WRAP_NEW
 
 public:
   /** For example,
diff --git a/gstreamer/src/discovererinfo.ccg b/gstreamer/src/discovererinfo.ccg
index 3c04053..ef29e1b 100644
--- a/gstreamer/src/discovererinfo.ccg
+++ b/gstreamer/src/discovererinfo.ccg
@@ -24,7 +24,117 @@
 
 _PINCLUDE(gstreamermm/private/miniobject_p.h)
 
+namespace
+{
+
+extern "C"
+{
+
+static void DiscovererInfo_gstreamermm_callback_destroy(void* data,
+  GstMiniObject* /* where_the_object_was */)
+{
+  delete static_cast<Gst::DiscovererInfo*>(data);
+}
+
+static void DiscovererStreamInfo_gstreamermm_callback_destroy(void* data,
+  GstMiniObject* /* where_the_object_was */)
+{
+  delete static_cast<Gst::DiscovererStreamInfo*>(data);
+}
+
+static void DiscovererContainerInfo_gstreamermm_callback_destroy(void* data,
+  GstMiniObject* /* where_the_object_was */)
+{
+  delete static_cast<Gst::DiscovererContainerInfo*>(data);
+}
+
+static void DiscovererAudioInfo_gstreamermm_callback_destroy(void* data,
+  GstMiniObject* /* where_the_object_was */)
+{
+  delete static_cast<Gst::DiscovererAudioInfo*>(data);
+}
+
+static void DiscovererVideoInfo_gstreamermm_callback_destroy(void* data,
+  GstMiniObject* /* where_the_object_was */)
+{
+  delete static_cast<Gst::DiscovererVideoInfo*>(data);
+}
+
+}
+
+}
+
 namespace Gst
 {
 
+Gst::MiniObject* DiscovererInfo_Class::wrap_new(GstMiniObject* object)
+{
+  // Use this wrap_new() method to ensure that the wrapper is destroyed
+  // when the miniobject loses its last reference.
+
+  Gst::DiscovererInfo* wrapper =
+    new Gst::DiscovererInfo((GstDiscovererInfo*)(object));
+
+  gst_mini_object_weak_ref(object,
+    &DiscovererInfo_gstreamermm_callback_destroy, wrapper);
+
+  return wrapper;
+}
+
+Gst::MiniObject* DiscovererStreamInfo_Class::wrap_new(GstMiniObject* object)
+{
+  // Use this wrap_new() method to ensure that the wrapper is destroyed
+  // when the miniobject loses its last reference.
+
+  Gst::DiscovererStreamInfo* wrapper =
+    new Gst::DiscovererStreamInfo((GstDiscovererStreamInfo*)(object));
+
+  gst_mini_object_weak_ref(object,
+    &DiscovererStreamInfo_gstreamermm_callback_destroy, wrapper);
+
+  return wrapper;
+}
+
+Gst::MiniObject* DiscovererContainerInfo_Class::wrap_new(GstMiniObject* object)
+{
+  // Use this wrap_new() method to ensure that the wrapper is destroyed
+  // when the miniobject loses its last reference.
+
+  Gst::DiscovererContainerInfo* wrapper =
+    new Gst::DiscovererContainerInfo((GstDiscovererContainerInfo*)(object));
+
+  gst_mini_object_weak_ref(object,
+    &DiscovererContainerInfo_gstreamermm_callback_destroy, wrapper);
+
+  return wrapper;
+}
+
+Gst::MiniObject* DiscovererAudioInfo_Class::wrap_new(GstMiniObject* object)
+{
+  // Use this wrap_new() method to ensure that the wrapper is destroyed
+  // when the miniobject loses its last reference.
+
+  Gst::DiscovererAudioInfo* wrapper =
+    new Gst::DiscovererAudioInfo((GstDiscovererAudioInfo*)(object));
+
+  gst_mini_object_weak_ref(object,
+    &DiscovererAudioInfo_gstreamermm_callback_destroy, wrapper);
+
+  return wrapper;
+}
+
+Gst::MiniObject* DiscovererVideoInfo_Class::wrap_new(GstMiniObject* object)
+{
+  // Use this wrap_new() method to ensure that the wrapper is destroyed
+  // when the miniobject loses its last reference.
+
+  Gst::DiscovererVideoInfo* wrapper =
+    new Gst::DiscovererVideoInfo((GstDiscovererVideoInfo*)(object));
+
+  gst_mini_object_weak_ref(object,
+    &DiscovererVideoInfo_gstreamermm_callback_destroy, wrapper);
+
+  return wrapper;
+}
+
 } // namespace Gst
diff --git a/gstreamer/src/discovererinfo.hg b/gstreamer/src/discovererinfo.hg
index 402ea2d..2d20334 100644
--- a/gstreamer/src/discovererinfo.hg
+++ b/gstreamer/src/discovererinfo.hg
@@ -65,6 +65,7 @@ class DiscovererInfo : public MiniObject
   _STRUCT_NOT_HIDDEN
   _CLASS_GSTMINIOBJECT(DiscovererInfo, GstDiscovererInfo, GST_DISCOVERER_INFO, MiniObject, GstMiniObject)
   _IGNORE(gst_discoverer_info_ref, gst_discoverer_info_unref)
+  _CUSTOM_WRAP_NEW
 
 public:
   _WRAP_METHOD(ClockTime get_duration() const, gst_discoverer_info_get_duration) 
@@ -124,6 +125,7 @@ class DiscovererStreamInfo : public MiniObject
   _STRUCT_NOT_HIDDEN
   _CLASS_GSTMINIOBJECT(DiscovererStreamInfo, GstDiscovererStreamInfo, GST_DISCOVERER_STREAM_INFO, MiniObject, GstMiniObject)
   _IGNORE(gst_discoverer_stream_info_ref, gst_discoverer_stream_info_unref)
+  _CUSTOM_WRAP_NEW
 
 public:
   _WRAP_METHOD(Glib::RefPtr<Gst::Caps> get_caps(), gst_discoverer_stream_info_get_caps)
@@ -149,6 +151,7 @@ class DiscovererContainerInfo : public DiscovererStreamInfo
 {
   _STRUCT_NOT_HIDDEN
   _CLASS_GSTMINIOBJECT(DiscovererContainerInfo, GstDiscovererContainerInfo, GST_DISCOVERER_CONTAINER_INFO, DiscovererStreamInfo, GstDiscovererStreamInfo)
+  _CUSTOM_WRAP_NEW
 
 public:
   _WRAP_METHOD(std::vector< Glib::RefPtr<DiscovererStreamInfo> > get_streams(), gst_discoverer_container_info_get_streams)
@@ -162,6 +165,7 @@ class DiscovererAudioInfo : public DiscovererStreamInfo
 {
   _STRUCT_NOT_HIDDEN
   _CLASS_GSTMINIOBJECT(DiscovererAudioInfo, GstDiscovererAudioInfo, GST_DISCOVERER_AUDIO_INFO, DiscovererStreamInfo, GstDiscovererStreamInfo)
+  _CUSTOM_WRAP_NEW
 
 public:
   _WRAP_METHOD(guint get_bitrate() const, gst_discoverer_audio_info_get_bitrate)
@@ -178,6 +182,7 @@ class DiscovererVideoInfo : public DiscovererStreamInfo
 {
   _STRUCT_NOT_HIDDEN
   _CLASS_GSTMINIOBJECT(DiscovererVideoInfo, GstDiscovererVideoInfo, GST_DISCOVERER_VIDEO_INFO, DiscovererStreamInfo, GstDiscovererStreamInfo)
+  _CUSTOM_WRAP_NEW
 
 public:
   _WRAP_METHOD(guint get_bitrate() const, gst_discoverer_video_info_get_bitrate)
diff --git a/gstreamer/src/event.ccg b/gstreamer/src/event.ccg
index bb0e324..5539fbf 100644
--- a/gstreamer/src/event.ccg
+++ b/gstreamer/src/event.ccg
@@ -23,6 +23,25 @@
 #include <gstreamermm/structure.h>
 #include <gstreamermm/taglist.h>
 _PINCLUDE(gstreamermm/private/miniobject_p.h)
+#include <iostream>
+
+namespace
+{
+
+extern "C"
+{
+
+static void Event_gstreamermm_callback_destroy(void* data,
+  GstMiniObject* where_the_object_was)
+{
+  // This works for any of the Gst::Event derived classes because none of
+  // them have member variables so in essence they are all the same size.
+  delete static_cast<Gst::Event*>(data);
+}
+
+}
+
+}
 
 namespace Gst
 {
@@ -526,6 +545,9 @@ Glib::RefPtr<Gst::Event> Event::wrap(GstEvent* event, bool take_copy)
 
   result = Glib::RefPtr<Gst::Event>(wrapper);
 
+  // Ensure that the wrapper is freed when the event (mini object) is freed.
+  gst_mini_object_weak_ref(GST_MINI_OBJECT(event), &Event_gstreamermm_callback_destroy, wrapper);
+
   if(take_copy)
     result->reference();
 
diff --git a/gstreamer/src/message.ccg b/gstreamer/src/message.ccg
index ffe49c9..706403c 100644
--- a/gstreamer/src/message.ccg
+++ b/gstreamer/src/message.ccg
@@ -25,6 +25,25 @@
 #include <gstreamermm/structure.h>
 #include <gstreamermm/taglist.h>
 _PINCLUDE(gstreamermm/private/miniobject_p.h)
+#include <iostream>
+
+namespace
+{
+
+extern "C"
+{
+
+static void Message_gstreamermm_callback_destroy(void* data,
+  GstMiniObject* /* where_the_object_was */)
+{
+  // This works for any of the Gst::Message derived classes because none of
+  // them have member variables so in essence they are all the same size.
+  delete static_cast<Gst::Message*>(data);
+}
+
+}
+
+}
 
 namespace Gst
 {
@@ -1086,6 +1105,9 @@ Glib::RefPtr<Gst::Message> Message::wrap(GstMessage* message, bool take_copy)
 
   result = Glib::RefPtr<Gst::Message>(wrapper);
 
+  // Ensure that the wrapper is freed when the message (mini object) is freed.
+  gst_mini_object_weak_ref(GST_MINI_OBJECT(message), &Message_gstreamermm_callback_destroy, wrapper);
+
   if(take_copy)
     result->reference();
 
diff --git a/gstreamer/src/query.ccg b/gstreamer/src/query.ccg
index ca98258..70ab67a 100644
--- a/gstreamer/src/query.ccg
+++ b/gstreamer/src/query.ccg
@@ -21,6 +21,25 @@
 #include <gstreamermm/iterator.h>
 
 _PINCLUDE(gstreamermm/private/miniobject_p.h)
+#include <iostream>
+
+namespace
+{
+
+extern "C"
+{
+
+static void Query_gstreamermm_callback_destroy(void* data,
+  GstMiniObject* where_the_object_was)
+{
+  // This works for any of the Gst::Query derived classes because none of
+  // them have member variables so in essence they are all the same size.
+  delete static_cast<Gst::Query*>(data);
+}
+
+}
+
+}
 
 namespace Gst
 {
@@ -590,6 +609,9 @@ Glib::RefPtr<Gst::Query> Query::wrap(GstQuery* query, bool take_copy)
 
   result = Glib::RefPtr<Gst::Query>(wrapper);
 
+  // Ensure that the wrapper is freed when the query (mini object) is freed.
+  gst_mini_object_weak_ref(GST_MINI_OBJECT(query), &Query_gstreamermm_callback_destroy, wrapper);
+
   if(take_copy)
     result->reference();
 



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]