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.
parent f9afacc3
......@@ -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);
......
#!/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
......@@ -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 \
......
......@@ -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 *
......
......@@ -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);
}
}
}
......
......@@ -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
......
......@@ -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
......@@ -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
......
......@@ -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;
......
......@@ -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
......
......@@ -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)
......
......@@ -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.
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment