[gnome-builder] build-result: add IdeBuildResult::log signal



commit 96eafc44448a5b57e81aaf14da081c04436a6da7
Author: Christian Hergert <chergert redhat com>
Date:   Tue Dec 22 01:22:52 2015 -0800

    build-result: add IdeBuildResult::log signal
    
    This adds a signal that is emitted when a new log line is received from
    stderr or stdout. I'm not hugely fond of this design (since signals are
    pretty lock-heavy), but I rather like the API. It makes it very simple
    for a build result observer to track things. We'll always be in the main
    loop anyway, so contention should be low.
    
    We should be able to use this signal to move errorformat extraction out
    of IdeBuildResult too.

 libide/Makefile.am        |    1 +
 libide/ide-build-result.c |   74 +++++++++++++++++++++++++++++++++++---------
 libide/ide-build-result.h |   13 +++++++-
 libide/ide-enums.c.in     |    1 +
 4 files changed, 72 insertions(+), 17 deletions(-)
---
diff --git a/libide/Makefile.am b/libide/Makefile.am
index 86ba1cf..f2ab9ed 100644
--- a/libide/Makefile.am
+++ b/libide/Makefile.am
@@ -482,6 +482,7 @@ glib_enum_c = ide-enums.c
 glib_enum_headers =  \
        doap/ide-doap.h \
        ide-buffer.h \
+       ide-build-result.h \
        ide-diagnostic.h \
        ide-highlighter.h \
        ide-indent-style.h \
diff --git a/libide/ide-build-result.c b/libide/ide-build-result.c
index ca37b64..9e4b7ae 100644
--- a/libide/ide-build-result.c
+++ b/libide/ide-build-result.c
@@ -22,6 +22,7 @@
 #include <libpeas/peas.h>
 
 #include "ide-build-result.h"
+#include "ide-enums.h"
 #include "ide-file.h"
 #include "ide-source-location.h"
 
@@ -45,8 +46,9 @@ typedef struct
 
 typedef struct
 {
-  IdeBuildResult *self;
-  GOutputStream  *writer;
+  IdeBuildResult    *self;
+  GOutputStream     *writer;
+  IdeBuildResultLog  log;
 } Tail;
 
 G_DEFINE_TYPE_WITH_PRIVATE (IdeBuildResult, ide_build_result, IDE_TYPE_OBJECT)
@@ -60,6 +62,7 @@ enum {
 
 enum {
   DIAGNOSTIC,
+  LOG,
   LAST_SIGNAL
 };
 
@@ -255,9 +258,10 @@ _ide_build_result_open_log (IdeBuildResult  *self,
 }
 
 static void
-_ide_build_result_log (IdeBuildResult *self,
-                       GOutputStream  *stream,
-                       const gchar    *message)
+_ide_build_result_log (IdeBuildResult    *self,
+                       IdeBuildResultLog  log,
+                       GOutputStream     *stream,
+                       const gchar       *message)
 {
   g_autofree gchar *buffer = NULL;
 
@@ -272,11 +276,35 @@ _ide_build_result_log (IdeBuildResult *self,
    *       like date/time, but I didn't think it was necessary in the long
    *       run. Would be nice to remove the printf as well. We need to do the
    *       write as a single item in case we have multiple threads appending.
+   *
+   *       We could probably replace the \0 with \n and pass string lengths
+   *       around, but it would be nice for the callers to have a valid
+   *       copy of the string.
+   *
+   *       However, even worse, is that the signal emit may result in a
+   *       string copy anyway. We could get around this by using an
+   *       intermediate structure such as "IdeBuildResultEvent" or
+   *       similar.
    */
 
   buffer = g_strdup_printf ("%s\n", message);
-  g_output_stream_write_all (stream, buffer, strlen (buffer),
-                             NULL, NULL, NULL);
+  g_output_stream_write_all (stream, buffer, strlen (buffer), NULL, NULL, NULL);
+
+  /*
+   * XXX:
+   *
+   * This is rather non-ideal today. Signal emission requires a global lock
+   * to access the signal information. However, we'll be in the Gtk main loop
+   * at this point, and signals generally aren't used in other threads. So
+   * the lock should most likely be non-contended. Still feels a bit heavy
+   * though since @message will get strdup()'d in most cases.
+   *
+   * I'm also non-plus'd at our use of read_line_async() to get the next line.
+   * It results in re-entering the main loop for ever log message in the build
+   * result. We already have IdeLineReader, which could help us lower the cost
+   * while doing larger buffered reads.
+   */
+  g_signal_emit (self, signals [LOG], 0, log, buffer);
 }
 
 void
@@ -297,7 +325,7 @@ ide_build_result_log_stdout (IdeBuildResult *self,
       msg = g_strdup_vprintf (format, args);
       va_end (args);
 
-      _ide_build_result_log (self, priv->stdout_writer, msg);
+      _ide_build_result_log (self, IDE_BUILD_RESULT_LOG_STDOUT, priv->stdout_writer, msg);
     }
 }
 
@@ -319,7 +347,7 @@ ide_build_result_log_stderr (IdeBuildResult *self,
       msg = g_strdup_vprintf (format, args);
       va_end (args);
 
-      _ide_build_result_log (self, priv->stderr_writer, msg);
+      _ide_build_result_log (self, IDE_BUILD_RESULT_LOG_STDERR, priv->stderr_writer, msg);
     }
 }
 
@@ -402,7 +430,7 @@ ide_build_result_tail_cb (GObject      *object,
 
   if (line)
     {
-      _ide_build_result_log (tail->self, tail->writer, line);
+      _ide_build_result_log (tail->self, tail->log, tail->writer, line);
       g_data_input_stream_read_line_async (reader,
                                            G_PRIORITY_DEFAULT,
                                            NULL,
@@ -418,9 +446,10 @@ ide_build_result_tail_cb (GObject      *object,
 }
 
 static void
-ide_build_result_tail_into (IdeBuildResult *self,
-                            GInputStream   *reader,
-                            GOutputStream  *writer)
+ide_build_result_tail_into (IdeBuildResult    *self,
+                            IdeBuildResultLog  log,
+                            GInputStream      *reader,
+                            GOutputStream     *writer)
 {
   g_autoptr(GDataInputStream) data_reader = NULL;
   Tail *tail;
@@ -434,6 +463,7 @@ ide_build_result_tail_into (IdeBuildResult *self,
   tail = g_slice_alloc0 (sizeof *tail);
   tail->self = g_object_ref (self);
   tail->writer = g_object_ref (writer);
+  tail->log = log;
 
   g_data_input_stream_read_line_async (data_reader,
                                        G_PRIORITY_DEFAULT,
@@ -459,11 +489,17 @@ ide_build_result_log_subprocess (IdeBuildResult *self,
 
   stderr_stream = g_subprocess_get_stderr_pipe (subprocess);
   if (stderr_stream)
-    ide_build_result_tail_into (self, stderr_stream, priv->stderr_writer);
+    ide_build_result_tail_into (self,
+                                IDE_BUILD_RESULT_LOG_STDERR,
+                                stderr_stream,
+                                priv->stderr_writer);
 
   stdout_stream = g_subprocess_get_stdout_pipe (subprocess);
   if (stdout_stream)
-    ide_build_result_tail_into (self, stdout_stream, priv->stdout_writer);
+    ide_build_result_tail_into (self,
+                                IDE_BUILD_RESULT_LOG_STDOUT,
+                                stdout_stream,
+                                priv->stdout_writer);
 }
 
 static void
@@ -565,6 +601,14 @@ ide_build_result_class_init (IdeBuildResultClass *klass)
                   NULL, NULL, NULL,
                   G_TYPE_NONE, 1, IDE_TYPE_DIAGNOSTIC);
 
+  signals [LOG] =
+    g_signal_new ("log",
+                  G_TYPE_FROM_CLASS (klass),
+                  G_SIGNAL_RUN_LAST,
+                  G_STRUCT_OFFSET (IdeBuildResultClass, log),
+                  NULL, NULL, NULL,
+                  G_TYPE_NONE, 2, IDE_TYPE_BUILD_RESULT_LOG, G_TYPE_STRING);
+
   errorformats = g_ptr_array_new ();
 
   ide_build_result_add_error_format ("(?<filename>[a-zA-Z0-9\\-\\.]+):"
diff --git a/libide/ide-build-result.h b/libide/ide-build-result.h
index db3e4ce..dac13be 100644
--- a/libide/ide-build-result.h
+++ b/libide/ide-build-result.h
@@ -30,12 +30,21 @@ G_BEGIN_DECLS
 
 G_DECLARE_DERIVABLE_TYPE (IdeBuildResult, ide_build_result, IDE, BUILD_RESULT, IdeObject)
 
+typedef enum
+{
+  IDE_BUILD_RESULT_LOG_STDOUT,
+  IDE_BUILD_RESULT_LOG_STDERR,
+} IdeBuildResultLog;
+
 struct _IdeBuildResultClass
 {
   IdeObjectClass parent;
 
-  void (*diagnostic) (IdeBuildResult *self,
-                      IdeDiagnostic  *diagnostic);
+  void (*diagnostic) (IdeBuildResult    *self,
+                      IdeDiagnostic     *diagnostic);
+  void (*log)        (IdeBuildResult    *self,
+                      IdeBuildResultLog  log,
+                      const gchar       *message);
 };
 
 GInputStream  *ide_build_result_get_stdout_stream (IdeBuildResult *result);
diff --git a/libide/ide-enums.c.in b/libide/ide-enums.c.in
index ccdac74..4b782b4 100644
--- a/libide/ide-enums.c.in
+++ b/libide/ide-enums.c.in
@@ -6,6 +6,7 @@
 #include "ide-enums.h"
 
 #include "ide-buffer.h"
+#include "ide-build-result.h"
 #include "ide-diagnostic.h"
 #include "ide-doap.h"
 #include "ide-highlighter.h"


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