[gegl] Re-enable shared read-write buffers.



commit 66a7cd72883baff6575fd25295bf499767258fd3
Author: �yvind Kolås <pippin gimp org>
Date:   Fri Nov 27 00:41:46 2009 +0000

    Re-enable shared read-write buffers.
    
    glib provides the ability to open files read/write now, re-enabled
    code that synchronises access from multiple concurrent GEGL processes.
    The code seems to have some flakiness but it basically works.

 examples/geglbuffer-clock.c          |    9 +++-
 examples/multiplayer-paint.sh        |   10 ++--
 gegl/buffer/Makefile.am              |    1 +
 gegl/buffer/gegl-buffer-access.c     |    2 -
 gegl/buffer/gegl-buffer-iterator.c   |    5 ++-
 gegl/buffer/gegl-buffer-linear.c     |    2 +-
 gegl/buffer/gegl-buffer.c            |   27 +++++------
 gegl/buffer/gegl-tile-backend-file.c |   83 +++++++++++++++++++--------------
 gegl/buffer/gegl-tile.c              |    4 --
 gegl/gegl-config.c                   |    4 +-
 gegl/property-types/gegl-path.c      |   12 +++--
 operations/common/buffer-source.c    |   14 ++++++
 12 files changed, 101 insertions(+), 72 deletions(-)
---
diff --git a/examples/geglbuffer-clock.c b/examples/geglbuffer-clock.c
index 4691883..6dd2656 100644
--- a/examples/geglbuffer-clock.c
+++ b/examples/geglbuffer-clock.c
@@ -11,6 +11,7 @@ main (gint    argc,
       gchar **argv)
 {
   GeglNode   *gegl;   /* the gegl graph we're using as a node factor */
+  GeglBuffer *buffer;
   GeglNode   *display,
              *text,
              *layer,
@@ -31,6 +32,8 @@ main (gint    argc,
   gegl = gegl_node_new ();
 
 
+  buffer = gegl_buffer_open (argv[1]);
+
   blank      = gegl_node_new_child (gegl,
                                     "operation", "gegl:color",
                                     "value", gegl_color_new ("rgba(0.0,0.0,0.0,0.4)"),
@@ -57,11 +60,11 @@ main (gint    argc,
   text       = gegl_node_new_child (gegl,
                                    "operation", "gegl:text",
                                    "size", 20.0,
-                             /*      "color", gegl_color_new ("rgb(0.0,0.0,0.0)"),*/
+                                   "color", gegl_color_new ("rgb(1.0,1.0,1.0)"),
                                    NULL);
   display    = gegl_node_new_child (gegl,
-                                    "operation", "gegl:composite-buffer",
-                                    "path", argv[1],
+                                    "operation", "gegl:write-buffer",
+                                    "buffer", buffer,
                                     NULL);
 
   gegl_node_link_many (blank, crop, layer, shift, display, NULL);
diff --git a/examples/multiplayer-paint.sh b/examples/multiplayer-paint.sh
index d47e1cf..7d72f90 100755
--- a/examples/multiplayer-paint.sh
+++ b/examples/multiplayer-paint.sh
@@ -1,12 +1,12 @@
 #!/bin/sh
 
+killall -9 geglbuffer-clock gegl-paint lt-geglbuffer-clock lt-gegl-paint
+
 ./2geglbuffer data/surfer.png test.gegl
-./geglbuffer-add-image test.gegl data/surfer.png 64 64
-./geglbuffer-clock test.gegl &
 
 ./gegl-paint test.gegl &
 ./gegl-paint test.gegl &
+sleep 3
+#./geglbuffer-add-image test.gegl data/surfer.png 64 64
+./geglbuffer-clock test.gegl 
 
-gegl -x '<gegl><open-buffer path="test.gegl"/></gegl>'
-
-killall -9 geglbuffer-clock gegl-paint lt-geglbuffer-clock lt-gegl-paint
diff --git a/gegl/buffer/Makefile.am b/gegl/buffer/Makefile.am
index 21c44a6..5458703 100644
--- a/gegl/buffer/Makefile.am
+++ b/gegl/buffer/Makefile.am
@@ -41,6 +41,7 @@ libbuffer_la_SOURCES = \
     gegl-tile-storage.c		\
     gegl-tile-backend.c		\
     gegl-tile-backend-file.c	\
+    gegl-tile-backend-gio.c	\
     gegl-tile-backend-ram.c	\
     gegl-tile-handler.c		\
     gegl-tile-handler-cache.c	\
diff --git a/gegl/buffer/gegl-buffer-access.c b/gegl/buffer/gegl-buffer-access.c
index ac0ddd0..d8f4afb 100644
--- a/gegl/buffer/gegl-buffer-access.c
+++ b/gegl/buffer/gegl-buffer-access.c
@@ -1061,9 +1061,7 @@ gegl_buffer_get (GeglBuffer          *buffer,
                  gint                 rowstride)
 {
   g_return_if_fail (GEGL_IS_BUFFER (buffer));
-  gegl_buffer_lock (buffer);
   gegl_buffer_get_unlocked (buffer, scale, rect, format, dest_buf, rowstride);
-  gegl_buffer_unlock (buffer);
 }
 
 const GeglRectangle *
diff --git a/gegl/buffer/gegl-buffer-iterator.c b/gegl/buffer/gegl-buffer-iterator.c
index 4973d38..b716d23 100644
--- a/gegl/buffer/gegl-buffer-iterator.c
+++ b/gegl/buffer/gegl-buffer-iterator.c
@@ -433,7 +433,10 @@ gboolean gegl_buffer_iterator_next     (GeglBufferIterator *iterator)
 
                   ensure_buf (i, no);
 
-                  gegl_buffer_set_unlocked (i->buffer[no], &(i->roi[no]), i->format[no], i->buf[no], GEGL_AUTO_ROWSTRIDE);
+  /* XXX: should perhaps use _set_unlocked, and keep the lock in the
+   * iterator.
+   */
+                  gegl_buffer_set (i->buffer[no], &(i->roi[no]), i->format[no], i->buf[no], GEGL_AUTO_ROWSTRIDE);
                 }
             }
         }
diff --git a/gegl/buffer/gegl-buffer-linear.c b/gegl/buffer/gegl-buffer-linear.c
index 6977a2f..0626359 100644
--- a/gegl/buffer/gegl-buffer-linear.c
+++ b/gegl/buffer/gegl-buffer-linear.c
@@ -243,7 +243,7 @@ gegl_buffer_linear_close (GeglBuffer *buffer,
                          */
                 }
 
-              gegl_buffer_set_unlocked (buffer, &info->extent, info->format, info->buf, 0);
+              gegl_buffer_set (buffer, &info->extent, info->format, info->buf, 0);
               break;
             }
           else
diff --git a/gegl/buffer/gegl-buffer.c b/gegl/buffer/gegl-buffer.c
index ff8d91c..3d9bbac 100644
--- a/gegl/buffer/gegl-buffer.c
+++ b/gegl/buffer/gegl-buffer.c
@@ -1206,14 +1206,13 @@ gboolean gegl_buffer_is_shared (GeglBuffer *buffer)
 
 gboolean gegl_buffer_try_lock (GeglBuffer *buffer)
 {
-#if 0
+  gboolean ret;
   GeglTileBackend *backend = gegl_buffer_backend (buffer);
   if (buffer->lock_count>0)
     {
       buffer->lock_count++;
       return TRUE;
     }
-  gboolean ret;
   if (gegl_buffer_is_shared(buffer))
     ret =gegl_tile_backend_file_try_lock (GEGL_TILE_BACKEND_FILE (backend));
   else
@@ -1221,26 +1220,26 @@ gboolean gegl_buffer_try_lock (GeglBuffer *buffer)
   if (ret)
     buffer->lock_count++;
   return TRUE;
-#else
-  //return g_mutex_trylock (buffer->tile_storage->mutex);
-  return FALSE;
-#endif
 }
 
-#if 1
+/* this locking is for synchronising shared buffers */
 gboolean gegl_buffer_lock (GeglBuffer *buffer)
 {
-#if ENABLE_MT
-  if(0)g_mutex_lock (buffer->tile_storage->mutex);
-#endif
+  while (gegl_buffer_try_lock (buffer)==FALSE)
+    {
+      g_print ("waiting to aquire buffer..");
+        g_usleep (100000);
+    }
   return TRUE;
 }
 
 gboolean gegl_buffer_unlock (GeglBuffer *buffer)
 {
-#if ENABLE_MT
-  if(0)g_mutex_unlock (buffer->tile_storage->mutex);
-#endif
+  GeglTileBackend *backend = gegl_buffer_backend (buffer);
+  g_assert (buffer->lock_count >=0);
+  buffer->lock_count--;
+  g_assert (buffer->lock_count >=0);
+  if (buffer->lock_count == 0 && gegl_buffer_is_shared (buffer))
+    return gegl_tile_backend_file_unlock (GEGL_TILE_BACKEND_FILE (backend));
   return TRUE;
 }
-#endif
diff --git a/gegl/buffer/gegl-tile-backend-file.c b/gegl/buffer/gegl-tile-backend-file.c
index da29058..061897a 100644
--- a/gegl/buffer/gegl-tile-backend-file.c
+++ b/gegl/buffer/gegl-tile-backend-file.c
@@ -95,12 +95,16 @@ struct _GeglTileBackendFile
   /* GFile refering to our buffer */
   GFile           *file;
 
-  /* for writing */
-  GOutputStream   *o;
+  /* for reading/writing */
+  GIOStream       *io;
 
   /* for reading */
   GInputStream    *i;
 
+  /* for writing */
+  GOutputStream   *o;
+
+
   /* Before using mmap we'll use GIO's infrastructure for monitoring
    * the file for changes, this should also be more portable. This is
    * used for for cooperated sharing of a buffer file
@@ -687,10 +691,12 @@ gegl_tile_backend_file_finalize (GObject *object)
       GEGL_NOTE (GEGL_DEBUG_TILE_BACKEND, "finalizing buffer %s", self->path);
 
 #if HAVE_GIO
-      if (self->i)
-        g_object_unref (self->i);
-      if (self->o)
-        g_object_unref (self->o);
+      if (self->io)
+        {
+          g_io_stream_close (self->io, NULL, NULL);
+          g_object_unref (self->io);
+          self->io = NULL;
+        }
 
       if (self->file)
         g_file_delete  (self->file, NULL, NULL);
@@ -886,6 +892,7 @@ gegl_tile_backend_file_constructor (GType                  type,
 #endif
   self->index = g_hash_table_new (gegl_tile_backend_file_hashfunc, gegl_tile_backend_file_equalfunc);
 
+
   /* If the file already exists open it, assuming it is a GeglBuffer. */
 #if HAVE_GIO
   if (g_file_query_exists (self->file, NULL))
@@ -905,19 +912,19 @@ gegl_tile_backend_file_constructor (GType                  type,
                         G_CALLBACK (gegl_tile_backend_file_file_changed),
                         self);
 
-#ifndef HACKED_GIO_WITH_READWRITE
-      g_error ("not able to open a file readwrite properly with GIO");
-#else
-      /* this construct uses a hacked up version of GIO that detects the
-       * createflag to be passed as G_FILE_CREATE_READWRITE for the append
-       * call on local files, and provides a suitable inputstream as istream
-       * data on the object.
-       */
-      self->o = G_OUTPUT_STREAM (g_file_append_to (self->file,
-                                                   G_FILE_CREATE_READWRITE,
-                                                   NULL, NULL));
-      self->i = g_object_get_data (G_OBJECT (self->o), "istream");
-#endif
+      {
+        GError *error = NULL;
+        self->io = G_IO_STREAM (g_file_open_readwrite (self->file, NULL, &error));
+        if (error)
+          {
+            g_warning ("%s: %s", G_STRLOC, error->message);
+            g_error_free (error);
+            error = NULL;
+          }
+        self->o = g_io_stream_get_output_stream (self->io);
+        self->i = g_io_stream_get_input_stream (self->io);
+      }
+
 #else
       self->o = open (self->path, O_RDWR|O_CREAT, S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP|S_IROTH|S_IWOTH);
       self->i = dup (self->o);
@@ -967,30 +974,35 @@ gegl_tile_backend_file_ensure_exist (GeglTileBackendFile *self)
   if (!self->exist)
     {
       GeglTileBackend *backend;
+      GError *error = NULL;
 
       self->exist = TRUE;
+
+      if (self->io)
+        {
+          g_print ("we already existed\n");
+          return;
+        }
+
       backend = GEGL_TILE_BACKEND (self);
 
       GEGL_NOTE (GEGL_DEBUG_TILE_BACKEND, "creating swapfile  %s", self->path);
-#ifdef HACKED_GIO_WITH_READWRITE
-
-      self->o = G_OUTPUT_STREAM (g_file_append_to (self->file,
-                                                   G_FILE_CREATE_READWRITE,
-                                                   NULL, NULL));
-      gegl_buffer_header_init (&self->header,
-                               backend->tile_width,
-                               backend->tile_height,
-                               backend->px_size,
-                               backend->format
-                               );
-      gegl_tile_backend_file_write_header (self);
-      g_output_stream_flush (self->o, NULL, NULL);
-      self->i = g_object_get_data (G_OBJECT (self->o), "istream");
-#else
 
 #if HAVE_GIO
       self->o = G_OUTPUT_STREAM (g_file_replace (self->file, NULL, FALSE, G_FILE_CREATE_NONE, NULL, NULL));
       g_output_stream_flush (self->o, NULL, NULL);
+      g_output_stream_close (self->o, NULL, NULL);
+
+      self->io = G_IO_STREAM (g_file_open_readwrite (self->file, NULL, &error));
+      if (error)
+        {
+          g_warning ("%s: %s", G_STRLOC, error->message);
+          g_error_free (error);
+          error = NULL;
+        }
+      self->o = g_io_stream_get_output_stream (self->io);
+      self->i = g_io_stream_get_input_stream (self->io);
+
 #else
       self->o = open (self->path, O_RDWR|O_CREAT, S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP|S_IROTH|S_IWOTH);
 #endif
@@ -1015,11 +1027,11 @@ gegl_tile_backend_file_ensure_exist (GeglTileBackendFile *self)
       self->i = dup (self->o);
 #endif
 
-#endif
       /*self->i = G_INPUT_STREAM (g_file_read (self->file, NULL, NULL));*/
       self->next_pre_alloc = 256;  /* reserved space for header */
       self->total          = 256;  /* reserved space for header */
 #if HAVE_GIO
+      g_assert (self->io);
       g_assert (self->i);
       g_assert (self->o);
 #else
@@ -1061,6 +1073,7 @@ gegl_tile_backend_file_init (GeglTileBackendFile *self)
   self->path           = NULL;
 #if HAVE_GIO
   self->file           = NULL;
+  self->io             = NULL;
   self->i              = NULL;
   self->o              = NULL;
 #else
diff --git a/gegl/buffer/gegl-tile.c b/gegl/buffer/gegl-tile.c
index 3388ad2..2381c9a 100644
--- a/gegl/buffer/gegl-tile.c
+++ b/gegl/buffer/gegl-tile.c
@@ -198,7 +198,6 @@ gegl_tile_lock (GeglTile *tile)
   /*fprintf (stderr, "global tile locking: %i %i\n", locks, unlocks);*/
 
   gegl_tile_unclone (tile);
-  /*gegl_buffer_add_dirty (tile->buffer, tile->x, tile->y);*/
 }
 
 static void
@@ -295,9 +294,6 @@ gegl_tile_swp (GeglTile *a,
   gegl_tile_unclone (a);
   gegl_tile_unclone (b);
 
-/* gegl_buffer_add_dirty (a->buffer, a->x, a->y);
-   gegl_buffer_add_dirty (b->buffer, b->x, b->y);*/
-
   g_assert (a->size == b->size);
 
   tmp     = a->data;
diff --git a/gegl/gegl-config.c b/gegl/gegl-config.c
index 74a5365..21db5f4 100644
--- a/gegl/gegl-config.c
+++ b/gegl/gegl-config.c
@@ -220,8 +220,8 @@ gegl_config_init (GeglConfig *self)
   self->quality     = 1.0;
   self->cache_size  = 256 * 1024 * 1024;
   self->chunk_size  = 512 * 512;
-  self->tile_width  = 64;
-  self->tile_height = 128;
+  self->tile_width  = 128;
+  self->tile_height = 64;
 #if ENABLE_MT
   self->threads = 2;
 #endif
diff --git a/gegl/property-types/gegl-path.c b/gegl/property-types/gegl-path.c
index 88c8a9a..a187dc5 100644
--- a/gegl/property-types/gegl-path.c
+++ b/gegl/property-types/gegl-path.c
@@ -1355,7 +1355,7 @@ gegl_path_get_node (GeglPath     *vector,
 static void gegl_path_item_free (GeglPathList *p)
 {
   InstructionInfo *info = lookup_instruction_info(p->d.type);
-  g_slice_free1 (sizeof (gpointer) + sizeof (gchar) + sizeof (gfloat)*2 * (info->n_items+1)/2, p);
+  g_slice_free1 (sizeof (gpointer) + sizeof (gchar) + sizeof (gfloat)*2 * (info->n_items+3)/2, p);
 }
 
 void  gegl_path_remove_node  (GeglPath *vector,
@@ -1406,7 +1406,7 @@ void  gegl_path_insert_node     (GeglPath           *vector,
     {
       if (count == pos)
         {
-          GeglPathList *new = g_slice_alloc0 (sizeof (gpointer) + sizeof (gchar) + sizeof (gfloat)*2 *(info->n_items+1)/2);
+          GeglPathList *new = g_slice_alloc0 (sizeof (gpointer) + sizeof (gchar) + sizeof (gfloat)*2 *(info->n_items+3)/2);
           new->d.type=knot->type;
           copy_data (knot, &new->d);
           new->next = iter->next;
@@ -1423,7 +1423,7 @@ void  gegl_path_insert_node     (GeglPath           *vector,
     }
   if (pos==-1)
     {
-      GeglPathList *new = g_slice_alloc0 (sizeof (gpointer) + sizeof (gchar) + sizeof (gfloat)*2 *(info->n_items+1)/2);
+      GeglPathList *new = g_slice_alloc0 (sizeof (gpointer) + sizeof (gchar) + sizeof (gfloat)*2 *(info->n_items+3)/2);
       new->d.type = knot->type;
       copy_data (knot, &new->d);
       new->next = NULL;
@@ -2087,7 +2087,8 @@ void gegl_path_stroke (GeglBuffer *buffer,
    {
      return;
    }
-  gegl_buffer_lock (buffer);
+  if (gegl_buffer_is_shared (buffer))
+    while (!gegl_buffer_try_lock (buffer));
 
   /*gegl_buffer_clear (buffer, &extent);*/
 
@@ -2166,7 +2167,8 @@ void gegl_path_stroke (GeglBuffer *buffer,
       iter=iter->next;
     }
 
-  gegl_buffer_unlock (buffer);
+  if (gegl_buffer_is_shared (buffer))
+    gegl_buffer_unlock (buffer);
 }
 
 gint gegl_path_type_get_n_items (gchar type)
diff --git a/operations/common/buffer-source.c b/operations/common/buffer-source.c
index 5f19c5d..6b5b5fe 100644
--- a/operations/common/buffer-source.c
+++ b/operations/common/buffer-source.c
@@ -32,6 +32,14 @@ gegl_chant_object(buffer, _("Input buffer"),
 
 #include "gegl-chant.h"
 
+static void buffer_changed (GeglBuffer          *buffer,
+                            const GeglRectangle *rect,
+                            gpointer             userdata)
+{
+  gegl_operation_invalidate (GEGL_OPERATION (userdata), rect, FALSE);
+}
+
+
 static GeglRectangle
 get_bounding_box (GeglOperation *operation)
 {
@@ -56,6 +64,12 @@ process (GeglOperation       *operation,
 
   if (o->buffer)
     {
+      if (!o->chant_data)
+        {
+          o->chant_data = (void*)0xf00;
+          g_signal_connect (o->buffer, "changed",
+                            G_CALLBACK(buffer_changed), operation);
+        }
       g_object_ref (o->buffer); /* Add an extra reference, since
 				     * gegl_operation_set_data is
 				     * stealing one.



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