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 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217
|
/*
* Copyright (c) 2011 Tony Arcieri. Distributed under the MIT License. See
* LICENSE.txt for further details.
*/
#include "nio4r.h"
static VALUE mNIO = Qnil;
static VALUE cNIO_Monitor = Qnil;
/* Allocator/deallocator */
static VALUE NIO_Monitor_allocate(VALUE klass);
static void NIO_Monitor_mark(struct NIO_Monitor *monitor);
static void NIO_Monitor_free(struct NIO_Monitor *monitor);
/* Methods */
static VALUE NIO_Monitor_initialize(VALUE self, VALUE selector, VALUE io, VALUE interests);
static VALUE NIO_Monitor_close(int argc, VALUE *argv, VALUE self);
static VALUE NIO_Monitor_is_closed(VALUE self);
static VALUE NIO_Monitor_io(VALUE self);
static VALUE NIO_Monitor_interests(VALUE self);
static VALUE NIO_Monitor_selector(VALUE self);
static VALUE NIO_Monitor_is_readable(VALUE self);
static VALUE NIO_Monitor_is_writable(VALUE self);
static VALUE NIO_Monitor_value(VALUE self);
static VALUE NIO_Monitor_set_value(VALUE self, VALUE obj);
static VALUE NIO_Monitor_readiness(VALUE self);
/* Internal functions */
static void NIO_Monitor_callback(struct ev_loop *ev_loop, struct ev_io *io, int revents);
#if HAVE_RB_IO_T
rb_io_t *fptr;
#else
OpenFile *fptr;
#endif
/* Monitor control how a channel is being waited for by a monitor */
void Init_NIO_Monitor()
{
mNIO = rb_define_module("NIO");
cNIO_Monitor = rb_define_class_under(mNIO, "Monitor", rb_cObject);
rb_define_alloc_func(cNIO_Monitor, NIO_Monitor_allocate);
rb_define_method(cNIO_Monitor, "initialize", NIO_Monitor_initialize, 3);
rb_define_method(cNIO_Monitor, "close", NIO_Monitor_close, -1);
rb_define_method(cNIO_Monitor, "closed?", NIO_Monitor_is_closed, 0);
rb_define_method(cNIO_Monitor, "io", NIO_Monitor_io, 0);
rb_define_method(cNIO_Monitor, "interests", NIO_Monitor_interests, 0);
rb_define_method(cNIO_Monitor, "selector", NIO_Monitor_selector, 0);
rb_define_method(cNIO_Monitor, "value", NIO_Monitor_value, 0);
rb_define_method(cNIO_Monitor, "value=", NIO_Monitor_set_value, 1);
rb_define_method(cNIO_Monitor, "readiness", NIO_Monitor_readiness, 0);
rb_define_method(cNIO_Monitor, "readable?", NIO_Monitor_is_readable, 0);
rb_define_method(cNIO_Monitor, "writable?", NIO_Monitor_is_writable, 0);
rb_define_method(cNIO_Monitor, "writeable?", NIO_Monitor_is_writable, 0);
}
static VALUE NIO_Monitor_allocate(VALUE klass)
{
struct NIO_Monitor *monitor = (struct NIO_Monitor *)xmalloc(sizeof(struct NIO_Monitor));
return Data_Wrap_Struct(klass, NIO_Monitor_mark, NIO_Monitor_free, monitor);
}
static void NIO_Monitor_mark(struct NIO_Monitor *monitor)
{
}
static void NIO_Monitor_free(struct NIO_Monitor *monitor)
{
xfree(monitor);
}
static VALUE NIO_Monitor_initialize(VALUE self, VALUE io, VALUE interests, VALUE selector_obj)
{
struct NIO_Monitor *monitor;
struct NIO_Selector *selector;
ID interests_id;
#if HAVE_RB_IO_T
rb_io_t *fptr;
#else
OpenFile *fptr;
#endif
interests_id = SYM2ID(interests);
Data_Get_Struct(self, struct NIO_Monitor, monitor);
if(interests_id == rb_intern("r")) {
monitor->interests = EV_READ;
} else if(interests_id == rb_intern("w")) {
monitor->interests = EV_WRITE;
} else if(interests_id == rb_intern("rw")) {
monitor->interests = EV_READ | EV_WRITE;
} else {
rb_raise(rb_eArgError, "invalid event type %s (must be :r, :w, or :rw)",
RSTRING_PTR(rb_funcall(interests, rb_intern("inspect"), 0, 0)));
}
GetOpenFile(rb_convert_type(io, T_FILE, "IO", "to_io"), fptr);
ev_io_init(&monitor->ev_io, NIO_Selector_monitor_callback, FPTR_TO_FD(fptr), monitor->interests);
rb_ivar_set(self, rb_intern("io"), io);
rb_ivar_set(self, rb_intern("interests"), interests);
rb_ivar_set(self, rb_intern("selector"), selector_obj);
Data_Get_Struct(selector_obj, struct NIO_Selector, selector);
monitor->self = self;
monitor->ev_io.data = (void *)monitor;
/* We can safely hang onto this as we also hang onto a reference to the
object where it originally came from */
monitor->selector = selector;
ev_io_start(selector->ev_loop, &monitor->ev_io);
return Qnil;
}
static VALUE NIO_Monitor_close(int argc, VALUE *argv, VALUE self)
{
VALUE deregister, selector;
struct NIO_Monitor *monitor;
Data_Get_Struct(self, struct NIO_Monitor, monitor);
rb_scan_args(argc, argv, "01", &deregister);
selector = rb_ivar_get(self, rb_intern("selector"));
if(selector != Qnil) {
ev_io_stop(monitor->selector->ev_loop, &monitor->ev_io);
monitor->selector = 0;
rb_ivar_set(self, rb_intern("selector"), Qnil);
/* Default value is true */
if(deregister == Qtrue || deregister == Qnil) {
rb_funcall(selector, rb_intern("deregister"), 1, rb_ivar_get(self, rb_intern("io")));
}
}
return Qnil;
}
static VALUE NIO_Monitor_is_closed(VALUE self)
{
struct NIO_Monitor *monitor;
Data_Get_Struct(self, struct NIO_Monitor, monitor);
return !monitor->selector;
}
static VALUE NIO_Monitor_io(VALUE self)
{
return rb_ivar_get(self, rb_intern("io"));
}
static VALUE NIO_Monitor_interests(VALUE self)
{
return rb_ivar_get(self, rb_intern("interests"));
}
static VALUE NIO_Monitor_selector(VALUE self)
{
return rb_ivar_get(self, rb_intern("selector"));
}
static VALUE NIO_Monitor_value(VALUE self)
{
return rb_ivar_get(self, rb_intern("value"));
}
static VALUE NIO_Monitor_set_value(VALUE self, VALUE obj)
{
return rb_ivar_set(self, rb_intern("value"), obj);
}
static VALUE NIO_Monitor_readiness(VALUE self)
{
struct NIO_Monitor *monitor;
Data_Get_Struct(self, struct NIO_Monitor, monitor);
if((monitor->revents & (EV_READ | EV_WRITE)) == (EV_READ | EV_WRITE)) {
return ID2SYM(rb_intern("rw"));
} else if(monitor->revents & EV_READ) {
return ID2SYM(rb_intern("r"));
} else if(monitor->revents & EV_WRITE) {
return ID2SYM(rb_intern("w"));
} else {
return Qnil;
}
}
static VALUE NIO_Monitor_is_readable(VALUE self)
{
struct NIO_Monitor *monitor;
Data_Get_Struct(self, struct NIO_Monitor, monitor);
if(monitor->revents & EV_READ) {
return Qtrue;
} else {
return Qfalse;
}
}
static VALUE NIO_Monitor_is_writable(VALUE self)
{
struct NIO_Monitor *monitor;
Data_Get_Struct(self, struct NIO_Monitor, monitor);
if(monitor->revents & EV_WRITE) {
return Qtrue;
} else {
return Qfalse;
}
}
|