nio4r 0.2.2-java → 0.3.0-java

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -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
+ }