예제 #1
0
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;
}
예제 #2
0
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);
}
예제 #3
0
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);
}
예제 #4
0
/* TYPICALLY CALLED FROM ANOTHER THREAD */
void
hio_output_stream_close(HioOutputStream *stream)
{
    if (g_atomic_int_exchange_and_add(&stream->closed, 1) == 0) {
        /* If we just went from 0 (not closed) to 1 (closed) and that
         * makes us done, we need to notify done-ness in the task
         * thread.  If we still aren't done, we'll notify done-ness
         * once we flush so don't need to add a handler here.
         *
         * It's important not to add a watcher if we've already
         * notified done-ness because we'll have unblocked completion
         * and you can't add watchers to completed tasks.
         */
        if (hio_output_stream_is_done(stream)) {
            hrt_task_add_immediate(stream->task,
                                   on_notify_done_after_close,
                                   g_object_ref(stream),
                                   g_object_unref);
        }
    }
}
예제 #5
0
/* IN OUR TASK THREAD */
static void
notify_if_done(HioOutputStream *stream)
{
    HRT_ASSERT_IN_TASK_THREAD(stream->task);

    if (g_atomic_int_get(&stream->done_notified) == 0 &&
        hio_output_stream_is_done(stream)) {
        g_atomic_int_inc(&stream->done_notified);

        /* allow task to complete, assuming it has no other watchers.
         *
         * Another side effect: this should mean the task can complete
         * even if no watcher was ever added, which happens if the
         * stream is closed with no bytes ever written.
         */
        hrt_task_unblock_completion(stream->task);

        g_mutex_lock(stream->done_notify_lock);
        if (stream->done_notify_func != NULL) {
            HioOutputStreamDoneNotify func = stream->done_notify_func;
            void *data = stream->done_notify_data;
            GDestroyNotify dnotify = stream->done_notify_dnotify;

            stream->done_notify_func = NULL;
            stream->done_notify_data = NULL;
            stream->done_notify_dnotify = NULL;

            g_mutex_unlock(stream->done_notify_lock);

            g_object_ref(stream);
            (* func) (stream, data);
            if (dnotify != NULL) {
                (* dnotify) (data);
            }
            g_object_unref(stream);
        } else {
            g_mutex_unlock(stream->done_notify_lock);
        }
    }
}