After an evaluation, GNOME has moved from Bugzilla to GitLab. Learn more about GitLab.
No new issues can be reported in GNOME Bugzilla anymore.
To report an issue in a GNOME project, go to GNOME GitLab.
Do not go to GNOME Gitlab for: Bluefish, Doxygen, GnuCash, GStreamer, java-gnome, LDTP, NetworkManager, Tomboy.
Bug 741630 - Add GSimpleIOStream class
Add GSimpleIOStream class
Status: RESOLVED FIXED
Product: glib
Classification: Platform
Component: gio
unspecified
Other All
: Normal normal
: ---
Assigned To: gtkdev
gtkdev
Depends on: 743990
Blocks:
 
 
Reported: 2014-12-17 08:31 UTC by Ignacio Casal Quinteiro (nacho)
Modified: 2015-02-17 21:33 UTC
See Also:
GNOME target: ---
GNOME version: ---


Attachments
Add GSimpleStream class (16.40 KB, patch)
2014-12-17 08:31 UTC, Ignacio Casal Quinteiro (nacho)
none Details | Review
Add GSimpleIOStream class (16.27 KB, patch)
2014-12-17 09:49 UTC, Ignacio Casal Quinteiro (nacho)
reviewed Details | Review
Add GSimpleIOStream class (16.71 KB, patch)
2014-12-17 10:21 UTC, Ignacio Casal Quinteiro (nacho)
none Details | Review
Add GSimpleIOStream class (16.73 KB, patch)
2014-12-17 10:22 UTC, Ignacio Casal Quinteiro (nacho)
none Details | Review
Add GSimpleIOStream class (16.75 KB, patch)
2014-12-17 10:23 UTC, Ignacio Casal Quinteiro (nacho)
needs-work Details | Review
Add GSimpleIOStream class (18.66 KB, patch)
2014-12-18 16:20 UTC, Ignacio Casal Quinteiro (nacho)
none Details | Review
Add GSimpleIOStream class (18.70 KB, patch)
2014-12-18 17:22 UTC, Ignacio Casal Quinteiro (nacho)
none Details | Review
Add GSimpleIOStream class (19.05 KB, patch)
2015-01-19 10:55 UTC, Ignacio Casal Quinteiro (nacho)
reviewed Details | Review
Add GSimpleIOStream class (18.89 KB, patch)
2015-01-20 08:39 UTC, Ignacio Casal Quinteiro (nacho)
none Details | Review
streams: add private 'async close via threads' API (3.11 KB, patch)
2015-01-20 13:41 UTC, Allison Karlitskaya (desrt)
reviewed Details | Review
GIOStream: support for unemulated async close() (3.71 KB, patch)
2015-01-20 13:41 UTC, Allison Karlitskaya (desrt)
reviewed Details | Review
Add GSimpleIOStream class (15.54 KB, patch)
2015-01-20 13:41 UTC, Allison Karlitskaya (desrt)
reviewed Details | Review
tests: add GSimpleIOStream async close tests (2.35 KB, patch)
2015-01-20 13:42 UTC, Allison Karlitskaya (desrt)
reviewed Details | Review
streams: de-gtkdocify internal API (1.67 KB, patch)
2015-01-20 18:01 UTC, Allison Karlitskaya (desrt)
committed Details | Review
streams: add private 'async close via threads' API (3.13 KB, patch)
2015-01-20 18:01 UTC, Allison Karlitskaya (desrt)
committed Details | Review
GIOStream: support for unemulated async close() (3.76 KB, patch)
2015-01-20 18:01 UTC, Allison Karlitskaya (desrt)
committed Details | Review
Add GSimpleIOStream class (15.54 KB, patch)
2015-01-20 18:01 UTC, Allison Karlitskaya (desrt)
committed Details | Review
tests: add GSimpleIOStream async close tests (2.35 KB, patch)
2015-01-20 18:01 UTC, Allison Karlitskaya (desrt)
committed Details | Review
gdbus: delay closing stream after read finish (2.62 KB, patch)
2015-02-12 21:41 UTC, Marc-Andre Lureau
none Details | Review
tests: fix unref of optionnal cancellable (1.01 KB, patch)
2015-02-12 21:41 UTC, Marc-Andre Lureau
none Details | Review

Description Ignacio Casal Quinteiro (nacho) 2014-12-17 08:31:26 UTC
Add an io stream that allows to set the input and output stream.
The problem from this implementation is that the GIOStream already
sets the input and output stream properties and we cannot override them.
Is there a way to override them and making them read/write ?
Should I use a different property name?
Comment 1 Ignacio Casal Quinteiro (nacho) 2014-12-17 08:31:33 UTC
Created attachment 292873 [details] [review]
Add GSimpleStream class

GSimpleIOStream represents an object that wraps an input and an output
stream making easy to use them by calling the #GIOStream methods.
Comment 2 Ignacio Casal Quinteiro (nacho) 2014-12-17 09:49:11 UTC
Created attachment 292876 [details] [review]
Add GSimpleIOStream class

GSimpleIOStream represents an object that wraps an input and an output
stream making easy to use them by calling the #GIOStream methods.
Comment 3 Ignacio Casal Quinteiro (nacho) 2014-12-17 10:00:48 UTC
so now it seems to be fine, though should we make it construct_only or just construct and let the user the ability to change the streams?
Comment 4 Emmanuele Bassi (:ebassi) 2014-12-17 10:09:03 UTC
Review of attachment 292876 [details] [review]:

::: gio/giotypes.h
@@ +135,3 @@
 typedef struct _GIOStream                     GIOStream;
+/**
+ * GSimpleIOStream:

should move this doc annotation inside gsimpleiostream.h.

::: gio/gsimpleiostream.c
@@ +19,3 @@
+
+
+/* Prologue {{{1 */

copy and paste issue? there's no terminator for the code folding.

@@ +216,3 @@
+  io_class->close_finish = g_simple_io_stream_close_finish;
+
+  g_object_class_install_property (gobject_class, PROP_INPUT_STREAM,

missing documentation.

@@ +225,3 @@
+                                                        G_PARAM_CONSTRUCT_ONLY));
+
+  g_object_class_install_property (gobject_class, PROP_OUTPUT_STREAM,

missing documentation.

@@ +241,3 @@
+}
+
+GIOStream *

missing documentation.

::: gio/gsimpleiostream.h
@@ +46,3 @@
+  GIOStream parent;
+
+  GSimpleIOStreamPrivate *priv;

please, don't use a priv pointer in the instance structure. we have the get_instance_private() function for that.
Comment 5 Ignacio Casal Quinteiro (nacho) 2014-12-17 10:21:01 UTC
Created attachment 292877 [details] [review]
Add GSimpleIOStream class

GSimpleIOStream represents an object that wraps an input and an output
stream making easy to use them by calling the #GIOStream methods.
Comment 6 Ignacio Casal Quinteiro (nacho) 2014-12-17 10:22:58 UTC
Created attachment 292878 [details] [review]
Add GSimpleIOStream class

GSimpleIOStream represents an object that wraps an input and an output
stream making easy to use them by calling the #GIOStream methods.
Comment 7 Ignacio Casal Quinteiro (nacho) 2014-12-17 10:23:43 UTC
Created attachment 292879 [details] [review]
Add GSimpleIOStream class

GSimpleIOStream represents an object that wraps an input and an output
stream making easy to use them by calling the #GIOStream methods.
Comment 8 Matthias Clasen 2014-12-17 11:45:10 UTC
Not really reviewing here, just a comment from the sidelines:  "Enough streams in GIO already!"
Comment 9 Allison Karlitskaya (desrt) 2014-12-17 16:57:37 UTC
Review of attachment 292879 [details] [review]:

Missing docs section addition.

::: gio/gsimpleiostream.c
@@ +51,3 @@
+};
+
+G_DEFINE_TYPE_WITH_PRIVATE (GSimpleIOStream, g_simple_io_stream, G_TYPE_IO_STREAM)

Sorry to hit you with this after ebassi already told you different: I'd prefer if you just moved the struct definition inside of the .c file (along with the class typedef) and avoided priv use entirely.  That would effectively make the class unsubclassable, as is often the case for our "Simple" classes.  See GSimpleAction, GSimpleAsyncResult, etc. for how that is done.

@@ +158,3 @@
+  /* If this errored out, unset error so that we don't report
+     further errors, but still do the following ops */
+  if (error != NULL && *error != NULL)

This is a bit tricky, but I think you can do better.

If the other close is successful you probably still want to report the first error.  For that reason I guess the better approach here would actually be to set 'error = NULL' here in order to keep the error in place and prevent the input_stream_close() from modifying it.  That would definitely require a comment explaining what is happening though because it's non-standard usage and somewhat confusing.

@@ +183,3 @@
+  /* socket close is not blocked, just do it! */
+  error = NULL;
+  if (!class->close_fn (stream, cancellable, &error))

I'm pretty sure I don't like whatever it is you're trying to do here.
Comment 10 Allison Karlitskaya (desrt) 2014-12-17 17:01:49 UTC
Might be nice as well to add two small functions:

#ifdef G_IS_WIN32
g_io_stream_new_for_handle()
#else
g_io_stream_new_for_unix_fd()
#endif

which do the 'obvious' thing.
Comment 11 Ignacio Casal Quinteiro (nacho) 2014-12-18 16:20:39 UTC
Created attachment 292990 [details] [review]
Add GSimpleIOStream class

GSimpleIOStream represents an object that wraps an input and an output
stream making easy to use them by calling the #GIOStream methods.
Comment 12 A. Walton 2014-12-18 17:15:28 UTC
Review of attachment 292990 [details] [review]:

::: gio/gsimpleiostream.c
@@ +33,3 @@
+ *
+ * GSimpleIOStream represents an object that wraps an input and an output
+ * stream making easy to use them by calling the #GIOStream methods.

The English here could use some simplification and clarification. As simply put as I can think:

GSimpleIOStream creates a #GIOStream from an arbitrary #GInputStream and #GOutputStream. This allows any pair of input and output streams to be used with #GIOStream methods.

And then it'd be nice to go on and show/discuss the cases of why this might be interesting, which would be good to see here. Presumably this is to make it easier to assemble some kind of shell-like stream pipeline?

@@ +259,3 @@
+  GIOStreamClass *io_class = G_IO_STREAM_CLASS (klass);
+
+  gobject_class->finalize = g_simple_io_stream_dispose;

Sort of surprised nobody has pointed out yet that you're passing the dispose func as your finalizer here.
Comment 13 Ignacio Casal Quinteiro (nacho) 2014-12-18 17:22:54 UTC
Created attachment 292992 [details] [review]
Add GSimpleIOStream class

GSimpleIOStream represents an object that wraps an input and an output
stream making easy to use them by calling the #GIOStream methods.
Comment 14 Ignacio Casal Quinteiro (nacho) 2014-12-18 17:23:30 UTC
Thanks for the review. Nice catch with the finalize typo.
This patch is still missing some better explanation as you pointed out though.
Comment 15 Ignacio Casal Quinteiro (nacho) 2015-01-19 10:55:39 UTC
Created attachment 294852 [details] [review]
Add GSimpleIOStream class

GSimpleIOStream represents an object that wraps an input and an output
stream making easy to use them by calling the #GIOStream methods.
Comment 16 Allison Karlitskaya (desrt) 2015-01-19 21:44:13 UTC
Review of attachment 294852 [details] [review]:

Something to consider: moving the close implementations into the interface as reasonable defaults.

::: gio/gsimpleiostream.c
@@ +181,3 @@
+
+  /* propagate only the first error if already set */
+  if (error != NULL && *error == NULL)

This check is a bit confusing, but it seems correct.

I'd probably have just done the check the other way and set error itself to NULL, skipping the need for the other variable.

@@ +247,3 @@
+  g_task_set_task_data (task, data, free_async_data);
+
+  g_output_stream_close_async (simple_stream->output_stream,

Is there a reason that you close the input before the output?  Why not both at once?  You already have an async data structure so you could just put a counter in it, set to 2, and use the same ready func -- whichever one gets to 0 is the one that dispatches the result.
Comment 17 Ignacio Casal Quinteiro (nacho) 2015-01-20 08:39:01 UTC
Created attachment 294958 [details] [review]
Add GSimpleIOStream class

GSimpleIOStream represents an object that wraps an input and an output
stream making easy to use them by calling the #GIOStream methods.
Comment 18 Allison Karlitskaya (desrt) 2015-01-20 13:41:44 UTC
Created attachment 294977 [details] [review]
streams: add private 'async close via threads' API

Add an internal helper to find out if close_async() is implemented via
threads using the default implementation in the base class.

We will use this to decide if we should do a 'pure async' close of a
GIOStream or not.
Comment 19 Allison Karlitskaya (desrt) 2015-01-20 13:41:51 UTC
Created attachment 294978 [details] [review]
GIOStream: support for unemulated async close()

Add an implementation of non-thread-emulated async close of a GIOStream
if either of the underlying stream objects support it.

This prevents us from calling close() functions from another thread on
an object that may not be expecting that.  It also allows us to skip the
thread entirely in case our objects support a pure async close.
Comment 20 Allison Karlitskaya (desrt) 2015-01-20 13:41:58 UTC
Created attachment 294979 [details] [review]
Add GSimpleIOStream class

GSimpleIOStream represents an object that wraps an input and an output
stream making easy to use them by calling the #GIOStream methods.
Comment 21 Allison Karlitskaya (desrt) 2015-01-20 13:42:03 UTC
Created attachment 294980 [details] [review]
tests: add GSimpleIOStream async close tests

Just a couple of tests to make sure the two paths are working properly,
without crashes or leaks.
Comment 22 Ignacio Casal Quinteiro (nacho) 2015-01-20 13:44:51 UTC
Review of attachment 294977 [details] [review]:

Looks good.
Comment 23 Emmanuele Bassi (:ebassi) 2015-01-20 13:48:06 UTC
Review of attachment 294977 [details] [review]:

::: gio/ginputstream.c
@@ +1254,3 @@
 }
 
+/**

this will make gtk-doc pick the annotation up, but the function is private, so you'll get a warning.

::: gio/goutputstream.c
@@ +1706,3 @@
 }
 
+/**

same as with g_input_stream_async_close_is_via_threads(): gtk-doc will pick the annotation up.
Comment 24 Ignacio Casal Quinteiro (nacho) 2015-01-20 13:49:26 UTC
Review of attachment 294978 [details] [review]:

Looks good, just wondering whether we should use g_slice_new for consistency?
Comment 25 Ignacio Casal Quinteiro (nacho) 2015-01-20 13:50:43 UTC
Review of attachment 294979 [details] [review]:

Looks good.
Comment 26 Emmanuele Bassi (:ebassi) 2015-01-20 13:51:46 UTC
Review of attachment 294978 [details] [review]:

::: gio/giostream.c
@@ +547,3 @@
+{
+  GError *error;
+  gint todo;

maybe "pending_close" instead of "todo"? :-)

@@ +624,3 @@
+       * threadsafe.
+       */
+      data = g_new (CloseAsyncData, 1);

how are we doing with the GSlice investigation? is it worth using g_slice_new instead of g_new? it makes the free function explicit, though…
Comment 27 Ignacio Casal Quinteiro (nacho) 2015-01-20 13:53:04 UTC
Review of attachment 294980 [details] [review]:

See the comment

::: gio/tests/io-stream.c
@@ +112,3 @@
+test_close_file (void)
+{
+#ifdef G_OS_UNIX

any reason to test it only for unix?
Comment 28 Allison Karlitskaya (desrt) 2015-01-20 17:51:50 UTC
(In reply to comment #26)
> maybe "pending_close" instead of "todo"? :-)

sure

> how are we doing with the GSlice investigation? is it worth using g_slice_new
> instead of g_new? it makes the free function explicit, though…

I just did it out of laziness for the DestroyNotify.  I could just as easily free the task data when I unref the task, though, so I'll do that instead.
Comment 29 Allison Karlitskaya (desrt) 2015-01-20 17:54:16 UTC
(In reply to comment #23)
> this will make gtk-doc pick the annotation up, but the function is private, so
> you'll get a warning.

I copied the comment block from the existing 'read is via threads' helper -- turns out that this functions is indeed showing up in -unused :)
Comment 30 Allison Karlitskaya (desrt) 2015-01-20 17:57:07 UTC
(In reply to comment #27)
> any reason to test it only for unix?

it opens /dev/null
Comment 31 Allison Karlitskaya (desrt) 2015-01-20 18:01:32 UTC
Created attachment 295033 [details] [review]
streams: de-gtkdocify internal API

Remove the /** **/-style block from two internal helpers to prevent
gtk-doc from picking them up.

Also add the gioprivate.h header to the IGNORE_HFILES to keep the
functions out of gio-unused.txt.
Comment 32 Allison Karlitskaya (desrt) 2015-01-20 18:01:37 UTC
Created attachment 295034 [details] [review]
streams: add private 'async close via threads' API

Add an internal helper to find out if close_async() is implemented via
threads using the default implementation in the base class.

We will use this to decide if we should do a 'pure async' close of a
GIOStream or not.
Comment 33 Allison Karlitskaya (desrt) 2015-01-20 18:01:41 UTC
Created attachment 295035 [details] [review]
GIOStream: support for unemulated async close()

Add an implementation of non-thread-emulated async close of a GIOStream
if either of the underlying stream objects support it.

This prevents us from calling close() functions from another thread on
an object that may not be expecting that.  It also allows us to skip the
thread entirely in case our objects support a pure async close.
Comment 34 Allison Karlitskaya (desrt) 2015-01-20 18:01:45 UTC
Created attachment 295036 [details] [review]
Add GSimpleIOStream class

GSimpleIOStream represents an object that wraps an input and an output
stream making easy to use them by calling the #GIOStream methods.
Comment 35 Allison Karlitskaya (desrt) 2015-01-20 18:01:49 UTC
Created attachment 295037 [details] [review]
tests: add GSimpleIOStream async close tests

Just a couple of tests to make sure the two paths are working properly,
without crashes or leaks.
Comment 36 Paolo Borelli 2015-02-03 15:09:21 UTC
Review of attachment 295036 [details] [review]:

The patch looks good to me and it is pretty much the code we are running in production.

Just a couple of nitpicks/questions below

::: gio/gsimpleiostream.c
@@ +215,3 @@
+g_simple_io_stream_new (GInputStream  *input_stream,
+                        GOutputStream *output_stream)
+{

should we add g_return_if_fail checks?

::: gio/gsimpleiostream.h
@@ +32,3 @@
+#define G_TYPE_SIMPLE_IO_STREAM                  (g_simple_io_stream_get_type ())
+#define G_SIMPLE_IO_STREAM(obj)                  (G_TYPE_CHECK_INSTANCE_CAST ((obj), G_TYPE_SIMPLE_IO_STREAM, GSimpleIOStream))
+#define G_IS_SIMPLE_IO_STREAM(obj)               (G_TYPE_CHECK_INSTANCE_TYPE ((obj), G_TYPE_SIMPLE_IO_STREAM))

Should we use the new G_DECLARE_FINAL_TYPE macro?
Comment 37 Paolo Borelli 2015-02-03 15:14:09 UTC
Also the rest of the patchset (preliminary patches and the tests) look ok to me (we run the tests and they pass here too)
Comment 38 Marc-Andre Lureau 2015-02-12 21:26:20 UTC
Review of attachment 295035 [details] [review]:

this patch "breaks" gdbus-close-pending test:

/gdbus/close-pending: 
(/home/elmarco/src/gnome/glib/gio/tests/.libs/lt-gdbus-close-pending:6063): GLib-GObject-CRITICAL **: g_object_unref: assertion 'G_IS_OBJECT (object)' failed

(gdb) bt
...
  • #4 g_object_unref
    at gobject.c line 3067
  • #5 delayed_close_free
    at gdbus-close-pending.c line 177
  • #0 g_output_stream_close_async
    at goutputstream.c line 1478
  • #1 g_io_stream_real_close_async
    at giostream.c line 633
  • #2 g_io_stream_close_async
    at giostream.c line 490
  • #3 continue_writing
    at gdbusprivate.c line 1451
  • #4 write_message_cb
    at gdbusprivate.c line 1352
  • #0 my_slow_close_output_stream_close_async
    at gdbus-close-pending.c line 199
  • #1 async_ready_close_flushed_callback_wrapper
    at goutputstream.c line 1423
  • #2 g_task_return_now
    at gtask.c line 1077
  • #3 complete_in_idle_cb
    at gtask.c line 1086
  • #4 g_idle_dispatch
    at gmain.c line 5392
  • #0 g_set_error_literal
    at gerror.c line 591
  • #1 g_input_stream_set_pending
    at ginputstream.c line 1208
  • #2 g_input_stream_close_async
    at ginputstream.c line 1105
  • #3 g_io_stream_real_close_async
    at giostream.c line 632
  • #4 g_io_stream_close_async
    at giostream.c line 490
  • #5 continue_writing
    at gdbusprivate.c line 1451
  • #6 continue_writing_in_idle_cb
    at gdbusprivate.c line 1553

It turns out continue_writing() doesn't pay enough attention to reading side, 

I am sending two fixes that should be applied before this patch.
Comment 39 Marc-Andre Lureau 2015-02-12 21:41:01 UTC
Created attachment 296716 [details] [review]
gdbus: delay closing stream after read finish

Closing the stream on the writing side my race with a pending read. This
patch ensures that closing is delayed after reading is finished.
Comment 40 Marc-Andre Lureau 2015-02-12 21:41:08 UTC
Created attachment 296717 [details] [review]
tests: fix unref of optionnal cancellable

An output_stream_close_async() may take NULL cancellable.

And my_slow_close_output_stream_close_async() does:

  df->cancellable = (cancellable != NULL ? g_object_ref (cancellable) : NULL);

So, don't expect df->cancellable to be non-null.
Comment 41 Marc-Andre Lureau 2015-02-12 21:46:59 UTC
Fwiw, the last patches look good to me,
+1 this would be quite useful.
Comment 42 Allison Karlitskaya (desrt) 2015-02-17 21:33:15 UTC
Attachment 295033 [details] pushed as f56f1ef - streams: de-gtkdocify internal API
Attachment 295034 [details] pushed as cb40c55 - streams: add private 'async close via threads' API
Attachment 295035 [details] pushed as c2c0a6a - GIOStream: support for unemulated async close()
Attachment 295036 [details] pushed as d4e3b82 - Add GSimpleIOStream class
Attachment 295037 [details] pushed as 07ae2e1 - tests: add GSimpleIOStream async close tests

Also applied the two GDBus fixes as part of bug 743990.