nio4r 0.2.0 → 0.2.1
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.
- data/CHANGES.md +6 -0
- data/ext/nio4r/nio4r.h +2 -1
- data/ext/nio4r/selector.c +35 -8
- data/lib/nio/version.rb +1 -1
- metadata +7 -7
data/CHANGES.md
CHANGED
@@ -1,3 +1,9 @@
|
|
1
|
+
0.2.1
|
2
|
+
-----
|
3
|
+
* Implement wakeup mechanism using raw pipes instead of ev_async, since
|
4
|
+
ev_async likes to cause segvs when used across threads (despite claims
|
5
|
+
in the documentation to the contrary)
|
6
|
+
|
1
7
|
0.2.0
|
2
8
|
-----
|
3
9
|
* NIO::Monitor#readiness API to query readiness, along with #readable? and
|
data/ext/nio4r/nio4r.h
CHANGED
@@ -14,8 +14,9 @@ struct NIO_Selector
|
|
14
14
|
{
|
15
15
|
struct ev_loop *ev_loop;
|
16
16
|
struct ev_timer timer; /* for timeouts */
|
17
|
-
struct
|
17
|
+
struct ev_io wakeup;
|
18
18
|
|
19
|
+
int wakeup_reader, wakeup_writer;
|
19
20
|
int closed, selecting;
|
20
21
|
int ready_count;
|
21
22
|
int ready_buffer_size;
|
data/ext/nio4r/selector.c
CHANGED
@@ -5,6 +5,8 @@
|
|
5
5
|
|
6
6
|
#include "nio4r.h"
|
7
7
|
#include "rubysig.h"
|
8
|
+
#include <unistd.h>
|
9
|
+
#include <fcntl.h>
|
8
10
|
|
9
11
|
static VALUE mNIO = Qnil;
|
10
12
|
static VALUE cNIO_Channel = Qnil;
|
@@ -38,7 +40,7 @@ static VALUE NIO_Selector_select_each_synchronized(VALUE *args);
|
|
38
40
|
static int NIO_Selector_fill_ready_buffer(VALUE *args);
|
39
41
|
static VALUE NIO_Selector_run_evloop(void *ptr);
|
40
42
|
static void NIO_Selector_timeout_callback(struct ev_loop *ev_loop, struct ev_timer *timer, int revents);
|
41
|
-
static void NIO_Selector_wakeup_callback(struct ev_loop *ev_loop, struct
|
43
|
+
static void NIO_Selector_wakeup_callback(struct ev_loop *ev_loop, struct ev_io *io, int revents);
|
42
44
|
|
43
45
|
/* Default number of slots in the buffer for selected monitors */
|
44
46
|
#define INITIAL_READY_BUFFER 32
|
@@ -69,15 +71,33 @@ void Init_NIO_Selector()
|
|
69
71
|
/* Create the libev event loop and incoming event buffer */
|
70
72
|
static VALUE NIO_Selector_allocate(VALUE klass)
|
71
73
|
{
|
72
|
-
struct NIO_Selector *selector
|
74
|
+
struct NIO_Selector *selector;
|
75
|
+
int fds[2];
|
76
|
+
|
77
|
+
/* Use a pipe to implement the wakeup mechanism. I know libev provides
|
78
|
+
async watchers that implement this same behavior, but I'm getting
|
79
|
+
segvs trying to use that between threads, despite claims of thread
|
80
|
+
safety. Pipes are nice and safe to use between threads.
|
81
|
+
|
82
|
+
Note that Java NIO uses this same mechanism */
|
83
|
+
if(pipe(fds) < 0) {
|
84
|
+
rb_sys_fail("pipe");
|
85
|
+
}
|
86
|
+
|
87
|
+
if(fcntl(fds[0], F_SETFL, O_NONBLOCK) < 0) {
|
88
|
+
rb_sys_fail("fcntl");
|
89
|
+
}
|
73
90
|
|
91
|
+
selector = (struct NIO_Selector *)xmalloc(sizeof(struct NIO_Selector));
|
74
92
|
selector->ev_loop = ev_loop_new(0);
|
75
93
|
ev_init(&selector->timer, NIO_Selector_timeout_callback);
|
76
94
|
|
77
|
-
|
78
|
-
selector->
|
95
|
+
selector->wakeup_reader = fds[0];
|
96
|
+
selector->wakeup_writer = fds[1];
|
79
97
|
|
80
|
-
|
98
|
+
ev_io_init(&selector->wakeup, NIO_Selector_wakeup_callback, selector->wakeup_reader, EV_READ);
|
99
|
+
selector->wakeup.data = (void *)selector;
|
100
|
+
ev_io_start(selector->ev_loop, &selector->wakeup);
|
81
101
|
|
82
102
|
selector->closed = selector->selecting = selector->ready_count = 0;
|
83
103
|
selector->ready_buffer_size = INITIAL_READY_BUFFER;
|
@@ -104,6 +124,9 @@ static void NIO_Selector_shutdown(struct NIO_Selector *selector)
|
|
104
124
|
return;
|
105
125
|
}
|
106
126
|
|
127
|
+
close(selector->wakeup_reader);
|
128
|
+
close(selector->wakeup_writer);
|
129
|
+
|
107
130
|
selector->closed = 1;
|
108
131
|
}
|
109
132
|
|
@@ -383,7 +406,7 @@ static VALUE NIO_Selector_wakeup(VALUE self)
|
|
383
406
|
struct NIO_Selector *selector;
|
384
407
|
Data_Get_Struct(self, struct NIO_Selector, selector);
|
385
408
|
|
386
|
-
|
409
|
+
write(selector->wakeup_writer, "\0", 1);
|
387
410
|
|
388
411
|
return Qnil;
|
389
412
|
}
|
@@ -416,10 +439,14 @@ static void NIO_Selector_timeout_callback(struct ev_loop *ev_loop, struct ev_tim
|
|
416
439
|
}
|
417
440
|
|
418
441
|
/* Called whenever a wakeup request is sent to a selector */
|
419
|
-
static void NIO_Selector_wakeup_callback(struct ev_loop *ev_loop, struct
|
442
|
+
static void NIO_Selector_wakeup_callback(struct ev_loop *ev_loop, struct ev_io *io, int revents)
|
420
443
|
{
|
421
|
-
|
444
|
+
char buffer[128];
|
445
|
+
struct NIO_Selector *selector = (struct NIO_Selector *)io->data;
|
422
446
|
selector->selecting = 0;
|
447
|
+
|
448
|
+
/* Drain the wakeup pipe, giving us level-triggered behavior */
|
449
|
+
while(read(selector->wakeup_reader, buffer, 128) > 0);
|
423
450
|
}
|
424
451
|
|
425
452
|
/* This gets called from individual monitors. We must be careful here because
|
data/lib/nio/version.rb
CHANGED
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: nio4r
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.2.
|
4
|
+
version: 0.2.1
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -13,7 +13,7 @@ date: 2012-01-08 00:00:00.000000000 Z
|
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: rake-compiler
|
16
|
-
requirement: &
|
16
|
+
requirement: &70205623851360 !ruby/object:Gem::Requirement
|
17
17
|
none: false
|
18
18
|
requirements:
|
19
19
|
- - ~>
|
@@ -21,10 +21,10 @@ dependencies:
|
|
21
21
|
version: 0.7.9
|
22
22
|
type: :development
|
23
23
|
prerelease: false
|
24
|
-
version_requirements: *
|
24
|
+
version_requirements: *70205623851360
|
25
25
|
- !ruby/object:Gem::Dependency
|
26
26
|
name: rake
|
27
|
-
requirement: &
|
27
|
+
requirement: &70205623850800 !ruby/object:Gem::Requirement
|
28
28
|
none: false
|
29
29
|
requirements:
|
30
30
|
- - ! '>='
|
@@ -32,10 +32,10 @@ dependencies:
|
|
32
32
|
version: '0'
|
33
33
|
type: :development
|
34
34
|
prerelease: false
|
35
|
-
version_requirements: *
|
35
|
+
version_requirements: *70205623850800
|
36
36
|
- !ruby/object:Gem::Dependency
|
37
37
|
name: rspec
|
38
|
-
requirement: &
|
38
|
+
requirement: &70205623850040 !ruby/object:Gem::Requirement
|
39
39
|
none: false
|
40
40
|
requirements:
|
41
41
|
- - ~>
|
@@ -43,7 +43,7 @@ dependencies:
|
|
43
43
|
version: 2.7.0
|
44
44
|
type: :development
|
45
45
|
prerelease: false
|
46
|
-
version_requirements: *
|
46
|
+
version_requirements: *70205623850040
|
47
47
|
description: New IO for Ruby
|
48
48
|
email:
|
49
49
|
- tony.arcieri@gmail.com
|