wstream: Implement wstream_set_file

It's analogous to rstream_set_file but only supports pipes(Support for regular
files may be added later). This function was added to support creating API
channels via stdout.
This commit is contained in:
Thiago de Arruda 2014-08-12 14:57:47 -03:00
parent b744073fae
commit 801ed0e0a3

View File

@ -1,6 +1,7 @@
#include <assert.h> #include <assert.h>
#include <stdint.h> #include <stdint.h>
#include <stdbool.h> #include <stdbool.h>
#include <stdlib.h>
#include <uv.h> #include <uv.h>
@ -20,7 +21,7 @@ struct wstream {
size_t maxmem; size_t maxmem;
// Number of pending requests // Number of pending requests
size_t pending_reqs; size_t pending_reqs;
bool freed; bool freed, free_handle;
// (optional) Write callback and data // (optional) Write callback and data
wstream_cb cb; wstream_cb cb;
void *data; void *data;
@ -60,6 +61,7 @@ WStream * wstream_new(size_t maxmem)
rv->curmem = 0; rv->curmem = 0;
rv->pending_reqs = 0; rv->pending_reqs = 0;
rv->freed = false; rv->freed = false;
rv->free_handle = false;
rv->cb = NULL; rv->cb = NULL;
return rv; return rv;
@ -68,9 +70,13 @@ WStream * wstream_new(size_t maxmem)
/// Frees all memory allocated for a WStream instance /// Frees all memory allocated for a WStream instance
/// ///
/// @param wstream The `WStream` instance /// @param wstream The `WStream` instance
void wstream_free(WStream *wstream) void wstream_free(WStream *wstream) {
{
if (!wstream->pending_reqs) { if (!wstream->pending_reqs) {
handle_set_wstream((uv_handle_t *)wstream->stream, NULL);
if (wstream->free_handle) {
uv_close((uv_handle_t *)wstream->stream, close_cb);
}
free(wstream); free(wstream);
} else { } else {
wstream->freed = true; wstream->freed = true;
@ -87,6 +93,24 @@ void wstream_set_stream(WStream *wstream, uv_stream_t *stream)
wstream->stream = stream; wstream->stream = stream;
} }
/// Sets the underlying file descriptor that will be written to. Only pipes
/// are supported for now.
///
/// @param wstream The `WStream` instance
/// @param file The file descriptor
void wstream_set_file(WStream *wstream, uv_file file)
{
uv_handle_type type = uv_guess_handle(file);
assert(type == UV_NAMED_PIPE || type == UV_TTY);
wstream->stream = xmalloc(sizeof(uv_pipe_t));
uv_pipe_init(uv_default_loop(), (uv_pipe_t *)wstream->stream, 0);
uv_pipe_open((uv_pipe_t *)wstream->stream, file);
wstream->stream->data = NULL;
handle_set_wstream((uv_handle_t *)wstream->stream, wstream);
wstream->free_handle = true;
}
/// Sets a callback that will be called on completion of a write request, /// Sets a callback that will be called on completion of a write request,
/// indicating failure/success. /// indicating failure/success.
/// ///
@ -211,3 +235,16 @@ static void release_wbuffer(WBuffer *buffer)
free(buffer); free(buffer);
} }
} }
static void close_cb(uv_handle_t *handle)
{
WStream *wstream = handle_get_wstream(handle);
if (wstream) {
free(wstream);
}
free(handle->data);
free(handle);
}