nio4r 0.2.2 → 0.3.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,7 +1,7 @@
1
1
  /*
2
2
  * libev select fd activity backend
3
3
  *
4
- * Copyright (c) 2007,2008,2009,2010 Marc Alexander Lehmann <libev@schmorp.de>
4
+ * Copyright (c) 2007,2008,2009,2010,2011 Marc Alexander Lehmann <libev@schmorp.de>
5
5
  * All rights reserved.
6
6
  *
7
7
  * Redistribution and use in source and binary forms, with or without modifica-
@@ -195,7 +195,12 @@ select_poll (EV_P_ ev_tstamp timeout)
195
195
  */
196
196
  if (errno == EINVAL)
197
197
  {
198
- ev_sleep (timeout);
198
+ if (timeout)
199
+ {
200
+ unsigned long ms = timeout * 1e3;
201
+ Sleep (ms ? ms : 1);
202
+ }
203
+
199
204
  return;
200
205
  }
201
206
  #endif
@@ -269,9 +274,9 @@ select_poll (EV_P_ ev_tstamp timeout)
269
274
  int inline_size
270
275
  select_init (EV_P_ int flags)
271
276
  {
272
- backend_fudge = 0.; /* posix says this is zero */
273
- backend_modify = select_modify;
274
- backend_poll = select_poll;
277
+ backend_mintime = 1e-6;
278
+ backend_modify = select_modify;
279
+ backend_poll = select_poll;
275
280
 
276
281
  #if EV_SELECT_USE_FD_SET
277
282
  vec_ri = ev_malloc (sizeof (fd_set)); FD_ZERO ((fd_set *)vec_ri);
@@ -307,4 +312,3 @@ select_destroy (EV_P)
307
312
  #endif
308
313
  }
309
314
 
310
-
data/ext/libev/ev_vars.h CHANGED
@@ -51,7 +51,7 @@ VARx(int, activecnt) /* total number of active events ("refcount") */
51
51
  VARx(EV_ATOMIC_T, loop_done) /* signal by ev_break */
52
52
 
53
53
  VARx(int, backend_fd)
54
- VARx(ev_tstamp, backend_fudge) /* assumed typical timer resolution */
54
+ VARx(ev_tstamp, backend_mintime) /* assumed typical timer resolution */
55
55
  VAR (backend_modify, void (*backend_modify)(EV_P_ int fd, int oev, int nev))
56
56
  VAR (backend_poll , void (*backend_poll)(EV_P_ ev_tstamp timeout))
57
57
 
@@ -73,6 +73,8 @@ VARx(int, evfd)
73
73
  #endif
74
74
  VAR (evpipe, int evpipe [2])
75
75
  VARx(ev_io, pipe_w)
76
+ VARx(EV_ATOMIC_T, pipe_write_wanted)
77
+ VARx(EV_ATOMIC_T, pipe_write_skipped)
76
78
 
77
79
  #if !defined(_WIN32) || EV_GENWRAP
78
80
  VARx(pid_t, curpid)
@@ -180,7 +182,6 @@ VAR (fs_hash, ANFS fs_hash [EV_INOTIFY_HASHSIZE])
180
182
  #endif
181
183
 
182
184
  VARx(EV_ATOMIC_T, sig_pending)
183
- VARx(int, nosigmask)
184
185
  #if EV_USE_SIGNALFD || EV_GENWRAP
185
186
  VARx(int, sigfd)
186
187
  VARx(ev_io, sigfd_w)
data/ext/libev/ev_wrap.h CHANGED
@@ -10,7 +10,7 @@
10
10
  #define activecnt ((loop)->activecnt)
11
11
  #define loop_done ((loop)->loop_done)
12
12
  #define backend_fd ((loop)->backend_fd)
13
- #define backend_fudge ((loop)->backend_fudge)
13
+ #define backend_mintime ((loop)->backend_mintime)
14
14
  #define backend_modify ((loop)->backend_modify)
15
15
  #define backend_poll ((loop)->backend_poll)
16
16
  #define anfds ((loop)->anfds)
@@ -25,6 +25,8 @@
25
25
  #define evfd ((loop)->evfd)
26
26
  #define evpipe ((loop)->evpipe)
27
27
  #define pipe_w ((loop)->pipe_w)
28
+ #define pipe_write_wanted ((loop)->pipe_write_wanted)
29
+ #define pipe_write_skipped ((loop)->pipe_write_skipped)
28
30
  #define curpid ((loop)->curpid)
29
31
  #define postfork ((loop)->postfork)
30
32
  #define vec_ri ((loop)->vec_ri)
@@ -85,7 +87,6 @@
85
87
  #define fs_2625 ((loop)->fs_2625)
86
88
  #define fs_hash ((loop)->fs_hash)
87
89
  #define sig_pending ((loop)->sig_pending)
88
- #define nosigmask ((loop)->nosigmask)
89
90
  #define sigfd ((loop)->sigfd)
90
91
  #define sigfd_w ((loop)->sigfd_w)
91
92
  #define sigfd_set ((loop)->sigfd_set)
@@ -107,7 +108,7 @@
107
108
  #undef activecnt
108
109
  #undef loop_done
109
110
  #undef backend_fd
110
- #undef backend_fudge
111
+ #undef backend_mintime
111
112
  #undef backend_modify
112
113
  #undef backend_poll
113
114
  #undef anfds
@@ -122,6 +123,8 @@
122
123
  #undef evfd
123
124
  #undef evpipe
124
125
  #undef pipe_w
126
+ #undef pipe_write_wanted
127
+ #undef pipe_write_skipped
125
128
  #undef curpid
126
129
  #undef postfork
127
130
  #undef vec_ri
@@ -182,7 +185,6 @@
182
185
  #undef fs_2625
183
186
  #undef fs_hash
184
187
  #undef sig_pending
185
- #undef nosigmask
186
188
  #undef sigfd
187
189
  #undef sigfd_w
188
190
  #undef sigfd_set
data/ext/nio4r/monitor.c CHANGED
@@ -16,10 +16,11 @@ static void NIO_Monitor_free(struct NIO_Monitor *monitor);
16
16
 
17
17
  /* Methods */
18
18
  static VALUE NIO_Monitor_initialize(VALUE self, VALUE selector, VALUE io, VALUE interests);
19
- static VALUE NIO_Monitor_close(VALUE self);
19
+ static VALUE NIO_Monitor_close(int argc, VALUE *argv, VALUE self);
20
20
  static VALUE NIO_Monitor_is_closed(VALUE self);
21
21
  static VALUE NIO_Monitor_io(VALUE self);
22
22
  static VALUE NIO_Monitor_interests(VALUE self);
23
+ static VALUE NIO_Monitor_selector(VALUE self);
23
24
  static VALUE NIO_Monitor_is_readable(VALUE self);
24
25
  static VALUE NIO_Monitor_is_writable(VALUE self);
25
26
  static VALUE NIO_Monitor_value(VALUE self);
@@ -43,10 +44,11 @@ void Init_NIO_Monitor()
43
44
  rb_define_alloc_func(cNIO_Monitor, NIO_Monitor_allocate);
44
45
 
45
46
  rb_define_method(cNIO_Monitor, "initialize", NIO_Monitor_initialize, 3);
46
- rb_define_method(cNIO_Monitor, "close", NIO_Monitor_close, 0);
47
+ rb_define_method(cNIO_Monitor, "close", NIO_Monitor_close, -1);
47
48
  rb_define_method(cNIO_Monitor, "closed?", NIO_Monitor_is_closed, 0);
48
49
  rb_define_method(cNIO_Monitor, "io", NIO_Monitor_io, 0);
49
50
  rb_define_method(cNIO_Monitor, "interests", NIO_Monitor_interests, 0);
51
+ rb_define_method(cNIO_Monitor, "selector", NIO_Monitor_selector, 0);
50
52
  rb_define_method(cNIO_Monitor, "value", NIO_Monitor_value, 0);
51
53
  rb_define_method(cNIO_Monitor, "value=", NIO_Monitor_set_value, 1);
52
54
  rb_define_method(cNIO_Monitor, "readiness", NIO_Monitor_readiness, 0);
@@ -71,7 +73,7 @@ static void NIO_Monitor_free(struct NIO_Monitor *monitor)
71
73
  xfree(monitor);
72
74
  }
73
75
 
74
- static VALUE NIO_Monitor_initialize(VALUE self, VALUE selector_obj, VALUE io, VALUE interests)
76
+ static VALUE NIO_Monitor_initialize(VALUE self, VALUE io, VALUE interests, VALUE selector_obj)
75
77
  {
76
78
  struct NIO_Monitor *monitor;
77
79
  struct NIO_Selector *selector;
@@ -101,9 +103,9 @@ static VALUE NIO_Monitor_initialize(VALUE self, VALUE selector_obj, VALUE io, VA
101
103
  GetOpenFile(rb_convert_type(io, T_FILE, "IO", "to_io"), fptr);
102
104
  ev_io_init(&monitor->ev_io, NIO_Monitor_callback, FPTR_TO_FD(fptr), monitor->interests);
103
105
 
104
- rb_ivar_set(self, rb_intern("selector"), selector_obj);
105
106
  rb_ivar_set(self, rb_intern("io"), io);
106
107
  rb_ivar_set(self, rb_intern("interests"), interests);
108
+ rb_ivar_set(self, rb_intern("selector"), selector_obj);
107
109
 
108
110
  Data_Get_Struct(selector_obj, struct NIO_Selector, selector);
109
111
 
@@ -119,14 +121,24 @@ static VALUE NIO_Monitor_initialize(VALUE self, VALUE selector_obj, VALUE io, VA
119
121
  return Qnil;
120
122
  }
121
123
 
122
- static VALUE NIO_Monitor_close(VALUE self)
124
+ static VALUE NIO_Monitor_close(int argc, VALUE *argv, VALUE self)
123
125
  {
126
+ VALUE deregister, selector;
124
127
  struct NIO_Monitor *monitor;
125
128
  Data_Get_Struct(self, struct NIO_Monitor, monitor);
126
129
 
127
- if(monitor->selector) {
130
+ rb_scan_args(argc, argv, "01", &deregister);
131
+ selector = rb_ivar_get(self, rb_intern("selector"));
132
+
133
+ if(selector != Qnil) {
128
134
  ev_io_stop(monitor->selector->ev_loop, &monitor->ev_io);
129
135
  monitor->selector = 0;
136
+ rb_ivar_set(self, rb_intern("selector"), Qnil);
137
+
138
+ /* Default value is true */
139
+ if(deregister == Qtrue || deregister == Qnil) {
140
+ rb_funcall(selector, rb_intern("deregister"), 1, rb_ivar_get(self, rb_intern("io")));
141
+ }
130
142
  }
131
143
 
132
144
  return Qnil;
@@ -150,6 +162,11 @@ static VALUE NIO_Monitor_interests(VALUE self)
150
162
  return rb_ivar_get(self, rb_intern("interests"));
151
163
  }
152
164
 
165
+ static VALUE NIO_Monitor_selector(VALUE self)
166
+ {
167
+ return rb_ivar_get(self, rb_intern("selector"));
168
+ }
169
+
153
170
  static VALUE NIO_Monitor_value(VALUE self)
154
171
  {
155
172
  return rb_ivar_get(self, rb_intern("value"));
@@ -0,0 +1,409 @@
1
+ package org.nio4r;
2
+
3
+ import java.util.Iterator;
4
+ import java.io.IOException;
5
+ import java.nio.channels.Channel;
6
+ import java.nio.channels.SocketChannel;
7
+ import java.nio.channels.SelectableChannel;
8
+ import java.nio.channels.SelectionKey;
9
+ import org.jruby.Ruby;
10
+ import org.jruby.RubyModule;
11
+ import org.jruby.RubyClass;
12
+ import org.jruby.RubyObject;
13
+ import org.jruby.RubyIO;
14
+ import org.jruby.RubyNumeric;
15
+ import org.jruby.RubyArray;
16
+ import org.jruby.anno.JRubyMethod;
17
+ import org.jruby.runtime.ObjectAllocator;
18
+ import org.jruby.runtime.ThreadContext;
19
+ import org.jruby.runtime.load.Library;
20
+ import org.jruby.runtime.builtin.IRubyObject;
21
+ import org.jruby.runtime.Block;
22
+
23
+ public class Nio4r implements Library {
24
+ private Ruby ruby;
25
+
26
+ public void load(final Ruby ruby, boolean bln) {
27
+ this.ruby = ruby;
28
+
29
+ RubyModule nio = ruby.defineModule("NIO");
30
+
31
+ RubyClass selector = ruby.defineClassUnder("Selector", ruby.getObject(), new ObjectAllocator() {
32
+ public IRubyObject allocate(Ruby ruby, RubyClass rc) {
33
+ return new Selector(ruby, rc);
34
+ }
35
+ }, nio);
36
+
37
+ selector.defineAnnotatedMethods(Selector.class);
38
+
39
+ RubyClass monitor = ruby.defineClassUnder("Monitor", ruby.getObject(), new ObjectAllocator() {
40
+ public IRubyObject allocate(Ruby ruby, RubyClass rc) {
41
+ return new Monitor(ruby, rc);
42
+ }
43
+ }, nio);
44
+
45
+ monitor.defineAnnotatedMethods(Monitor.class);
46
+ }
47
+
48
+ public static int symbolToInterestOps(Ruby ruby, SelectableChannel channel, IRubyObject interest) {
49
+ if(interest == ruby.newSymbol("r")) {
50
+ if((channel.validOps() & SelectionKey.OP_ACCEPT) != 0) {
51
+ return SelectionKey.OP_ACCEPT;
52
+ } else {
53
+ return SelectionKey.OP_READ;
54
+ }
55
+ } else if(interest == ruby.newSymbol("w")) {
56
+ if(channel instanceof SocketChannel && !((SocketChannel)channel).isConnected()) {
57
+ return SelectionKey.OP_CONNECT;
58
+ } else {
59
+ return SelectionKey.OP_WRITE;
60
+ }
61
+ } else if(interest == ruby.newSymbol("rw")) {
62
+ int interestOps = 0;
63
+
64
+ /* nio4r emulates the POSIX behavior, which is sloppy about allowed modes */
65
+ if((channel.validOps() & (SelectionKey.OP_READ | SelectionKey.OP_ACCEPT)) != 0) {
66
+ interestOps |= symbolToInterestOps(ruby, channel, ruby.newSymbol("r"));
67
+ }
68
+
69
+ if((channel.validOps() & (SelectionKey.OP_WRITE | SelectionKey.OP_CONNECT)) != 0) {
70
+ interestOps |= symbolToInterestOps(ruby, channel, ruby.newSymbol("w"));
71
+ }
72
+
73
+ return interestOps;
74
+ } else {
75
+ throw ruby.newArgumentError("invalid interest type: " + interest);
76
+ }
77
+ }
78
+
79
+ public static IRubyObject interestOpsToSymbol(Ruby ruby, int interestOps) {
80
+ switch(interestOps) {
81
+ case SelectionKey.OP_READ:
82
+ case SelectionKey.OP_ACCEPT:
83
+ return ruby.newSymbol("r");
84
+ case SelectionKey.OP_WRITE:
85
+ case SelectionKey.OP_CONNECT:
86
+ return ruby.newSymbol("w");
87
+ case SelectionKey.OP_READ | SelectionKey.OP_CONNECT:
88
+ case SelectionKey.OP_READ | SelectionKey.OP_WRITE:
89
+ return ruby.newSymbol("rw");
90
+ default:
91
+ throw ruby.newArgumentError("unknown interest op combination");
92
+ }
93
+ }
94
+
95
+ public class Selector extends RubyObject {
96
+ private java.nio.channels.Selector selector;
97
+
98
+ public Selector(final Ruby ruby, RubyClass rubyClass) {
99
+ super(ruby, rubyClass);
100
+ }
101
+
102
+ @JRubyMethod
103
+ public IRubyObject initialize(ThreadContext context) {
104
+ try {
105
+ selector = java.nio.channels.Selector.open();
106
+ } catch(IOException ie) {
107
+ throw context.runtime.newIOError(ie.getLocalizedMessage());
108
+ }
109
+
110
+ return context.nil;
111
+ }
112
+
113
+ @JRubyMethod
114
+ public IRubyObject close(ThreadContext context) {
115
+ try {
116
+ selector.close();
117
+ } catch(IOException ie) {
118
+ throw context.runtime.newIOError(ie.getLocalizedMessage());
119
+ }
120
+
121
+ return context.nil;
122
+ }
123
+
124
+ @JRubyMethod(name = "closed?")
125
+ public IRubyObject isClosed(ThreadContext context) {
126
+ Ruby runtime = context.getRuntime();
127
+ return selector.isOpen() ? runtime.getFalse() : runtime.getTrue();
128
+ }
129
+
130
+ @JRubyMethod
131
+ public IRubyObject register(ThreadContext context, IRubyObject io, IRubyObject interests) {
132
+ Ruby runtime = context.getRuntime();
133
+ Channel raw_channel = RubyIO.convertToIO(context, io).getChannel();
134
+
135
+ if(!(raw_channel instanceof SelectableChannel)) {
136
+ throw runtime.newArgumentError("not a selectable IO object");
137
+ }
138
+
139
+ SelectableChannel channel = (SelectableChannel)raw_channel;
140
+
141
+ try {
142
+ channel.configureBlocking(false);
143
+ } catch(IOException ie) {
144
+ throw runtime.newIOError(ie.getLocalizedMessage());
145
+ }
146
+
147
+ int interestOps = Nio4r.symbolToInterestOps(runtime, channel, interests);
148
+ SelectionKey key;
149
+
150
+ try {
151
+ key = channel.register(selector, interestOps);
152
+ } catch(java.lang.IllegalArgumentException ia) {
153
+ throw runtime.newArgumentError("mode not supported for this object: " + interests);
154
+ } catch(java.nio.channels.ClosedChannelException cce) {
155
+ throw context.runtime.newIOError(cce.getLocalizedMessage());
156
+ }
157
+
158
+ RubyClass monitorClass = runtime.getModule("NIO").getClass("Monitor");
159
+ Monitor monitor = (Monitor)monitorClass.newInstance(context, io, interests, this, null);
160
+ monitor.setSelectionKey(key);
161
+
162
+ return monitor;
163
+ }
164
+
165
+ @JRubyMethod
166
+ public IRubyObject deregister(ThreadContext context, IRubyObject io) {
167
+ Ruby runtime = context.getRuntime();
168
+ Channel raw_channel = RubyIO.convertToIO(context, io).getChannel();
169
+
170
+ if(!(raw_channel instanceof SelectableChannel)) {
171
+ throw runtime.newArgumentError("not a selectable IO object");
172
+ }
173
+
174
+ SelectableChannel channel = (SelectableChannel)raw_channel;
175
+ SelectionKey key = channel.keyFor(selector);
176
+
177
+ if(key == null)
178
+ return context.nil;
179
+
180
+ Monitor monitor = (Monitor)key.attachment();
181
+ monitor.close(context);
182
+
183
+ return monitor;
184
+ }
185
+
186
+ @JRubyMethod(name = "registered?")
187
+ public IRubyObject isRegistered(ThreadContext context, IRubyObject io) {
188
+ Ruby runtime = context.getRuntime();
189
+ Channel raw_channel = RubyIO.convertToIO(context, io).getChannel();
190
+
191
+ if(!(raw_channel instanceof SelectableChannel)) {
192
+ throw runtime.newArgumentError("not a selectable IO object");
193
+ }
194
+
195
+ SelectableChannel channel = (SelectableChannel)raw_channel;
196
+ SelectionKey key = channel.keyFor(selector);
197
+
198
+ if(key == null)
199
+ return context.nil;
200
+
201
+
202
+ if(((Monitor)key.attachment()).isClosed(context) == runtime.getTrue()) {
203
+ return runtime.getFalse();
204
+ } else {
205
+ return runtime.getTrue();
206
+ }
207
+ }
208
+
209
+ @JRubyMethod
210
+ public synchronized IRubyObject select(ThreadContext context, Block block) {
211
+ return select(context, context.nil, block);
212
+ }
213
+
214
+ @JRubyMethod
215
+ public synchronized IRubyObject select(ThreadContext context, IRubyObject timeout, Block block) {
216
+ Ruby runtime = context.getRuntime();
217
+ int ready = doSelect(runtime, timeout);
218
+
219
+ /* Timeout or wakeup */
220
+ if(ready <= 0)
221
+ return context.nil;
222
+
223
+ RubyArray array = null;
224
+ if(!block.isGiven()) {
225
+ array = runtime.newArray(selector.selectedKeys().size());
226
+ }
227
+
228
+ Iterator selectedKeys = selector.selectedKeys().iterator();
229
+ while (selectedKeys.hasNext()) {
230
+ SelectionKey key = (SelectionKey)selectedKeys.next();
231
+ processKey(key);
232
+ selectedKeys.remove();
233
+
234
+ if(block.isGiven()) {
235
+ block.call(context, (IRubyObject)key.attachment());
236
+ } else {
237
+ array.add(key.attachment());
238
+ }
239
+ }
240
+
241
+ if(block.isGiven()) {
242
+ return RubyNumeric.int2fix(runtime, ready);
243
+ } else {
244
+ return array;
245
+ }
246
+ }
247
+
248
+ @JRubyMethod
249
+ public synchronized IRubyObject select_each(ThreadContext context, Block block) {
250
+ return select_each(context, context.nil, block);
251
+ }
252
+
253
+ @JRubyMethod
254
+ public synchronized IRubyObject select_each(ThreadContext context, IRubyObject timeout, Block block) {
255
+ Ruby runtime = context.getRuntime();
256
+ int ready = doSelect(runtime, timeout);
257
+
258
+ /* Timeout or wakeup */
259
+ if(ready <= 0)
260
+ return context.nil;
261
+
262
+ Iterator selectedKeys = selector.selectedKeys().iterator();
263
+ while (selectedKeys.hasNext()) {
264
+ SelectionKey key = (SelectionKey)selectedKeys.next();
265
+ processKey(key);
266
+ selectedKeys.remove();
267
+ block.call(context, (IRubyObject)key.attachment());
268
+ }
269
+
270
+ return context.nil;
271
+ }
272
+
273
+ private int doSelect(Ruby runtime, IRubyObject timeout) {
274
+ try {
275
+ if(timeout.isNil()) {
276
+ return selector.select();
277
+ } else {
278
+ double t = RubyNumeric.num2dbl(timeout);
279
+ if(t == 0) {
280
+ return selector.selectNow();
281
+ } else if(t < 0) {
282
+ throw runtime.newArgumentError("time interval must be positive");
283
+ } else {
284
+ return selector.select((long)(t * 1000));
285
+ }
286
+ }
287
+ } catch(IOException ie) {
288
+ throw runtime.newIOError(ie.getLocalizedMessage());
289
+ }
290
+ }
291
+
292
+ // Remove connect interest from connected sockets
293
+ // See: http://stackoverflow.com/questions/204186/java-nio-select-returns-without-selected-keys-why
294
+ private void processKey(SelectionKey key) {
295
+ if((key.readyOps() & SelectionKey.OP_CONNECT) != 0) {
296
+ int interestOps = key.interestOps();
297
+
298
+ interestOps &= ~SelectionKey.OP_CONNECT;
299
+ interestOps |= SelectionKey.OP_WRITE;
300
+
301
+ key.interestOps(interestOps);
302
+ }
303
+ }
304
+
305
+ @JRubyMethod
306
+ public IRubyObject wakeup(ThreadContext context) {
307
+ if(!selector.isOpen()) {
308
+ throw context.getRuntime().newIOError("selector is closed");
309
+ }
310
+
311
+ selector.wakeup();
312
+ return context.nil;
313
+ }
314
+ }
315
+
316
+ public class Monitor extends RubyObject {
317
+ private SelectionKey key;
318
+ private RubyIO io;
319
+ private IRubyObject interests, selector, value, closed;
320
+
321
+ public Monitor(final Ruby ruby, RubyClass rubyClass) {
322
+ super(ruby, rubyClass);
323
+ }
324
+
325
+ @JRubyMethod
326
+ public IRubyObject initialize(ThreadContext context, IRubyObject selectable, IRubyObject interests, IRubyObject selector) {
327
+ this.io = RubyIO.convertToIO(context, selectable);
328
+ this.interests = interests;
329
+ this.selector = selector;
330
+
331
+ value = context.nil;
332
+ closed = context.getRuntime().getFalse();
333
+
334
+ return context.nil;
335
+ }
336
+
337
+ public void setSelectionKey(SelectionKey k) {
338
+ key = k;
339
+ key.attach(this);
340
+ }
341
+
342
+ @JRubyMethod
343
+ public IRubyObject io(ThreadContext context) {
344
+ return io;
345
+ }
346
+
347
+ @JRubyMethod
348
+ public IRubyObject selector(ThreadContext context) {
349
+ return selector;
350
+ }
351
+
352
+ @JRubyMethod
353
+ public IRubyObject interests(ThreadContext context) {
354
+ return interests;
355
+ }
356
+
357
+ @JRubyMethod
358
+ public IRubyObject readiness(ThreadContext context) {
359
+ return Nio4r.interestOpsToSymbol(context.getRuntime(), key.readyOps());
360
+ }
361
+
362
+ @JRubyMethod(name = "readable?")
363
+ public IRubyObject isReadable(ThreadContext context) {
364
+ Ruby runtime = context.getRuntime();
365
+ int readyOps = key.readyOps();
366
+
367
+ if((readyOps & SelectionKey.OP_READ) != 0 || (readyOps & SelectionKey.OP_ACCEPT) != 0) {
368
+ return runtime.getTrue();
369
+ } else {
370
+ return runtime.getFalse();
371
+ }
372
+ }
373
+
374
+ @JRubyMethod(name = {"writable?", "writeable?"})
375
+ public IRubyObject writable(ThreadContext context) {
376
+ Ruby runtime = context.getRuntime();
377
+ int readyOps = key.readyOps();
378
+
379
+ if((readyOps & SelectionKey.OP_WRITE) != 0 || (readyOps & SelectionKey.OP_CONNECT) != 0) {
380
+ return runtime.getTrue();
381
+ } else {
382
+ return runtime.getFalse();
383
+ }
384
+ }
385
+
386
+ @JRubyMethod(name = "value")
387
+ public IRubyObject getValue(ThreadContext context) {
388
+ return value;
389
+ }
390
+
391
+ @JRubyMethod(name = "value=")
392
+ public IRubyObject setValue(ThreadContext context, IRubyObject obj) {
393
+ value = obj;
394
+ return context.nil;
395
+ }
396
+
397
+ @JRubyMethod
398
+ public IRubyObject close(ThreadContext context) {
399
+ key.cancel();
400
+ closed = context.getRuntime().getTrue();
401
+ return context.nil;
402
+ }
403
+
404
+ @JRubyMethod(name = "closed?")
405
+ public IRubyObject isClosed(ThreadContext context) {
406
+ return closed;
407
+ }
408
+ }
409
+ }