Coverage Report

Created: 2017-04-15 07:07

/home/travis/build/MoarVM/MoarVM/src/io/timers.c
Line
Count
Source (jump to first uncovered line)
1
#include "moar.h"
2
3
/* Info we convey about a timer. */
4
typedef struct {
5
    int timeout;
6
    int repeat;
7
    uv_timer_t handle;
8
    MVMThreadContext *tc;
9
    int work_idx;
10
} TimerInfo;
11
12
/* Timer callback; dispatches schedulee to the queue. */
13
0
static void timer_cb(uv_timer_t *handle) {
14
0
    TimerInfo        *ti = (TimerInfo *)handle->data;
15
0
    MVMThreadContext *tc = ti->tc;
16
0
    MVMAsyncTask     *t  = MVM_io_eventloop_get_active_work(tc, ti->work_idx);
17
0
    MVM_repr_push_o(tc, t->body.queue, t->body.schedulee);
18
0
}
19
20
/* Sets the timer up on the event loop. */
21
0
static void setup(MVMThreadContext *tc, uv_loop_t *loop, MVMObject *async_task, void *data) {
22
0
    TimerInfo *ti = (TimerInfo *)data;
23
0
    uv_timer_init(loop, &ti->handle);
24
0
    ti->work_idx    = MVM_io_eventloop_add_active_work(tc, async_task);
25
0
    ti->tc          = tc;
26
0
    ti->handle.data = ti;
27
0
    uv_timer_start(&ti->handle, timer_cb, ti->timeout, ti->repeat);
28
0
}
29
30
/* Stops the timer. */
31
0
static void cancel(MVMThreadContext *tc, uv_loop_t *loop, MVMObject *async_task, void *data) {
32
0
    TimerInfo *ti = (TimerInfo *)data;
33
0
    uv_timer_stop(&ti->handle);
34
0
    MVM_io_eventloop_send_cancellation_notification(ti->tc,
35
0
        MVM_io_eventloop_get_active_work(tc, ti->work_idx));
36
0
    MVM_io_eventloop_remove_active_work(tc, &(ti->work_idx));
37
0
}
38
39
/* Frees data associated with a timer async task. */
40
0
static void gc_free(MVMThreadContext *tc, MVMObject *t, void *data) {
41
0
    if (data)
42
0
        MVM_free(data);
43
0
}
44
45
/* Operations table for async timer task. */
46
static const MVMAsyncTaskOps op_table = {
47
    setup,
48
    cancel,
49
    NULL,
50
    gc_free
51
};
52
53
/* Creates a new timer. */
54
MVMObject * MVM_io_timer_create(MVMThreadContext *tc, MVMObject *queue,
55
                                MVMObject *schedulee, MVMint64 timeout,
56
0
                                MVMint64 repeat, MVMObject *async_type) {
57
0
    MVMAsyncTask *task;
58
0
    TimerInfo *timer_info;
59
0
60
0
    /* Validate REPRs. */
61
0
    if (REPR(queue)->ID != MVM_REPR_ID_ConcBlockingQueue)
62
0
        MVM_exception_throw_adhoc(tc,
63
0
            "timer target queue must have ConcBlockingQueue REPR");
64
0
    if (REPR(async_type)->ID != MVM_REPR_ID_MVMAsyncTask)
65
0
        MVM_exception_throw_adhoc(tc,
66
0
            "timer result type must have REPR AsyncTask");
67
0
68
0
    /* Create async task handle. */
69
0
    MVMROOT(tc, queue, {
70
0
    MVMROOT(tc, schedulee, {
71
0
        task = (MVMAsyncTask *)MVM_repr_alloc_init(tc, async_type);
72
0
    });
73
0
    });
74
0
    MVM_ASSIGN_REF(tc, &(task->common.header), task->body.queue, queue);
75
0
    MVM_ASSIGN_REF(tc, &(task->common.header), task->body.schedulee, schedulee);
76
0
    task->body.ops      = &op_table;
77
0
    timer_info          = MVM_malloc(sizeof(TimerInfo));
78
0
    timer_info->timeout = timeout;
79
0
    timer_info->repeat  = repeat;
80
0
    task->body.data     = timer_info;
81
0
82
0
    /* Hand the task off to the event loop, which will set up the timer on the
83
0
     * event loop. */
84
0
    MVMROOT(tc, task, {
85
0
        MVM_io_eventloop_queue_work(tc, (MVMObject *)task);
86
0
    });
87
0
88
0
    return (MVMObject *)task;
89
0
}