[gegl] buffer: keep a count of number of times ::changed signal is connected



commit 3fb71f9606d8db94b651a3942ba535dd169553c0
Author: Øyvind Kolås <pippin gimp org>
Date:   Wed Jun 18 18:21:18 2014 +0200

    buffer: keep a count of number of times ::changed signal is connected
    
    There is overhead involved in emitting changed signals, even when nothing is
    connected. This adds a wrapper function to be used instead of g_signal_connect
    that tags the buffer as a buffer that should be emitting changed signals.

 gegl/buffer/gegl-buffer-private.h  |    2 ++
 gegl/buffer/gegl-buffer.c          |   25 +++++++++++++++++++------
 gegl/buffer/gegl-buffer.h          |   22 ++++++++++++++++++++++
 gegl/buffer/gegl-sampler.c         |    7 ++++---
 tests/simple/test-buffer-changes.c |    4 ++--
 5 files changed, 49 insertions(+), 11 deletions(-)
---
diff --git a/gegl/buffer/gegl-buffer-private.h b/gegl/buffer/gegl-buffer-private.h
index 841b88d..b5dbd71 100644
--- a/gegl/buffer/gegl-buffer-private.h
+++ b/gegl/buffer/gegl-buffer-private.h
@@ -72,6 +72,8 @@ struct _GeglBuffer
   gint              alloc_stack_size;
 
   GeglTileBackend  *backend;
+
+  gint              changed_signal_connections;
 };
 
 struct _GeglBufferClass
diff --git a/gegl/buffer/gegl-buffer.c b/gegl/buffer/gegl-buffer.c
index e157e2f..4124816 100644
--- a/gegl/buffer/gegl-buffer.c
+++ b/gegl/buffer/gegl-buffer.c
@@ -1159,12 +1159,25 @@ void
 gegl_buffer_emit_changed_signal (GeglBuffer          *buffer,
                                  const GeglRectangle *rect)
 {
-  GeglRectangle copy;
+  if (buffer->changed_signal_connections)
+  {
+    GeglRectangle copy;
 
-  if (rect == NULL)
-    copy = *gegl_buffer_get_extent (buffer);
-  else
-    copy = *rect;
+    if (rect == NULL)
+      copy = *gegl_buffer_get_extent (buffer);
+    else
+      copy = *rect;
+
+    g_signal_emit (buffer, gegl_buffer_signals[CHANGED], 0, &copy, NULL);
+  }
+}
 
-  g_signal_emit (buffer, gegl_buffer_signals[CHANGED], 0, &copy, NULL);
+glong gegl_buffer_signal_connect (GeglBuffer *buffer,
+                                  const char *detailed_signal,
+                                  GCallback   c_handler,
+                                  gpointer    data)
+{
+  buffer->changed_signal_connections++;
+  return g_signal_connect(buffer, detailed_signal, c_handler, data);
 }
+
diff --git a/gegl/buffer/gegl-buffer.h b/gegl/buffer/gegl-buffer.h
index e07e4f3..22f9f06 100644
--- a/gegl/buffer/gegl-buffer.h
+++ b/gegl/buffer/gegl-buffer.h
@@ -610,6 +610,28 @@ void            gegl_buffer_linear_close      (GeglBuffer    *buffer,
  */
 const GeglRectangle * gegl_buffer_get_abyss   (GeglBuffer           *buffer);
 
+
+
+/**
+ * gegl_buffer_signal_connect:
+ * @buffer: a GeglBuffer
+ * @detailed_signal: only "changed" expected for now
+ * @c_handler: c function callback
+ * @data: user data:
+ *
+ * This function should be used instead of g_signal_connect when connecting to
+ * the GeglBuffer::changed signal handler, GeglBuffer contains additional
+ * machinery to avoid the overhead of changes when no signal handler have been
+ * connected, if regular g_signal_connect is used; then no signals will be
+ * emitted.
+ *
+ * Returns: an handle like g_signal_connect.
+ */
+glong gegl_buffer_signal_connect (GeglBuffer *buffer,
+                                  const char *detailed_signal,
+                                  GCallback   c_handler,
+                                  gpointer    data);
+
 #include <gegl-buffer-iterator.h>
 
 G_END_DECLS
diff --git a/gegl/buffer/gegl-sampler.c b/gegl/buffer/gegl-sampler.c
index d1629ee..7a117c4 100644
--- a/gegl/buffer/gegl-sampler.c
+++ b/gegl/buffer/gegl-sampler.c
@@ -415,6 +415,7 @@ set_buffer (GeglSampler *self, GeglBuffer *buffer)
           g_signal_handlers_disconnect_by_func (self->buffer,
                                                 G_CALLBACK (buffer_contents_changed),
                                                 self);
+          self->buffer->changed_signal_connections--;
           g_object_remove_weak_pointer ((GObject*) self->buffer, (void**) &self->buffer);
         }
 
@@ -422,9 +423,9 @@ set_buffer (GeglSampler *self, GeglBuffer *buffer)
         {
           self->buffer = buffer;
           g_object_add_weak_pointer ((GObject*) self->buffer, (void**) &self->buffer);
-          g_signal_connect (buffer, "changed",
-                            G_CALLBACK (buffer_contents_changed),
-                            self);
+          gegl_buffer_signal_connect (buffer, "changed",
+                                      G_CALLBACK (buffer_contents_changed),
+                                      self);
         }
       else
         self->buffer = NULL;
diff --git a/tests/simple/test-buffer-changes.c b/tests/simple/test-buffer-changes.c
index 2a1b273..1aae041 100644
--- a/tests/simple/test-buffer-changes.c
+++ b/tests/simple/test-buffer-changes.c
@@ -82,7 +82,7 @@ test_buffer_change_signal_on_set(void)
     GeglRectangle rect = {0, 0, 100, 100};
     char *tmp = g_malloc(rect.height*rect.width*1*4);
     
-    g_signal_connect(test_case->buffer, "changed", (GCallback)handle_buffer_changed, test_case);
+    gegl_buffer_signal_connect(test_case->buffer, "changed", (GCallback)handle_buffer_changed, test_case);
     
     gegl_buffer_set(test_case->buffer, &rect, 1, test_case->buffer_format, tmp, GEGL_AUTO_ROWSTRIDE);
     
@@ -107,7 +107,7 @@ test_buffer_change_signal_with_iter(guint access_method, guint expected_signal_c
     GeglBufferIterator *gi = gegl_buffer_iterator_new(test_case->buffer, &rect, 0,
                                 test_case->buffer_format, access_method, GEGL_ABYSS_NONE);
     
-    g_signal_connect(test_case->buffer, "changed", (GCallback)handle_buffer_changed, test_case);
+    gegl_buffer_signal_connect(test_case->buffer, "changed", (GCallback)handle_buffer_changed, test_case);
 
     while (gegl_buffer_iterator_next(gi)) {
     }


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