/* TYPICALLY CALLED FROM ANOTHER THREAD */ void hio_output_stream_write(HioOutputStream *stream, HrtBuffer *locked_buffer) { g_return_if_fail(hrt_buffer_is_locked(locked_buffer)); if (hrt_buffer_get_length(locked_buffer) == 0) return; if (hio_output_stream_is_closed(stream)) return; g_mutex_lock(stream->buffers_lock); /* note, we still want to buffer stuff if fd == -1 since that just * means we aren't being asked to write yet. But on error, discard * anything that gets written. */ if (g_atomic_int_get(&stream->errored) == 0) { /* we could set stream->errored right here after we just * checked we haven't. However in that case, the * drop_all_buffers() just after we set stream->errored will * have to block for buffers_lock and only then drop them, so * it should drop this one we're pushing. */ hrt_buffer_ref(locked_buffer); g_queue_push_tail(&stream->buffers, locked_buffer); } g_mutex_unlock(stream->buffers_lock); /* add write watcher if necessary. */ check_write_watcher(stream); }
static void test_stream_with_error(OutputTestFixture *fixture, const void *data) { HioOutputStream *stream; g_assert(fixture->chain_task == NULL); close(fixture->read_fd); /* should error the writes */ stream = hio_output_stream_new(fixture->stream_tasks[0]); hio_output_stream_set_fd(stream, fixture->write_fd); hrt_task_add_immediate(fixture->write_tasks[0], on_write_stream_task, write_task_data_new(stream, fixture->stream_descs), write_task_data_free); /* run main loop to collect the tasks */ g_main_loop_run(fixture->loop); /* if the stream is zero-length we'll never try to write and never get an error */ g_assert(fixture->stream_descs->length == 0 || hio_output_stream_got_error(stream)); g_assert(hio_output_stream_is_done(stream)); g_assert(hio_output_stream_is_closed(stream)); g_object_unref(stream); /* so we don't close it again in teardown */ fixture->read_fd = -1; }
static void test_stream_with_initial_error(OutputTestFixture *fixture, const void *data) { HioOutputStream *stream; g_assert(fixture->chain_task == NULL); /* error before we even set an fd on it */ stream = hio_output_stream_new(fixture->stream_tasks[0]); hio_output_stream_error(stream); hrt_task_add_immediate(fixture->write_tasks[0], on_write_stream_task, write_task_data_new(stream, fixture->stream_descs), write_task_data_free); /* run main loop to collect the tasks */ g_main_loop_run(fixture->loop); g_assert(hio_output_stream_got_error(stream)); g_assert(hio_output_stream_is_done(stream)); g_assert(hio_output_stream_is_closed(stream)); g_object_unref(stream); }
static void test_stream(OutputTestFixture *fixture, const void *data) { HioOutputStream *stream; g_assert(fixture->chain_task == NULL); stream = hio_output_stream_new(fixture->stream_tasks[0]); hio_output_stream_set_fd(stream, fixture->write_fd); hrt_task_add_immediate(fixture->write_tasks[0], on_write_stream_task, write_task_data_new(stream, fixture->stream_descs), write_task_data_free); read_and_verify_stream(fixture->read_fd, fixture->stream_descs); /* run main loop to collect the task */ g_main_loop_run(fixture->loop); g_assert(!hio_output_stream_got_error(stream)); g_assert(hio_output_stream_is_done(stream)); g_assert(hio_output_stream_is_closed(stream)); g_object_unref(stream); }
/* CALLED FROM ANY THREAD */ gboolean hio_output_stream_is_done(HioOutputStream *stream) { gboolean done; g_mutex_lock(stream->buffers_lock); done = hio_output_stream_is_closed(stream) && (g_queue_get_length(&stream->buffers) == 0 || hio_output_stream_got_error(stream)); g_mutex_unlock(stream->buffers_lock); return done; }