summaryrefslogtreecommitdiff
path: root/scheduler.c
blob: d7e713a7109c1ae6384ca14419daec35d6afcd7b (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
/**********************************************************************

  scheduler.c

  $Author$

  Copyright (C) 2020 Samuel Grant Dawson Williams

**********************************************************************/

#include "internal/scheduler.h"
#include "ruby/io.h"

static ID id_close;

static ID id_block;
static ID id_unblock;

static ID id_kernel_sleep;

static ID id_io_read;
static ID id_io_write;
static ID id_io_wait;

void
Init_Scheduler(void)
{
    id_close = rb_intern_const("close");

    id_block = rb_intern_const("block");
    id_unblock = rb_intern_const("unblock");

    id_kernel_sleep = rb_intern_const("kernel_sleep");

    id_io_read = rb_intern_const("io_read");
    id_io_write = rb_intern_const("io_write");
    id_io_wait = rb_intern_const("io_wait");
}

VALUE
rb_scheduler_close(VALUE scheduler)
{
    if (rb_respond_to(scheduler, id_close)) {
        return rb_funcall(scheduler, id_close, 0);
    }

    return Qnil;
}

VALUE
rb_scheduler_timeout(struct timeval *timeout)
{
    if (timeout) {
        return rb_float_new((double)timeout->tv_sec + (0.000001f * timeout->tv_usec));
    }

    return Qnil;
}

VALUE
rb_scheduler_kernel_sleep(VALUE scheduler, VALUE timeout)
{
    return rb_funcall(scheduler, id_kernel_sleep, 1, timeout);
}

VALUE
rb_scheduler_kernel_sleepv(VALUE scheduler, int argc, VALUE * argv)
{
    return rb_funcallv(scheduler, id_kernel_sleep, argc, argv);
}

VALUE
rb_scheduler_block(VALUE scheduler, VALUE blocker, VALUE timeout)
{
    return rb_funcall(scheduler, id_block, 2, blocker, timeout);
}

VALUE
rb_scheduler_unblock(VALUE scheduler, VALUE blocker, VALUE fiber)
{
    return rb_funcall(scheduler, id_unblock, 2, blocker, fiber);
}

VALUE
rb_scheduler_io_wait(VALUE scheduler, VALUE io, VALUE events, VALUE timeout)
{
    return rb_funcall(scheduler, id_io_wait, 3, io, events, timeout);
}

VALUE
rb_scheduler_io_wait_readable(VALUE scheduler, VALUE io)
{
    return rb_scheduler_io_wait(scheduler, io, RB_UINT2NUM(RUBY_IO_READABLE), Qnil);
}

VALUE
rb_scheduler_io_wait_writable(VALUE scheduler, VALUE io)
{
    return rb_scheduler_io_wait(scheduler, io, RB_UINT2NUM(RUBY_IO_WRITABLE), Qnil);
}

int
rb_scheduler_supports_io_read(VALUE scheduler)
{
    return rb_respond_to(scheduler, id_io_read);
}

VALUE
rb_scheduler_io_read(VALUE scheduler, VALUE io, VALUE buffer, size_t offset, size_t length)
{
    return rb_funcall(scheduler, id_io_read, 4, io, buffer, SIZET2NUM(offset), SIZET2NUM(length));
}

int
rb_scheduler_supports_io_write(VALUE scheduler)
{
    return rb_respond_to(scheduler, id_io_write);
}

VALUE
rb_scheduler_io_write(VALUE scheduler, VALUE io, VALUE buffer, size_t offset, size_t length)
{
    // We should ensure string has capacity to receive data, and then resize it afterwards.
    return rb_funcall(scheduler, id_io_write, 4, io, buffer, SIZET2NUM(offset), SIZET2NUM(length));
}