mirror of
https://gitlab.gnome.org/GNOME/glib.git
synced 2025-07-24 10:57:53 +02:00
Bug 568394 – dropping the last reference to a stream filter closes the
2009-01-20 Ryan Lortie <desrt@desrt.ca> Bug 568394 – dropping the last reference to a stream filter closes the base stream * gfilterinputstream.h: * gfilterinputstream.c: add "close-base-stream" property and only close the base stream if it is true. issue async close callbacks from correct source object. * gfilteroutputstream.h: * gfilteroutputstream.c: add a "close-base-stream" property and only close the base stream if it is true. issue async close callbacks from correct source object. * gbufferedoutputstream: check g_filter_output_stream_get_close_base() before closing the base stream. fix invalid source tag comparison in close_async (was comparing to flush_async). * ../docs/reference/gio/gio-sections.txt: * gio.symbols: add g_filter_{in,out}put_stream_{g,s}et_close_base_stream * tests/filter-streams.c: new test cases * tests/Makefile.am: add new test * tests/.gitignore: add new test svn path=/trunk/; revision=7825
This commit is contained in:
@@ -23,6 +23,7 @@
|
||||
#include "config.h"
|
||||
#include "gfilterinputstream.h"
|
||||
#include "ginputstream.h"
|
||||
#include "gsimpleasyncresult.h"
|
||||
#include "glibintl.h"
|
||||
|
||||
#include "gioalias.h"
|
||||
@@ -36,7 +37,8 @@
|
||||
|
||||
enum {
|
||||
PROP_0,
|
||||
PROP_BASE_STREAM
|
||||
PROP_BASE_STREAM,
|
||||
PROP_CLOSE_BASE
|
||||
};
|
||||
|
||||
static void g_filter_input_stream_set_property (GObject *object,
|
||||
@@ -93,6 +95,13 @@ static gboolean g_filter_input_stream_close_finish (GInputStream *stream
|
||||
|
||||
G_DEFINE_TYPE (GFilterInputStream, g_filter_input_stream, G_TYPE_INPUT_STREAM)
|
||||
|
||||
#define GET_PRIVATE(inst) G_TYPE_INSTANCE_GET_PRIVATE (inst, \
|
||||
G_TYPE_FILTER_INPUT_STREAM, GFilterInputStreamPrivate)
|
||||
|
||||
typedef struct
|
||||
{
|
||||
gboolean close_base;
|
||||
} GFilterInputStreamPrivate;
|
||||
|
||||
static void
|
||||
g_filter_input_stream_class_init (GFilterInputStreamClass *klass)
|
||||
@@ -117,6 +126,8 @@ g_filter_input_stream_class_init (GFilterInputStreamClass *klass)
|
||||
istream_class->close_async = g_filter_input_stream_close_async;
|
||||
istream_class->close_finish = g_filter_input_stream_close_finish;
|
||||
|
||||
g_type_class_add_private (klass, sizeof (GFilterInputStreamPrivate));
|
||||
|
||||
g_object_class_install_property (object_class,
|
||||
PROP_BASE_STREAM,
|
||||
g_param_spec_object ("base-stream",
|
||||
@@ -126,6 +137,13 @@ g_filter_input_stream_class_init (GFilterInputStreamClass *klass)
|
||||
G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY |
|
||||
G_PARAM_STATIC_NAME|G_PARAM_STATIC_NICK|G_PARAM_STATIC_BLURB));
|
||||
|
||||
g_object_class_install_property (object_class,
|
||||
PROP_CLOSE_BASE,
|
||||
g_param_spec_boolean ("close-base-stream",
|
||||
P_("Close Base Stream"),
|
||||
P_("If the base stream be closed when the filter stream is"),
|
||||
TRUE, G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY |
|
||||
G_PARAM_STATIC_NAME|G_PARAM_STATIC_NICK|G_PARAM_STATIC_BLURB));
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -146,6 +164,11 @@ g_filter_input_stream_set_property (GObject *object,
|
||||
filter_stream->base_stream = G_INPUT_STREAM (obj);
|
||||
break;
|
||||
|
||||
case PROP_CLOSE_BASE:
|
||||
g_filter_input_stream_set_close_base_stream (filter_stream,
|
||||
g_value_get_boolean (value));
|
||||
break;
|
||||
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
||||
break;
|
||||
@@ -169,6 +192,10 @@ g_filter_input_stream_get_property (GObject *object,
|
||||
g_value_set_object (value, filter_stream->base_stream);
|
||||
break;
|
||||
|
||||
case PROP_CLOSE_BASE:
|
||||
g_value_set_boolean (value, GET_PRIVATE (filter_stream)->close_base);
|
||||
break;
|
||||
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
||||
break;
|
||||
@@ -210,6 +237,49 @@ g_filter_input_stream_get_base_stream (GFilterInputStream *stream)
|
||||
return stream->base_stream;
|
||||
}
|
||||
|
||||
/**
|
||||
* g_filter_input_stream_get_close_base_stream:
|
||||
* @stream: a #GFilterInputStream.
|
||||
*
|
||||
* Returns whether the base stream will be closed when @stream is
|
||||
* closed.
|
||||
*
|
||||
* Return value: %TRUE if the base stream will be closed.
|
||||
**/
|
||||
gboolean
|
||||
g_filter_input_stream_get_close_base_stream (GFilterInputStream *stream)
|
||||
{
|
||||
g_return_val_if_fail (G_IS_FILTER_INPUT_STREAM (stream), FALSE);
|
||||
|
||||
return GET_PRIVATE (stream)->close_base;
|
||||
}
|
||||
|
||||
/**
|
||||
* g_filter_input_stream_set_close_base_stream:
|
||||
* @stream: a #GFilterInputStream.
|
||||
* @close_base: %TRUE to close the base stream.
|
||||
*
|
||||
* Sets whether the base stream will be closed when @stream is closed.
|
||||
**/
|
||||
void
|
||||
g_filter_input_stream_set_close_base_stream (GFilterInputStream *stream,
|
||||
gboolean close_base)
|
||||
{
|
||||
GFilterInputStreamPrivate *priv;
|
||||
|
||||
g_return_if_fail (G_IS_FILTER_INPUT_STREAM (stream));
|
||||
|
||||
close_base = !!close_base;
|
||||
|
||||
priv = GET_PRIVATE (stream);
|
||||
|
||||
if (priv->close_base != close_base)
|
||||
{
|
||||
priv->close_base = close_base;
|
||||
g_object_notify (G_OBJECT (stream), "close-base-stream");
|
||||
}
|
||||
}
|
||||
|
||||
static gssize
|
||||
g_filter_input_stream_read (GInputStream *stream,
|
||||
void *buffer,
|
||||
@@ -258,16 +328,20 @@ g_filter_input_stream_close (GInputStream *stream,
|
||||
GCancellable *cancellable,
|
||||
GError **error)
|
||||
{
|
||||
GFilterInputStream *filter_stream;
|
||||
GInputStream *base_stream;
|
||||
gboolean res;
|
||||
gboolean res = TRUE;
|
||||
|
||||
filter_stream = G_FILTER_INPUT_STREAM (stream);
|
||||
base_stream = filter_stream->base_stream;
|
||||
if (GET_PRIVATE (stream)->close_base)
|
||||
{
|
||||
GFilterInputStream *filter_stream;
|
||||
GInputStream *base_stream;
|
||||
|
||||
res = g_input_stream_close (base_stream,
|
||||
cancellable,
|
||||
error);
|
||||
filter_stream = G_FILTER_INPUT_STREAM (stream);
|
||||
base_stream = filter_stream->base_stream;
|
||||
|
||||
res = g_input_stream_close (base_stream,
|
||||
cancellable,
|
||||
error);
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
@@ -357,6 +431,26 @@ g_filter_input_stream_skip_finish (GInputStream *stream,
|
||||
return nskipped;
|
||||
}
|
||||
|
||||
static void
|
||||
g_filter_input_stream_close_ready (GObject *object,
|
||||
GAsyncResult *result,
|
||||
gpointer user_data)
|
||||
{
|
||||
GSimpleAsyncResult *simple = user_data;
|
||||
GError *error = NULL;
|
||||
|
||||
g_input_stream_close_finish (G_INPUT_STREAM (object), result, &error);
|
||||
|
||||
if (error)
|
||||
{
|
||||
g_simple_async_result_set_from_error (simple, error);
|
||||
g_error_free (error);
|
||||
}
|
||||
|
||||
g_simple_async_result_complete (simple);
|
||||
g_object_unref (simple);
|
||||
}
|
||||
|
||||
static void
|
||||
g_filter_input_stream_close_async (GInputStream *stream,
|
||||
int io_priority,
|
||||
@@ -364,17 +458,26 @@ g_filter_input_stream_close_async (GInputStream *stream,
|
||||
GAsyncReadyCallback callback,
|
||||
gpointer user_data)
|
||||
{
|
||||
GFilterInputStream *filter_stream;
|
||||
GInputStream *base_stream;
|
||||
GSimpleAsyncResult *simple;
|
||||
|
||||
filter_stream = G_FILTER_INPUT_STREAM (stream);
|
||||
base_stream = filter_stream->base_stream;
|
||||
simple = g_simple_async_result_new (G_OBJECT (stream),
|
||||
callback, user_data,
|
||||
g_filter_input_stream_close_async);
|
||||
|
||||
g_input_stream_close_async (base_stream,
|
||||
io_priority,
|
||||
cancellable,
|
||||
callback,
|
||||
user_data);
|
||||
if (GET_PRIVATE (stream)->close_base)
|
||||
{
|
||||
GFilterInputStream *filter_stream = G_FILTER_INPUT_STREAM (stream);
|
||||
|
||||
g_input_stream_close_async (filter_stream->base_stream,
|
||||
io_priority, cancellable,
|
||||
g_filter_input_stream_close_ready,
|
||||
g_object_ref (simple));
|
||||
}
|
||||
else
|
||||
/* do nothing */
|
||||
g_simple_async_result_complete_in_idle (simple);
|
||||
|
||||
g_object_unref (simple);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
@@ -382,18 +485,14 @@ g_filter_input_stream_close_finish (GInputStream *stream,
|
||||
GAsyncResult *result,
|
||||
GError **error)
|
||||
{
|
||||
GFilterInputStream *filter_stream;
|
||||
GInputStream *base_stream;
|
||||
gboolean res;
|
||||
GSimpleAsyncResult *simple;
|
||||
|
||||
filter_stream = G_FILTER_INPUT_STREAM (stream);
|
||||
base_stream = filter_stream->base_stream;
|
||||
g_return_val_if_fail (g_simple_async_result_is_valid (
|
||||
result, G_OBJECT (stream), g_filter_input_stream_close_async), FALSE);
|
||||
|
||||
res = g_input_stream_close_finish (stream,
|
||||
result,
|
||||
error);
|
||||
simple = G_SIMPLE_ASYNC_RESULT (result);
|
||||
|
||||
return res;
|
||||
return !g_simple_async_result_propagate_error (simple, error);
|
||||
}
|
||||
|
||||
#define __G_FILTER_INPUT_STREAM_C__
|
||||
|
Reference in New Issue
Block a user