actual payload stream. */
conn->incoming_payload = response->payload =
i_stream_create_limit(response->payload, (uoff_t)-1);
- i_stream_set_destroy_callback(response->payload,
+ i_stream_add_destroy_callback(response->payload,
http_client_payload_destroyed,
req);
/* the callback may add its own I/O, so we need to remove
if (retrying) {
/* retrying, don't destroy the request */
if (response->payload != NULL) {
- i_stream_unset_destroy_callback(conn->incoming_payload);
+ i_stream_remove_destroy_callback(conn->incoming_payload,
+ http_client_payload_destroyed);
i_stream_unref(&conn->incoming_payload);
conn->conn.io = io_add(conn->conn.fd_in, IO_READ,
http_client_connection_input,
data = buffer_get_data(conn->literal_buf, &size);
i_assert(size == conn->literal_size);
reply->input = i_stream_create_from_data(data, size);
- i_stream_set_destroy_callback(reply->input,
+ i_stream_add_destroy_callback(reply->input,
literal_stream_destroy,
conn->literal_buf);
}
/* do this only once in case a plugin changes the stream.
otherwise the check would break. */
data->destroy_callback_set = TRUE;
- i_stream_set_destroy_callback(data->stream,
+ i_stream_add_destroy_callback(data->stream,
index_mail_stream_destroy_callback, mail);
}
i_stream_unref(&data->filter_stream);
if (data->stream != NULL) {
data->destroying_stream = TRUE;
- if (!closing) {
+ if (!closing && data->destroy_callback_set) {
/* we're replacing the stream with a new one. it's
allowed to have references until the mail is closed
(but we can't really check that) */
- i_stream_unset_destroy_callback(data->stream);
+ i_stream_remove_destroy_callback(data->stream,
+ index_mail_stream_destroy_callback);
}
i_stream_unref(&data->stream);
if (closing) {
/* This file is private to input stream and output stream implementations */
+struct iostream_destroy_callback {
+ void (*callback)(void *context);
+ void *context;
+};
+
struct iostream_private {
int refcount;
char *name;
void (*set_max_buffer_size)(struct iostream_private *stream,
size_t max_size);
- void (*destroy_callback)(void *context);
- void *destroy_context;
+ ARRAY(struct iostream_destroy_callback) destroy_callbacks;
};
void io_stream_init(struct iostream_private *stream);
tstream->buf->used);
i_stream_set_name(input, t_strdup_printf(
"(Temp file in %s)", tstream->temp_path_prefix));
- i_stream_set_destroy_callback(input, iostream_temp_buf_destroyed,
+ i_stream_add_destroy_callback(input, iostream_temp_buf_destroyed,
tstream->buf);
tstream->buf = NULL;
}
/* Copyright (c) 2002-2013 Dovecot authors, see the included COPYING file */
#include "lib.h"
+#include "array.h"
#include "iostream-private.h"
static void
void io_stream_unref(struct iostream_private *stream)
{
+ const struct iostream_destroy_callback *dc;
+
i_assert(stream->refcount > 0);
if (--stream->refcount != 0)
return;
stream->close(stream, FALSE);
stream->destroy(stream);
- if (stream->destroy_callback != NULL)
- stream->destroy_callback(stream->destroy_context);
+ if (array_is_created(&stream->destroy_callbacks)) {
+ array_foreach(&stream->destroy_callbacks, dc)
+ dc->callback(dc->context);
+ array_free(&stream->destroy_callbacks);
+ }
i_free(stream->name);
i_free(stream);
#include "lib.h"
#include "ioloop.h"
+#include "array.h"
#include "str.h"
#include "istream-private.h"
*stream = NULL;
}
-#undef i_stream_set_destroy_callback
-void i_stream_set_destroy_callback(struct istream *stream,
+#undef i_stream_add_destroy_callback
+void i_stream_add_destroy_callback(struct istream *stream,
istream_callback_t *callback, void *context)
{
struct iostream_private *iostream = &stream->real_stream->iostream;
+ struct iostream_destroy_callback *dc;
- iostream->destroy_callback = callback;
- iostream->destroy_context = context;
+ if (!array_is_created(&iostream->destroy_callbacks))
+ i_array_init(&iostream->destroy_callbacks, 2);
+ dc = array_append_space(&iostream->destroy_callbacks);
+ dc->callback = callback;
+ dc->context = context;
}
-void i_stream_unset_destroy_callback(struct istream *stream)
+void i_stream_remove_destroy_callback(struct istream *stream,
+ void (*callback)())
{
struct iostream_private *iostream = &stream->real_stream->iostream;
+ const struct iostream_destroy_callback *dcs;
+ unsigned int i, count;
- iostream->destroy_callback = NULL;
- iostream->destroy_context = NULL;
+ dcs = array_get(&iostream->destroy_callbacks, &count);
+ for (i = 0; i < count; i++) {
+ if (dcs[i].callback == callback) {
+ array_delete(&iostream->destroy_callbacks, i, 1);
+ return;
+ }
+ }
+ i_unreached();
}
int i_stream_get_fd(struct istream *stream)
/* Unreferences the stream and sets stream pointer to NULL. */
void i_stream_unref(struct istream **stream);
/* Call the given callback function when stream is destroyed. */
-void i_stream_set_destroy_callback(struct istream *stream,
+void i_stream_add_destroy_callback(struct istream *stream,
istream_callback_t *callback, void *context)
ATTR_NULL(3);
-#define i_stream_set_destroy_callback(stream, callback, context) \
- i_stream_set_destroy_callback(stream + \
+#define i_stream_add_destroy_callback(stream, callback, context) \
+ i_stream_add_destroy_callback(stream + \
CALLBACK_TYPECHECK(callback, void (*)(typeof(context))), \
(istream_callback_t *)callback, context)
/* Remove the destroy callback. */
-void i_stream_unset_destroy_callback(struct istream *stream);
+void i_stream_remove_destroy_callback(struct istream *stream,
+ void (*callback)());
/* Return file descriptor for stream, or -1 if none is available. */
int i_stream_get_fd(struct istream *stream);
parser->state = parser->state == JSON_STATE_OBJECT_VALUE ?
JSON_STATE_OBJECT_SKIP_STRING : JSON_STATE_ARRAY_SKIP_STRING;
parser->strinput = i_stream_create_jsonstr(parser->input);
- i_stream_set_destroy_callback(parser->strinput,
+ i_stream_add_destroy_callback(parser->strinput,
json_strinput_destroyed, parser);
*input_r = parser->strinput;