mirror of
https://gitlab.gnome.org/GNOME/glib.git
synced 2025-02-09 04:15:49 +01: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:
parent
4a22510022
commit
a9c978a354
@ -518,6 +518,8 @@ GFileInputStreamPrivate
|
|||||||
<TITLE>GFilterInputStream</TITLE>
|
<TITLE>GFilterInputStream</TITLE>
|
||||||
GFilterInputStream
|
GFilterInputStream
|
||||||
g_filter_input_stream_get_base_stream
|
g_filter_input_stream_get_base_stream
|
||||||
|
g_filter_input_stream_get_close_base_stream
|
||||||
|
g_filter_input_stream_set_close_base_stream
|
||||||
<SUBSECTION Standard>
|
<SUBSECTION Standard>
|
||||||
GFilterInputStreamClass
|
GFilterInputStreamClass
|
||||||
G_FILTER_INPUT_STREAM
|
G_FILTER_INPUT_STREAM
|
||||||
@ -694,6 +696,8 @@ GFileOutputStreamPrivate
|
|||||||
<TITLE>GFilterOutputStream</TITLE>
|
<TITLE>GFilterOutputStream</TITLE>
|
||||||
GFilterOutputStream
|
GFilterOutputStream
|
||||||
g_filter_output_stream_get_base_stream
|
g_filter_output_stream_get_base_stream
|
||||||
|
g_filter_output_stream_get_close_base_stream
|
||||||
|
g_filter_output_stream_set_close_base_stream
|
||||||
<SUBSECTION Standard>
|
<SUBSECTION Standard>
|
||||||
GFilterOutputStreamClass
|
GFilterOutputStreamClass
|
||||||
G_FILTER_OUTPUT_STREAM
|
G_FILTER_OUTPUT_STREAM
|
||||||
|
@ -1,3 +1,26 @@
|
|||||||
|
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
|
||||||
|
|
||||||
2009-01-19 Matthias Clasen <mclasen@redhat.com>
|
2009-01-19 Matthias Clasen <mclasen@redhat.com>
|
||||||
|
|
||||||
* gdesktopappinfo.c (g_desktop_app_info_new): Expand the docs.
|
* gdesktopappinfo.c (g_desktop_app_info_new): Expand the docs.
|
||||||
|
@ -508,11 +508,14 @@ g_buffered_output_stream_close (GOutputStream *stream,
|
|||||||
|
|
||||||
res = flush_buffer (bstream, cancellable, error);
|
res = flush_buffer (bstream, cancellable, error);
|
||||||
|
|
||||||
|
if (g_filter_output_stream_get_close_base_stream (G_FILTER_OUTPUT_STREAM (stream)))
|
||||||
|
{
|
||||||
/* report the first error but still close the stream */
|
/* report the first error but still close the stream */
|
||||||
if (res)
|
if (res)
|
||||||
res = g_output_stream_close (base_stream, cancellable, error);
|
res = g_output_stream_close (base_stream, cancellable, error);
|
||||||
else
|
else
|
||||||
g_output_stream_close (base_stream, cancellable, NULL);
|
g_output_stream_close (base_stream, cancellable, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
@ -569,11 +572,14 @@ flush_buffer_thread (GSimpleAsyncResult *result,
|
|||||||
/* if flushing the buffer or the stream returned
|
/* if flushing the buffer or the stream returned
|
||||||
* an error report that first error but still try
|
* an error report that first error but still try
|
||||||
* close the stream */
|
* close the stream */
|
||||||
|
if (g_filter_output_stream_get_close_base_stream (G_FILTER_OUTPUT_STREAM (stream)))
|
||||||
|
{
|
||||||
if (res == FALSE)
|
if (res == FALSE)
|
||||||
g_output_stream_close (base_stream, cancellable, NULL);
|
g_output_stream_close (base_stream, cancellable, NULL);
|
||||||
else
|
else
|
||||||
res = g_output_stream_close (base_stream, cancellable, &error);
|
res = g_output_stream_close (base_stream, cancellable, &error);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (res == FALSE)
|
if (res == FALSE)
|
||||||
{
|
{
|
||||||
@ -758,7 +764,7 @@ g_buffered_output_stream_close_finish (GOutputStream *stream,
|
|||||||
simple = G_SIMPLE_ASYNC_RESULT (result);
|
simple = G_SIMPLE_ASYNC_RESULT (result);
|
||||||
|
|
||||||
g_warn_if_fail (g_simple_async_result_get_source_tag (simple) ==
|
g_warn_if_fail (g_simple_async_result_get_source_tag (simple) ==
|
||||||
g_buffered_output_stream_flush_async);
|
g_buffered_output_stream_close_async);
|
||||||
|
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
@ -23,6 +23,7 @@
|
|||||||
#include "config.h"
|
#include "config.h"
|
||||||
#include "gfilterinputstream.h"
|
#include "gfilterinputstream.h"
|
||||||
#include "ginputstream.h"
|
#include "ginputstream.h"
|
||||||
|
#include "gsimpleasyncresult.h"
|
||||||
#include "glibintl.h"
|
#include "glibintl.h"
|
||||||
|
|
||||||
#include "gioalias.h"
|
#include "gioalias.h"
|
||||||
@ -36,7 +37,8 @@
|
|||||||
|
|
||||||
enum {
|
enum {
|
||||||
PROP_0,
|
PROP_0,
|
||||||
PROP_BASE_STREAM
|
PROP_BASE_STREAM,
|
||||||
|
PROP_CLOSE_BASE
|
||||||
};
|
};
|
||||||
|
|
||||||
static void g_filter_input_stream_set_property (GObject *object,
|
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)
|
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
|
static void
|
||||||
g_filter_input_stream_class_init (GFilterInputStreamClass *klass)
|
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_async = g_filter_input_stream_close_async;
|
||||||
istream_class->close_finish = g_filter_input_stream_close_finish;
|
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,
|
g_object_class_install_property (object_class,
|
||||||
PROP_BASE_STREAM,
|
PROP_BASE_STREAM,
|
||||||
g_param_spec_object ("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_READWRITE | G_PARAM_CONSTRUCT_ONLY |
|
||||||
G_PARAM_STATIC_NAME|G_PARAM_STATIC_NICK|G_PARAM_STATIC_BLURB));
|
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
|
static void
|
||||||
@ -146,6 +164,11 @@ g_filter_input_stream_set_property (GObject *object,
|
|||||||
filter_stream->base_stream = G_INPUT_STREAM (obj);
|
filter_stream->base_stream = G_INPUT_STREAM (obj);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case PROP_CLOSE_BASE:
|
||||||
|
g_filter_input_stream_set_close_base_stream (filter_stream,
|
||||||
|
g_value_get_boolean (value));
|
||||||
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
||||||
break;
|
break;
|
||||||
@ -169,6 +192,10 @@ g_filter_input_stream_get_property (GObject *object,
|
|||||||
g_value_set_object (value, filter_stream->base_stream);
|
g_value_set_object (value, filter_stream->base_stream);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case PROP_CLOSE_BASE:
|
||||||
|
g_value_set_boolean (value, GET_PRIVATE (filter_stream)->close_base);
|
||||||
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
||||||
break;
|
break;
|
||||||
@ -210,6 +237,49 @@ g_filter_input_stream_get_base_stream (GFilterInputStream *stream)
|
|||||||
return stream->base_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
|
static gssize
|
||||||
g_filter_input_stream_read (GInputStream *stream,
|
g_filter_input_stream_read (GInputStream *stream,
|
||||||
void *buffer,
|
void *buffer,
|
||||||
@ -257,10 +327,13 @@ static gboolean
|
|||||||
g_filter_input_stream_close (GInputStream *stream,
|
g_filter_input_stream_close (GInputStream *stream,
|
||||||
GCancellable *cancellable,
|
GCancellable *cancellable,
|
||||||
GError **error)
|
GError **error)
|
||||||
|
{
|
||||||
|
gboolean res = TRUE;
|
||||||
|
|
||||||
|
if (GET_PRIVATE (stream)->close_base)
|
||||||
{
|
{
|
||||||
GFilterInputStream *filter_stream;
|
GFilterInputStream *filter_stream;
|
||||||
GInputStream *base_stream;
|
GInputStream *base_stream;
|
||||||
gboolean res;
|
|
||||||
|
|
||||||
filter_stream = G_FILTER_INPUT_STREAM (stream);
|
filter_stream = G_FILTER_INPUT_STREAM (stream);
|
||||||
base_stream = filter_stream->base_stream;
|
base_stream = filter_stream->base_stream;
|
||||||
@ -268,6 +341,7 @@ g_filter_input_stream_close (GInputStream *stream,
|
|||||||
res = g_input_stream_close (base_stream,
|
res = g_input_stream_close (base_stream,
|
||||||
cancellable,
|
cancellable,
|
||||||
error);
|
error);
|
||||||
|
}
|
||||||
|
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
@ -357,6 +431,26 @@ g_filter_input_stream_skip_finish (GInputStream *stream,
|
|||||||
return nskipped;
|
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
|
static void
|
||||||
g_filter_input_stream_close_async (GInputStream *stream,
|
g_filter_input_stream_close_async (GInputStream *stream,
|
||||||
int io_priority,
|
int io_priority,
|
||||||
@ -364,17 +458,26 @@ g_filter_input_stream_close_async (GInputStream *stream,
|
|||||||
GAsyncReadyCallback callback,
|
GAsyncReadyCallback callback,
|
||||||
gpointer user_data)
|
gpointer user_data)
|
||||||
{
|
{
|
||||||
GFilterInputStream *filter_stream;
|
GSimpleAsyncResult *simple;
|
||||||
GInputStream *base_stream;
|
|
||||||
|
|
||||||
filter_stream = G_FILTER_INPUT_STREAM (stream);
|
simple = g_simple_async_result_new (G_OBJECT (stream),
|
||||||
base_stream = filter_stream->base_stream;
|
callback, user_data,
|
||||||
|
g_filter_input_stream_close_async);
|
||||||
|
|
||||||
g_input_stream_close_async (base_stream,
|
if (GET_PRIVATE (stream)->close_base)
|
||||||
io_priority,
|
{
|
||||||
cancellable,
|
GFilterInputStream *filter_stream = G_FILTER_INPUT_STREAM (stream);
|
||||||
callback,
|
|
||||||
user_data);
|
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
|
static gboolean
|
||||||
@ -382,18 +485,14 @@ g_filter_input_stream_close_finish (GInputStream *stream,
|
|||||||
GAsyncResult *result,
|
GAsyncResult *result,
|
||||||
GError **error)
|
GError **error)
|
||||||
{
|
{
|
||||||
GFilterInputStream *filter_stream;
|
GSimpleAsyncResult *simple;
|
||||||
GInputStream *base_stream;
|
|
||||||
gboolean res;
|
|
||||||
|
|
||||||
filter_stream = G_FILTER_INPUT_STREAM (stream);
|
g_return_val_if_fail (g_simple_async_result_is_valid (
|
||||||
base_stream = filter_stream->base_stream;
|
result, G_OBJECT (stream), g_filter_input_stream_close_async), FALSE);
|
||||||
|
|
||||||
res = g_input_stream_close_finish (stream,
|
simple = G_SIMPLE_ASYNC_RESULT (result);
|
||||||
result,
|
|
||||||
error);
|
|
||||||
|
|
||||||
return res;
|
return !g_simple_async_result_propagate_error (simple, error);
|
||||||
}
|
}
|
||||||
|
|
||||||
#define __G_FILTER_INPUT_STREAM_C__
|
#define __G_FILTER_INPUT_STREAM_C__
|
||||||
|
@ -44,7 +44,6 @@ G_BEGIN_DECLS
|
|||||||
* A base class for all input streams that work on an underlying stream.
|
* A base class for all input streams that work on an underlying stream.
|
||||||
**/
|
**/
|
||||||
typedef struct _GFilterInputStreamClass GFilterInputStreamClass;
|
typedef struct _GFilterInputStreamClass GFilterInputStreamClass;
|
||||||
typedef struct _GFilterInputStreamPrivate GFilterInputStreamPrivate;
|
|
||||||
|
|
||||||
struct _GFilterInputStream
|
struct _GFilterInputStream
|
||||||
{
|
{
|
||||||
@ -68,6 +67,9 @@ struct _GFilterInputStreamClass
|
|||||||
|
|
||||||
GType g_filter_input_stream_get_type (void) G_GNUC_CONST;
|
GType g_filter_input_stream_get_type (void) G_GNUC_CONST;
|
||||||
GInputStream * g_filter_input_stream_get_base_stream (GFilterInputStream *stream);
|
GInputStream * g_filter_input_stream_get_base_stream (GFilterInputStream *stream);
|
||||||
|
gboolean g_filter_input_stream_get_close_base_stream (GFilterInputStream *stream);
|
||||||
|
void g_filter_input_stream_set_close_base_stream (GFilterInputStream *stream,
|
||||||
|
gboolean close_base);
|
||||||
|
|
||||||
G_END_DECLS
|
G_END_DECLS
|
||||||
|
|
||||||
|
@ -22,6 +22,7 @@
|
|||||||
|
|
||||||
#include "config.h"
|
#include "config.h"
|
||||||
#include "gfilteroutputstream.h"
|
#include "gfilteroutputstream.h"
|
||||||
|
#include "gsimpleasyncresult.h"
|
||||||
#include "goutputstream.h"
|
#include "goutputstream.h"
|
||||||
#include "glibintl.h"
|
#include "glibintl.h"
|
||||||
|
|
||||||
@ -36,7 +37,8 @@
|
|||||||
|
|
||||||
enum {
|
enum {
|
||||||
PROP_0,
|
PROP_0,
|
||||||
PROP_BASE_STREAM
|
PROP_BASE_STREAM,
|
||||||
|
PROP_CLOSE_BASE
|
||||||
};
|
};
|
||||||
|
|
||||||
static void g_filter_output_stream_set_property (GObject *object,
|
static void g_filter_output_stream_set_property (GObject *object,
|
||||||
@ -93,7 +95,13 @@ static gboolean g_filter_output_stream_close_finish (GOutputStream *strea
|
|||||||
|
|
||||||
G_DEFINE_TYPE (GFilterOutputStream, g_filter_output_stream, G_TYPE_OUTPUT_STREAM)
|
G_DEFINE_TYPE (GFilterOutputStream, g_filter_output_stream, G_TYPE_OUTPUT_STREAM)
|
||||||
|
|
||||||
|
#define GET_PRIVATE(inst) G_TYPE_INSTANCE_GET_PRIVATE (inst, \
|
||||||
|
G_TYPE_FILTER_OUTPUT_STREAM, GFilterOutputStreamPrivate)
|
||||||
|
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
gboolean close_base;
|
||||||
|
} GFilterOutputStreamPrivate;
|
||||||
|
|
||||||
static void
|
static void
|
||||||
g_filter_output_stream_class_init (GFilterOutputStreamClass *klass)
|
g_filter_output_stream_class_init (GFilterOutputStreamClass *klass)
|
||||||
@ -117,6 +125,8 @@ g_filter_output_stream_class_init (GFilterOutputStreamClass *klass)
|
|||||||
ostream_class->close_async = g_filter_output_stream_close_async;
|
ostream_class->close_async = g_filter_output_stream_close_async;
|
||||||
ostream_class->close_finish = g_filter_output_stream_close_finish;
|
ostream_class->close_finish = g_filter_output_stream_close_finish;
|
||||||
|
|
||||||
|
g_type_class_add_private (klass, sizeof (GFilterOutputStreamPrivate));
|
||||||
|
|
||||||
g_object_class_install_property (object_class,
|
g_object_class_install_property (object_class,
|
||||||
PROP_BASE_STREAM,
|
PROP_BASE_STREAM,
|
||||||
g_param_spec_object ("base-stream",
|
g_param_spec_object ("base-stream",
|
||||||
@ -126,6 +136,13 @@ g_filter_output_stream_class_init (GFilterOutputStreamClass *klass)
|
|||||||
G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY |
|
G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY |
|
||||||
G_PARAM_STATIC_NAME|G_PARAM_STATIC_NICK|G_PARAM_STATIC_BLURB));
|
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
|
static void
|
||||||
@ -146,6 +163,11 @@ g_filter_output_stream_set_property (GObject *object,
|
|||||||
filter_stream->base_stream = G_OUTPUT_STREAM (obj);
|
filter_stream->base_stream = G_OUTPUT_STREAM (obj);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case PROP_CLOSE_BASE:
|
||||||
|
g_filter_output_stream_set_close_base_stream (filter_stream,
|
||||||
|
g_value_get_boolean (value));
|
||||||
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
||||||
break;
|
break;
|
||||||
@ -169,6 +191,10 @@ g_filter_output_stream_get_property (GObject *object,
|
|||||||
g_value_set_object (value, filter_stream->base_stream);
|
g_value_set_object (value, filter_stream->base_stream);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case PROP_CLOSE_BASE:
|
||||||
|
g_value_set_boolean (value, GET_PRIVATE (filter_stream)->close_base);
|
||||||
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
||||||
break;
|
break;
|
||||||
@ -214,6 +240,49 @@ g_filter_output_stream_get_base_stream (GFilterOutputStream *stream)
|
|||||||
return stream->base_stream;
|
return stream->base_stream;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* g_filter_output_stream_get_close_base_stream:
|
||||||
|
* @stream: a #GFilterOutputStream.
|
||||||
|
*
|
||||||
|
* 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_output_stream_get_close_base_stream (GFilterOutputStream *stream)
|
||||||
|
{
|
||||||
|
g_return_val_if_fail (G_IS_FILTER_OUTPUT_STREAM (stream), FALSE);
|
||||||
|
|
||||||
|
return GET_PRIVATE (stream)->close_base;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* g_filter_output_stream_set_close_base_stream:
|
||||||
|
* @stream: a #GFilterOutputStream.
|
||||||
|
* @close_base: %TRUE to close the base stream.
|
||||||
|
*
|
||||||
|
* Sets whether the base stream will be closed when @stream is closed.
|
||||||
|
**/
|
||||||
|
void
|
||||||
|
g_filter_output_stream_set_close_base_stream (GFilterOutputStream *stream,
|
||||||
|
gboolean close_base)
|
||||||
|
{
|
||||||
|
GFilterOutputStreamPrivate *priv;
|
||||||
|
|
||||||
|
g_return_if_fail (G_IS_FILTER_OUTPUT_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
|
static gssize
|
||||||
g_filter_output_stream_write (GOutputStream *stream,
|
g_filter_output_stream_write (GOutputStream *stream,
|
||||||
const void *buffer,
|
const void *buffer,
|
||||||
@ -256,15 +325,19 @@ static gboolean
|
|||||||
g_filter_output_stream_close (GOutputStream *stream,
|
g_filter_output_stream_close (GOutputStream *stream,
|
||||||
GCancellable *cancellable,
|
GCancellable *cancellable,
|
||||||
GError **error)
|
GError **error)
|
||||||
|
{
|
||||||
|
gboolean res = TRUE;
|
||||||
|
|
||||||
|
if (GET_PRIVATE (stream)->close_base)
|
||||||
{
|
{
|
||||||
GFilterOutputStream *filter_stream;
|
GFilterOutputStream *filter_stream;
|
||||||
gboolean res;
|
|
||||||
|
|
||||||
filter_stream = G_FILTER_OUTPUT_STREAM (stream);
|
filter_stream = G_FILTER_OUTPUT_STREAM (stream);
|
||||||
|
|
||||||
res = g_output_stream_close (filter_stream->base_stream,
|
res = g_output_stream_close (filter_stream->base_stream,
|
||||||
cancellable,
|
cancellable,
|
||||||
error);
|
error);
|
||||||
|
}
|
||||||
|
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
@ -344,22 +417,53 @@ g_filter_output_stream_flush_finish (GOutputStream *stream,
|
|||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
g_filter_output_stream_close_ready (GObject *object,
|
||||||
|
GAsyncResult *result,
|
||||||
|
gpointer user_data)
|
||||||
|
{
|
||||||
|
GSimpleAsyncResult *simple = user_data;
|
||||||
|
GError *error = NULL;
|
||||||
|
|
||||||
|
g_output_stream_close_finish (G_OUTPUT_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
|
static void
|
||||||
g_filter_output_stream_close_async (GOutputStream *stream,
|
g_filter_output_stream_close_async (GOutputStream *stream,
|
||||||
int io_priority,
|
int io_priority,
|
||||||
GCancellable *cancellable,
|
GCancellable *cancellable,
|
||||||
GAsyncReadyCallback callback,
|
GAsyncReadyCallback callback,
|
||||||
gpointer data)
|
gpointer user_data)
|
||||||
{
|
{
|
||||||
GFilterOutputStream *filter_stream;
|
GSimpleAsyncResult *simple;
|
||||||
|
|
||||||
filter_stream = G_FILTER_OUTPUT_STREAM (stream);
|
simple = g_simple_async_result_new (G_OBJECT (stream),
|
||||||
|
callback, user_data,
|
||||||
|
g_filter_output_stream_close_async);
|
||||||
|
|
||||||
|
if (GET_PRIVATE (stream)->close_base)
|
||||||
|
{
|
||||||
|
GFilterOutputStream *filter_stream = G_FILTER_OUTPUT_STREAM (stream);
|
||||||
|
|
||||||
g_output_stream_close_async (filter_stream->base_stream,
|
g_output_stream_close_async (filter_stream->base_stream,
|
||||||
io_priority,
|
io_priority, cancellable,
|
||||||
cancellable,
|
g_filter_output_stream_close_ready,
|
||||||
callback,
|
g_object_ref (simple));
|
||||||
data);
|
}
|
||||||
|
else
|
||||||
|
/* do nothing */
|
||||||
|
g_simple_async_result_complete_in_idle (simple);
|
||||||
|
|
||||||
|
g_object_unref (simple);
|
||||||
}
|
}
|
||||||
|
|
||||||
static gboolean
|
static gboolean
|
||||||
@ -367,16 +471,14 @@ g_filter_output_stream_close_finish (GOutputStream *stream,
|
|||||||
GAsyncResult *result,
|
GAsyncResult *result,
|
||||||
GError **error)
|
GError **error)
|
||||||
{
|
{
|
||||||
GFilterOutputStream *filter_stream;
|
GSimpleAsyncResult *simple;
|
||||||
gboolean res;
|
|
||||||
|
|
||||||
filter_stream = G_FILTER_OUTPUT_STREAM (stream);
|
g_return_val_if_fail (g_simple_async_result_is_valid (
|
||||||
|
result, G_OBJECT (stream), g_filter_output_stream_close_async), FALSE);
|
||||||
|
|
||||||
res = g_output_stream_close_finish (filter_stream->base_stream,
|
simple = G_SIMPLE_ASYNC_RESULT (result);
|
||||||
result,
|
|
||||||
error);
|
|
||||||
|
|
||||||
return res;
|
return !g_simple_async_result_propagate_error (simple, error);
|
||||||
}
|
}
|
||||||
|
|
||||||
#define __G_FILTER_OUTPUT_STREAM_C__
|
#define __G_FILTER_OUTPUT_STREAM_C__
|
||||||
|
@ -44,7 +44,6 @@ G_BEGIN_DECLS
|
|||||||
* A base class for all output streams that work on an underlying stream.
|
* A base class for all output streams that work on an underlying stream.
|
||||||
**/
|
**/
|
||||||
typedef struct _GFilterOutputStreamClass GFilterOutputStreamClass;
|
typedef struct _GFilterOutputStreamClass GFilterOutputStreamClass;
|
||||||
typedef struct _GFilterOutputStreamPrivate GFilterOutputStreamPrivate;
|
|
||||||
|
|
||||||
struct _GFilterOutputStream
|
struct _GFilterOutputStream
|
||||||
{
|
{
|
||||||
@ -68,6 +67,9 @@ struct _GFilterOutputStreamClass
|
|||||||
|
|
||||||
GType g_filter_output_stream_get_type (void) G_GNUC_CONST;
|
GType g_filter_output_stream_get_type (void) G_GNUC_CONST;
|
||||||
GOutputStream * g_filter_output_stream_get_base_stream (GFilterOutputStream *stream);
|
GOutputStream * g_filter_output_stream_get_base_stream (GFilterOutputStream *stream);
|
||||||
|
gboolean g_filter_output_stream_get_close_base_stream (GFilterOutputStream *stream);
|
||||||
|
void g_filter_output_stream_set_close_base_stream (GFilterOutputStream *stream,
|
||||||
|
gboolean close_base);
|
||||||
|
|
||||||
G_END_DECLS
|
G_END_DECLS
|
||||||
|
|
||||||
|
@ -456,6 +456,8 @@ g_file_output_stream_get_etag
|
|||||||
#if IN_FILE(__G_FILTER_INPUT_STREAM_C__)
|
#if IN_FILE(__G_FILTER_INPUT_STREAM_C__)
|
||||||
g_filter_input_stream_get_type G_GNUC_CONST
|
g_filter_input_stream_get_type G_GNUC_CONST
|
||||||
g_filter_input_stream_get_base_stream
|
g_filter_input_stream_get_base_stream
|
||||||
|
g_filter_input_stream_get_close_base_stream
|
||||||
|
g_filter_input_stream_set_close_base_stream
|
||||||
#endif
|
#endif
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@ -463,6 +465,8 @@ g_filter_input_stream_get_base_stream
|
|||||||
#if IN_FILE(__G_FILTER_OUTPUT_STREAM_C__)
|
#if IN_FILE(__G_FILTER_OUTPUT_STREAM_C__)
|
||||||
g_filter_output_stream_get_type G_GNUC_CONST
|
g_filter_output_stream_get_type G_GNUC_CONST
|
||||||
g_filter_output_stream_get_base_stream
|
g_filter_output_stream_get_base_stream
|
||||||
|
g_filter_output_stream_get_close_base_stream
|
||||||
|
g_filter_output_stream_set_close_base_stream
|
||||||
#endif
|
#endif
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
1
gio/tests/.gitignore
vendored
1
gio/tests/.gitignore
vendored
@ -10,3 +10,4 @@ g-file-info
|
|||||||
live-g-file
|
live-g-file
|
||||||
memory-input-stream
|
memory-input-stream
|
||||||
memory-output-stream
|
memory-output-stream
|
||||||
|
filter-streams
|
||||||
|
@ -25,6 +25,7 @@ TEST_PROGS += \
|
|||||||
data-output-stream \
|
data-output-stream \
|
||||||
g-icon \
|
g-icon \
|
||||||
buffered-input-stream \
|
buffered-input-stream \
|
||||||
|
filter-streams \
|
||||||
simple-async-result
|
simple-async-result
|
||||||
|
|
||||||
if OS_UNIX
|
if OS_UNIX
|
||||||
@ -68,4 +69,7 @@ unix_streams_LDADD = $(progs_ldadd) \
|
|||||||
simple_async_result_SOURCES = simple-async-result.c
|
simple_async_result_SOURCES = simple-async-result.c
|
||||||
simple_async_result_LDADD = $(progs_ldadd)
|
simple_async_result_LDADD = $(progs_ldadd)
|
||||||
|
|
||||||
|
filter_streams_SOURCES = filter-streams.c
|
||||||
|
filter_streams_LDADD = $(progs_ldadd)
|
||||||
|
|
||||||
DISTCLEAN_FILES = applications/mimeinfo.cache
|
DISTCLEAN_FILES = applications/mimeinfo.cache
|
||||||
|
239
gio/tests/filter-streams.c
Normal file
239
gio/tests/filter-streams.c
Normal file
@ -0,0 +1,239 @@
|
|||||||
|
/*
|
||||||
|
* Copyright © 2009 Codethink Limited
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU Lesser General Public License as published
|
||||||
|
* by the Free Software Foundation; either version 2 of the licence or (at
|
||||||
|
* your option) any later version.
|
||||||
|
*
|
||||||
|
* See the included COPYING file for more information.
|
||||||
|
*
|
||||||
|
* Author: Ryan Lortie <desrt@desrt.ca>
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <glib/glib.h>
|
||||||
|
#include <gio/gio.h>
|
||||||
|
|
||||||
|
static void
|
||||||
|
test_input_filter (void)
|
||||||
|
{
|
||||||
|
GInputStream *base, *f1, *f2;
|
||||||
|
|
||||||
|
g_test_bug ("568394");
|
||||||
|
base = g_memory_input_stream_new_from_data ("abcdefghijk", -1, NULL);
|
||||||
|
f1 = g_buffered_input_stream_new (base);
|
||||||
|
f2 = g_buffered_input_stream_new (base);
|
||||||
|
|
||||||
|
g_filter_input_stream_set_close_base_stream (G_FILTER_INPUT_STREAM (f1), FALSE);
|
||||||
|
|
||||||
|
g_assert (g_filter_input_stream_get_base_stream (G_FILTER_INPUT_STREAM (f1)) == base);
|
||||||
|
g_assert (g_filter_input_stream_get_base_stream (G_FILTER_INPUT_STREAM (f2)) == base);
|
||||||
|
|
||||||
|
g_assert (!g_input_stream_is_closed (base));
|
||||||
|
g_assert (!g_input_stream_is_closed (f1));
|
||||||
|
g_assert (!g_input_stream_is_closed (f2));
|
||||||
|
|
||||||
|
g_object_unref (f1);
|
||||||
|
|
||||||
|
g_assert (!g_input_stream_is_closed (base));
|
||||||
|
g_assert (!g_input_stream_is_closed (f2));
|
||||||
|
|
||||||
|
g_object_unref (f2);
|
||||||
|
|
||||||
|
g_assert (g_input_stream_is_closed (base));
|
||||||
|
|
||||||
|
g_object_unref (base);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
test_output_filter (void)
|
||||||
|
{
|
||||||
|
GOutputStream *base, *f1, *f2;
|
||||||
|
|
||||||
|
base = g_memory_output_stream_new (NULL, 0, g_realloc, g_free);
|
||||||
|
f1 = g_buffered_output_stream_new (base);
|
||||||
|
f2 = g_buffered_output_stream_new (base);
|
||||||
|
|
||||||
|
g_filter_output_stream_set_close_base_stream (G_FILTER_OUTPUT_STREAM (f1), FALSE);
|
||||||
|
|
||||||
|
g_assert (g_filter_output_stream_get_base_stream (G_FILTER_OUTPUT_STREAM (f1)) == base);
|
||||||
|
g_assert (g_filter_output_stream_get_base_stream (G_FILTER_OUTPUT_STREAM (f2)) == base);
|
||||||
|
|
||||||
|
g_assert (!g_output_stream_is_closed (base));
|
||||||
|
g_assert (!g_output_stream_is_closed (f1));
|
||||||
|
g_assert (!g_output_stream_is_closed (f2));
|
||||||
|
|
||||||
|
g_object_unref (f1);
|
||||||
|
|
||||||
|
g_assert (!g_output_stream_is_closed (base));
|
||||||
|
g_assert (!g_output_stream_is_closed (f2));
|
||||||
|
|
||||||
|
g_object_unref (f2);
|
||||||
|
|
||||||
|
g_assert (g_output_stream_is_closed (base));
|
||||||
|
|
||||||
|
g_object_unref (base);
|
||||||
|
}
|
||||||
|
|
||||||
|
gpointer expected_obj;
|
||||||
|
gpointer expected_data;
|
||||||
|
gboolean callback_happened;
|
||||||
|
|
||||||
|
static void
|
||||||
|
in_cb (GObject *object,
|
||||||
|
GAsyncResult *result,
|
||||||
|
gpointer user_data)
|
||||||
|
{
|
||||||
|
GError *error = NULL;
|
||||||
|
|
||||||
|
g_assert (object == expected_obj);
|
||||||
|
g_assert (user_data == expected_data);
|
||||||
|
g_assert (callback_happened == FALSE);
|
||||||
|
|
||||||
|
g_input_stream_close_finish (expected_obj, result, &error);
|
||||||
|
g_assert (error == NULL);
|
||||||
|
|
||||||
|
callback_happened = TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
test_input_async (void)
|
||||||
|
{
|
||||||
|
GInputStream *base, *f1, *f2;
|
||||||
|
|
||||||
|
base = g_memory_input_stream_new_from_data ("abcdefghijk", -1, NULL);
|
||||||
|
f1 = g_buffered_input_stream_new (base);
|
||||||
|
f2 = g_buffered_input_stream_new (base);
|
||||||
|
|
||||||
|
g_filter_input_stream_set_close_base_stream (G_FILTER_INPUT_STREAM (f1), FALSE);
|
||||||
|
|
||||||
|
g_assert (g_filter_input_stream_get_base_stream (G_FILTER_INPUT_STREAM (f1)) == base);
|
||||||
|
g_assert (g_filter_input_stream_get_base_stream (G_FILTER_INPUT_STREAM (f2)) == base);
|
||||||
|
|
||||||
|
g_assert (!g_input_stream_is_closed (base));
|
||||||
|
g_assert (!g_input_stream_is_closed (f1));
|
||||||
|
g_assert (!g_input_stream_is_closed (f2));
|
||||||
|
|
||||||
|
expected_obj = f1;
|
||||||
|
expected_data = g_malloc (20);
|
||||||
|
callback_happened = FALSE;
|
||||||
|
g_input_stream_close_async (f1, 0, NULL, in_cb, expected_data);
|
||||||
|
|
||||||
|
g_assert (callback_happened == FALSE);
|
||||||
|
while (g_main_context_pending (NULL))
|
||||||
|
g_main_context_iteration (NULL, FALSE);
|
||||||
|
g_assert (callback_happened == TRUE);
|
||||||
|
|
||||||
|
g_assert (!g_input_stream_is_closed (base));
|
||||||
|
g_assert (!g_input_stream_is_closed (f2));
|
||||||
|
g_free (expected_data);
|
||||||
|
g_object_unref (f1);
|
||||||
|
g_assert (!g_input_stream_is_closed (base));
|
||||||
|
g_assert (!g_input_stream_is_closed (f2));
|
||||||
|
|
||||||
|
expected_obj = f2;
|
||||||
|
expected_data = g_malloc (20);
|
||||||
|
callback_happened = FALSE;
|
||||||
|
g_input_stream_close_async (f2, 0, NULL, in_cb, expected_data);
|
||||||
|
|
||||||
|
g_assert (callback_happened == FALSE);
|
||||||
|
while (g_main_context_pending (NULL))
|
||||||
|
g_main_context_iteration (NULL, FALSE);
|
||||||
|
g_assert (callback_happened == TRUE);
|
||||||
|
|
||||||
|
g_assert (g_input_stream_is_closed (base));
|
||||||
|
g_assert (g_input_stream_is_closed (f2));
|
||||||
|
g_free (expected_data);
|
||||||
|
g_object_unref (f2);
|
||||||
|
|
||||||
|
g_assert (g_input_stream_is_closed (base));
|
||||||
|
g_object_unref (base);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
out_cb (GObject *object,
|
||||||
|
GAsyncResult *result,
|
||||||
|
gpointer user_data)
|
||||||
|
{
|
||||||
|
GError *error = NULL;
|
||||||
|
|
||||||
|
g_assert (object == expected_obj);
|
||||||
|
g_assert (user_data == expected_data);
|
||||||
|
g_assert (callback_happened == FALSE);
|
||||||
|
|
||||||
|
g_output_stream_close_finish (expected_obj, result, &error);
|
||||||
|
g_assert (error == NULL);
|
||||||
|
|
||||||
|
callback_happened = TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void
|
||||||
|
test_output_async (void)
|
||||||
|
{
|
||||||
|
GOutputStream *base, *f1, *f2;
|
||||||
|
|
||||||
|
base = g_memory_output_stream_new (NULL, 0, g_realloc, g_free);
|
||||||
|
f1 = g_buffered_output_stream_new (base);
|
||||||
|
f2 = g_buffered_output_stream_new (base);
|
||||||
|
|
||||||
|
g_filter_output_stream_set_close_base_stream (G_FILTER_OUTPUT_STREAM (f1), FALSE);
|
||||||
|
|
||||||
|
g_assert (g_filter_output_stream_get_base_stream (G_FILTER_OUTPUT_STREAM (f1)) == base);
|
||||||
|
g_assert (g_filter_output_stream_get_base_stream (G_FILTER_OUTPUT_STREAM (f2)) == base);
|
||||||
|
|
||||||
|
g_assert (!g_output_stream_is_closed (base));
|
||||||
|
g_assert (!g_output_stream_is_closed (f1));
|
||||||
|
g_assert (!g_output_stream_is_closed (f2));
|
||||||
|
|
||||||
|
expected_obj = f1;
|
||||||
|
expected_data = g_malloc (20);
|
||||||
|
callback_happened = FALSE;
|
||||||
|
g_output_stream_close_async (f1, 0, NULL, out_cb, expected_data);
|
||||||
|
|
||||||
|
g_assert (callback_happened == FALSE);
|
||||||
|
while (g_main_context_pending (NULL))
|
||||||
|
g_main_context_iteration (NULL, FALSE);
|
||||||
|
g_assert (callback_happened == TRUE);
|
||||||
|
|
||||||
|
g_assert (!g_output_stream_is_closed (base));
|
||||||
|
g_assert (!g_output_stream_is_closed (f2));
|
||||||
|
g_free (expected_data);
|
||||||
|
g_object_unref (f1);
|
||||||
|
g_assert (!g_output_stream_is_closed (base));
|
||||||
|
g_assert (!g_output_stream_is_closed (f2));
|
||||||
|
|
||||||
|
expected_obj = f2;
|
||||||
|
expected_data = g_malloc (20);
|
||||||
|
callback_happened = FALSE;
|
||||||
|
g_output_stream_close_async (f2, 0, NULL, out_cb, expected_data);
|
||||||
|
|
||||||
|
g_assert (callback_happened == FALSE);
|
||||||
|
while (g_main_context_pending (NULL))
|
||||||
|
g_main_context_iteration (NULL, FALSE);
|
||||||
|
g_assert (callback_happened == TRUE);
|
||||||
|
|
||||||
|
g_assert (g_output_stream_is_closed (base));
|
||||||
|
g_assert (g_output_stream_is_closed (f2));
|
||||||
|
g_free (expected_data);
|
||||||
|
g_object_unref (f2);
|
||||||
|
|
||||||
|
g_assert (g_output_stream_is_closed (base));
|
||||||
|
g_object_unref (base);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int
|
||||||
|
main (int argc, char **argv)
|
||||||
|
{
|
||||||
|
g_test_init (&argc, &argv, NULL);
|
||||||
|
g_test_bug_base ("http://bugzilla.gnome.org/");
|
||||||
|
|
||||||
|
g_type_init ();
|
||||||
|
g_test_add_func ("/filter-stream/input", test_input_filter);
|
||||||
|
g_test_add_func ("/filter-stream/output", test_output_filter);
|
||||||
|
g_test_add_func ("/filter-stream/async-input", test_input_async);
|
||||||
|
g_test_add_func ("/filter-stream/async-output", test_output_async);
|
||||||
|
|
||||||
|
return g_test_run();
|
||||||
|
}
|
Loading…
x
Reference in New Issue
Block a user