[gtksourceview/wip/loader-saver] FileLoader: temporary strong ref to the source_buffer



commit 69ba2da08f52882ad341712ce2b93d4e63ade510
Author: Sébastien Wilmet <swilmet gnome org>
Date:   Fri Mar 28 18:41:51 2014 +0100

    FileLoader: temporary strong ref to the source_buffer
    
    During the file loading.

 gtksourceview/gtksourcebufferoutputstream.c |   43 ++++++++++++++-------------
 gtksourceview/gtksourcefileloader.c         |   29 ++++++++++++++----
 2 files changed, 44 insertions(+), 28 deletions(-)
---
diff --git a/gtksourceview/gtksourcebufferoutputstream.c b/gtksourceview/gtksourcebufferoutputstream.c
index 628a3b4..880772b 100644
--- a/gtksourceview/gtksourcebufferoutputstream.c
+++ b/gtksourceview/gtksourcebufferoutputstream.c
@@ -55,8 +55,7 @@
 
 struct _GtkSourceBufferOutputStreamPrivate
 {
-       /* TODO rename */
-       GtkSourceBuffer *doc;
+       GtkSourceBuffer *source_buffer;
        GtkTextIter pos;
 
        gchar *buffer;
@@ -118,7 +117,8 @@ gtk_source_buffer_output_stream_set_property (GObject      *object,
        switch (prop_id)
        {
                case PROP_BUFFER:
-                       stream->priv->doc = GTK_SOURCE_BUFFER (g_value_get_object (value));
+                       g_assert (stream->priv->source_buffer == NULL);
+                       stream->priv->source_buffer = g_value_dup_object (value);
                        break;
 
                case PROP_ENSURE_TRAILING_NEWLINE:
@@ -142,7 +142,7 @@ gtk_source_buffer_output_stream_get_property (GObject    *object,
        switch (prop_id)
        {
                case PROP_BUFFER:
-                       g_value_set_object (value, stream->priv->doc);
+                       g_value_set_object (value, stream->priv->source_buffer);
                        break;
 
                case PROP_ENSURE_TRAILING_NEWLINE:
@@ -160,6 +160,7 @@ gtk_source_buffer_output_stream_dispose (GObject *object)
 {
        GtkSourceBufferOutputStream *stream = GTK_SOURCE_BUFFER_OUTPUT_STREAM (object);
 
+       g_clear_object (&stream->priv->source_buffer);
        g_clear_object (&stream->priv->charset_conv);
 
        G_OBJECT_CLASS (gtk_source_buffer_output_stream_parent_class)->dispose (object);
@@ -182,18 +183,18 @@ gtk_source_buffer_output_stream_constructed (GObject *object)
 {
        GtkSourceBufferOutputStream *stream = GTK_SOURCE_BUFFER_OUTPUT_STREAM (object);
 
-       if (stream->priv->doc == NULL)
+       if (stream->priv->source_buffer == NULL)
        {
                g_critical ("This should never happen, a problem happened constructing the Buffer Output 
Stream!");
                return;
        }
 
-       gtk_source_buffer_begin_not_undoable_action (stream->priv->doc);
+       gtk_source_buffer_begin_not_undoable_action (stream->priv->source_buffer);
 
-       gtk_text_buffer_set_text (GTK_TEXT_BUFFER (stream->priv->doc), "", 0);
-       gtk_text_buffer_set_modified (GTK_TEXT_BUFFER (stream->priv->doc), FALSE);
+       gtk_text_buffer_set_text (GTK_TEXT_BUFFER (stream->priv->source_buffer), "", 0);
+       gtk_text_buffer_set_modified (GTK_TEXT_BUFFER (stream->priv->source_buffer), FALSE);
 
-       gtk_source_buffer_end_not_undoable_action (GTK_SOURCE_BUFFER (stream->priv->doc));
+       gtk_source_buffer_end_not_undoable_action (stream->priv->source_buffer);
 
        G_OBJECT_CLASS (gtk_source_buffer_output_stream_parent_class)->constructed (object);
 }
@@ -496,7 +497,7 @@ gtk_source_buffer_output_stream_detect_newline_type (GtkSourceBufferOutputStream
 
        type = GTK_SOURCE_NEWLINE_TYPE_DEFAULT;
 
-       gtk_text_buffer_get_start_iter (GTK_TEXT_BUFFER (stream->priv->doc),
+       gtk_text_buffer_get_start_iter (GTK_TEXT_BUFFER (stream->priv->source_buffer),
                                        &iter);
 
        if (gtk_text_iter_ends_line (&iter) || gtk_text_iter_forward_to_line_end (&iter))
@@ -545,10 +546,10 @@ apply_error_tag (GtkSourceBufferOutputStream *stream)
                return;
        }
 
-       gtk_text_buffer_get_iter_at_offset (GTK_TEXT_BUFFER (stream->priv->doc),
+       gtk_text_buffer_get_iter_at_offset (GTK_TEXT_BUFFER (stream->priv->source_buffer),
                                            &start, stream->priv->error_offset);
 
-       _gtk_source_buffer_set_as_invalid_character (stream->priv->doc,
+       _gtk_source_buffer_set_as_invalid_character (stream->priv->source_buffer,
                                                     &start,
                                                     &stream->priv->pos);
 
@@ -572,7 +573,7 @@ insert_fallback (GtkSourceBufferOutputStream *stream,
        out[2] = hex[(v & 0x0f) >> 0];
        out[3] = '\0';
 
-       gtk_text_buffer_insert (GTK_TEXT_BUFFER (stream->priv->doc),
+       gtk_text_buffer_insert (GTK_TEXT_BUFFER (stream->priv->source_buffer),
                                &stream->priv->pos, (const gchar *)out, 3);
 
        ++stream->priv->n_fallback_errors;
@@ -587,7 +588,7 @@ validate_and_insert (GtkSourceBufferOutputStream *stream,
        GtkTextIter *iter;
        gsize len;
 
-       text_buffer = GTK_TEXT_BUFFER (stream->priv->doc);
+       text_buffer = GTK_TEXT_BUFFER (stream->priv->source_buffer);
        iter = &stream->priv->pos;
        len = count;
 
@@ -673,7 +674,7 @@ remove_ending_newline (GtkSourceBufferOutputStream *stream)
        GtkTextIter end;
        GtkTextIter start;
 
-       gtk_text_buffer_get_end_iter (GTK_TEXT_BUFFER (stream->priv->doc), &end);
+       gtk_text_buffer_get_end_iter (GTK_TEXT_BUFFER (stream->priv->source_buffer), &end);
        start = end;
 
        gtk_text_iter_set_line_offset (&start, 0);
@@ -687,7 +688,7 @@ remove_ending_newline (GtkSourceBufferOutputStream *stream)
                }
 
                /* Delete the empty line which is from 'start' to 'end' */
-               gtk_text_buffer_delete (GTK_TEXT_BUFFER (stream->priv->doc),
+               gtk_text_buffer_delete (GTK_TEXT_BUFFER (stream->priv->source_buffer),
                                        &start,
                                        &end);
        }
@@ -701,10 +702,10 @@ end_append_text_to_document (GtkSourceBufferOutputStream *stream)
                remove_ending_newline (stream);
        }
 
-       gtk_text_buffer_set_modified (GTK_TEXT_BUFFER (stream->priv->doc),
+       gtk_text_buffer_set_modified (GTK_TEXT_BUFFER (stream->priv->source_buffer),
                                      FALSE);
 
-       gtk_source_buffer_end_not_undoable_action (GTK_SOURCE_BUFFER (stream->priv->doc));
+       gtk_source_buffer_end_not_undoable_action (stream->priv->source_buffer);
 }
 
 static gboolean
@@ -876,9 +877,9 @@ gtk_source_buffer_output_stream_write (GOutputStream  *stream,
                }
 
                /* Init the undoable action */
-               gtk_source_buffer_begin_not_undoable_action (GTK_SOURCE_BUFFER (ostream->priv->doc));
+               gtk_source_buffer_begin_not_undoable_action (ostream->priv->source_buffer);
 
-               gtk_text_buffer_get_start_iter (GTK_TEXT_BUFFER (ostream->priv->doc),
+               gtk_text_buffer_get_start_iter (GTK_TEXT_BUFFER (ostream->priv->source_buffer),
                                                &ostream->priv->pos);
 
                ostream->priv->is_initialized = TRUE;
@@ -1046,7 +1047,7 @@ gtk_source_buffer_output_stream_flush (GOutputStream  *stream,
                apply_error_tag (ostream);
 
                /* See special case above, flush this */
-               gtk_text_buffer_insert (GTK_TEXT_BUFFER (ostream->priv->doc),
+               gtk_text_buffer_insert (GTK_TEXT_BUFFER (ostream->priv->source_buffer),
                                        &ostream->priv->pos,
                                        "\r",
                                        1);
diff --git a/gtksourceview/gtksourcefileloader.c b/gtksourceview/gtksourcefileloader.c
index b4ccf40..5767da1 100644
--- a/gtksourceview/gtksourcefileloader.c
+++ b/gtksourceview/gtksourcefileloader.c
@@ -53,7 +53,16 @@ enum
 
 struct _GtkSourceFileLoaderPrivate
 {
+       /* Weak reference to the source_buffer. A subclass of GtkSourceBuffer
+        * can have the ownership of the FileLoader. And a FileLoader can be
+        * used several times, so the object can be kept around until the
+        * subclass of GtkSourceBuffer is disposed.
+        * The GtkSourceBufferOutputStream has a strong reference to the
+        * source_buffer, so the buffer will not be finalized when the file is
+        * being loaded. So there can be a temporary reference cycle.
+         */
        GtkSourceBuffer *source_buffer;
+
        GFile *file;
 
        /* The value of the "input-stream" property. */
@@ -508,7 +517,7 @@ add_gzip_decompressor_stream (GtkSourceFileLoader *loader)
 }
 
 static void
-create_streams (GtkSourceFileLoader *loader)
+create_input_stream (GtkSourceFileLoader *loader)
 {
        loader->priv->auto_detected_compression_type = GTK_SOURCE_COMPRESSION_TYPE_NONE;
 
@@ -535,10 +544,6 @@ create_streams (GtkSourceFileLoader *loader)
 
        g_return_if_fail (loader->priv->input_stream != NULL);
 
-       loader->priv->output_stream = gtk_source_buffer_output_stream_new (loader->priv->source_buffer,
-                                                                          loader->priv->candidate_encodings,
-                                                                          
loader->priv->remove_trailing_newline);
-
        /* start reading */
        read_file_chunk (loader);
 }
@@ -572,7 +577,7 @@ query_info_cb (GFile               *file,
                return;
        }
 
-       create_streams (loader);
+       create_input_stream (loader);
 }
 
 static void
@@ -772,6 +777,8 @@ gtk_source_file_loader_load_async (GtkSourceFileLoader   *loader,
        g_return_if_fail (GTK_SOURCE_IS_FILE_LOADER (loader));
        g_return_if_fail (loader->priv->task == NULL);
 
+       reset (loader);
+
        loader->priv->task = g_task_new (loader, cancellable, callback, user_data);
        g_task_set_priority (loader->priv->task, io_priority);
 
@@ -782,12 +789,20 @@ gtk_source_file_loader_load_async (GtkSourceFileLoader   *loader,
               g_print ("Start loading\n");
        });
 
+       /* The BufferOutputStream has a strong reference to the source_buffer.
+         * We create the BufferOutputStream here so we are sure that the
+         * source_buffer will not be destroyed during the file loading.
+         */
+       loader->priv->output_stream = gtk_source_buffer_output_stream_new (loader->priv->source_buffer,
+                                                                          loader->priv->candidate_encodings,
+                                                                          
loader->priv->remove_trailing_newline);
+
        if (loader->priv->input_stream_property != NULL)
        {
                loader->priv->guess_content_type_from_content = TRUE;
                loader->priv->info = g_file_info_new ();
 
-               create_streams (loader);
+               create_input_stream (loader);
        }
        else
        {


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