cool.io 1.2.0 → 1.2.1
Sign up to get free protection for your applications and to get access to all the features.
- data/.travis.yml +9 -2
- data/CHANGES.md +7 -0
- data/Gemfile +1 -1
- data/ext/cool.io/loop.c +1 -12
- data/ext/libev/ev.c +68 -0
- data/ext/libev/ruby_gil.patch +97 -0
- data/lib/cool.io/listener.rb +9 -3
- data/lib/cool.io/server.rb +2 -1
- data/lib/cool.io/version.rb +1 -1
- data/spec/unix_server_spec.rb +3 -1
- metadata +5 -4
data/.travis.yml
CHANGED
data/CHANGES.md
CHANGED
@@ -1,9 +1,16 @@
|
|
1
|
+
1.2.1
|
2
|
+
-----
|
3
|
+
|
4
|
+
* Release the GIL when libev polls (#24)
|
5
|
+
* Add Listener#listen method to change backlog size
|
6
|
+
|
1
7
|
1.2.0
|
2
8
|
-----
|
3
9
|
|
4
10
|
* Support Windows environment via cross compilation
|
5
11
|
* Include iobuffer library
|
6
12
|
* Update to libev 4.15
|
13
|
+
* Remove Ruby 1.8 support
|
7
14
|
|
8
15
|
1.1.0
|
9
16
|
-----
|
data/Gemfile
CHANGED
data/ext/cool.io/loop.c
CHANGED
@@ -205,23 +205,12 @@ static VALUE Coolio_Loop_run_once(VALUE self)
|
|
205
205
|
return nevents;
|
206
206
|
}
|
207
207
|
|
208
|
-
/* Ruby 1.9 supports blocking system calls through rb_thread_blocking_region() */
|
209
208
|
#ifdef HAVE_RB_THREAD_BLOCKING_REGION
|
210
209
|
#define HAVE_EV_LOOP_ONESHOT
|
211
|
-
static VALUE Coolio_Loop_ev_loop_oneshot_blocking(void *ptr)
|
212
|
-
{
|
213
|
-
/* The libev loop has now escaped through the Global VM Lock unscathed! */
|
214
|
-
struct Coolio_Loop *loop_data = (struct Coolio_Loop *)ptr;
|
215
|
-
|
216
|
-
RUN_LOOP(loop_data, EVLOOP_ONESHOT);
|
217
|
-
|
218
|
-
return Qnil;
|
219
|
-
}
|
220
210
|
|
221
211
|
static void Coolio_Loop_ev_loop_oneshot(struct Coolio_Loop *loop_data)
|
222
212
|
{
|
223
|
-
|
224
|
-
rb_thread_blocking_region(Coolio_Loop_ev_loop_oneshot_blocking, loop_data, RUBY_UBF_IO, 0);
|
213
|
+
RUN_LOOP(loop_data, EVLOOP_ONESHOT);
|
225
214
|
}
|
226
215
|
#endif
|
227
216
|
|
data/ext/libev/ev.c
CHANGED
@@ -37,6 +37,10 @@
|
|
37
37
|
* either the BSD or the GPL.
|
38
38
|
*/
|
39
39
|
|
40
|
+
/* ########## COOLIO PATCHERY HO! ########## */
|
41
|
+
#include "ruby.h"
|
42
|
+
/* ######################################## */
|
43
|
+
|
40
44
|
/* this big block deduces configuration from config.h */
|
41
45
|
#ifndef EV_STANDALONE
|
42
46
|
# ifdef EV_CONFIG_H
|
@@ -3237,9 +3241,27 @@ time_update (EV_P_ ev_tstamp max_block)
|
|
3237
3241
|
}
|
3238
3242
|
}
|
3239
3243
|
|
3244
|
+
/* ########## COOLIO PATCHERY HO! ########## */
|
3245
|
+
#if defined(HAVE_RB_THREAD_BLOCKING_REGION)
|
3246
|
+
static
|
3247
|
+
VALUE ev_backend_poll(void **args)
|
3248
|
+
{
|
3249
|
+
struct ev_loop *loop = (struct ev_loop *)args[0];
|
3250
|
+
ev_tstamp waittime = *(ev_tstamp *)args[1];
|
3251
|
+
backend_poll (EV_A_ waittime);
|
3252
|
+
}
|
3253
|
+
#endif
|
3254
|
+
/* ######################################## */
|
3255
|
+
|
3240
3256
|
int
|
3241
3257
|
ev_run (EV_P_ int flags)
|
3242
3258
|
{
|
3259
|
+
/* ########## COOLIO PATCHERY HO! ########## */
|
3260
|
+
#if defined(HAVE_RB_THREAD_BLOCKING_REGION)
|
3261
|
+
void *poll_args[2];
|
3262
|
+
#endif
|
3263
|
+
/* ######################################## */
|
3264
|
+
|
3243
3265
|
#if EV_FEATURE_API
|
3244
3266
|
++loop_depth;
|
3245
3267
|
#endif
|
@@ -3357,7 +3379,53 @@ ev_run (EV_P_ int flags)
|
|
3357
3379
|
++loop_count;
|
3358
3380
|
#endif
|
3359
3381
|
assert ((loop_done = EVBREAK_RECURSE, 1)); /* assert for side effect */
|
3382
|
+
|
3383
|
+
/*
|
3384
|
+
########################## COOLIO PATCHERY HO! ##########################
|
3385
|
+
|
3386
|
+
The original patch file is made by Tony Arcieri.
|
3387
|
+
https://github.com/celluloid/nio4r/blob/680143345726c5a64bb22376ca8fc3c6857019ae/ext/libev/ruby_gil.patch.
|
3388
|
+
|
3389
|
+
According to the grandwizards of Ruby, locking and unlocking of the global
|
3390
|
+
interpreter lock are apparently too powerful a concept for a mere mortal to
|
3391
|
+
wield (although redefining what + and - do to numbers is totally cool).
|
3392
|
+
And so it came to pass that the only acceptable way to release the global
|
3393
|
+
interpreter lock is through a convoluted callback system that thakes a
|
3394
|
+
function pointer. While the grandwizard of libev foresaw this sort of scenario,
|
3395
|
+
he too attempted to place an API with callbacks on it, one that runs before
|
3396
|
+
the system call, and one that runs immediately after.
|
3397
|
+
|
3398
|
+
And so it came to pass that trying to wrap everything up in callbacks created
|
3399
|
+
two incompatible APIs, Ruby's which releases the global interpreter lock and
|
3400
|
+
reacquires it when the callback returns, and libev's, which wants two
|
3401
|
+
callbacks, one which runs before the polling operation starts, and one which
|
3402
|
+
runs after it finishes.
|
3403
|
+
|
3404
|
+
These two systems are incompatible as they both want to use callbacks to
|
3405
|
+
solve the same problem, however libev wants to use before/after callbacks,
|
3406
|
+
and Ruby wants to use an "around" callback. This presents a significant
|
3407
|
+
problem as these two patterns of callbacks are diametrical opposites of each
|
3408
|
+
other and thus cannot be composed.
|
3409
|
+
|
3410
|
+
And thus we are left with no choice but to patch the internals of libev in
|
3411
|
+
order to release a mutex at just the precise moment.
|
3412
|
+
|
3413
|
+
Let this be a lesson to the all: CALLBACKS FUCKING BLOW
|
3414
|
+
|
3415
|
+
#######################################################################
|
3416
|
+
*/
|
3417
|
+
|
3418
|
+
#if defined(HAVE_RB_THREAD_BLOCKING_REGION)
|
3419
|
+
poll_args[0] = (void *)loop;
|
3420
|
+
poll_args[1] = (void *)&waittime;
|
3421
|
+
rb_thread_blocking_region(ev_backend_poll, (void *)&poll_args, RUBY_UBF_IO, 0);
|
3422
|
+
#else
|
3360
3423
|
backend_poll (EV_A_ waittime);
|
3424
|
+
#endif
|
3425
|
+
/*
|
3426
|
+
############################# END PATCHERY ############################
|
3427
|
+
*/
|
3428
|
+
|
3361
3429
|
assert ((loop_done = EVBREAK_CANCEL, 1)); /* assert for side effect */
|
3362
3430
|
|
3363
3431
|
pipe_write_wanted = 0; /* just an optimisation, no fence needed */
|
@@ -0,0 +1,97 @@
|
|
1
|
+
diff --git a/ext/libev/ev.c b/ext/libev/ev.c
|
2
|
+
index e5bd5ab..10f6ff2 100644
|
3
|
+
--- a/ext/libev/ev.c
|
4
|
+
+++ b/ext/libev/ev.c
|
5
|
+
@@ -37,6 +37,10 @@
|
6
|
+
* either the BSD or the GPL.
|
7
|
+
*/
|
8
|
+
|
9
|
+
+/* ########## COOLIO PATCHERY HO! ########## */
|
10
|
+
+#include "ruby.h"
|
11
|
+
+/* ######################################## */
|
12
|
+
+
|
13
|
+
/* this big block deduces configuration from config.h */
|
14
|
+
#ifndef EV_STANDALONE
|
15
|
+
# ifdef EV_CONFIG_H
|
16
|
+
@@ -3237,9 +3241,27 @@ time_update (EV_P_ ev_tstamp max_block)
|
17
|
+
}
|
18
|
+
}
|
19
|
+
|
20
|
+
+/* ########## COOLIO PATCHERY HO! ########## */
|
21
|
+
+#if defined(HAVE_RB_THREAD_BLOCKING_REGION)
|
22
|
+
+static
|
23
|
+
+VALUE ev_backend_poll(void **args)
|
24
|
+
+{
|
25
|
+
+ struct ev_loop *loop = (struct ev_loop *)args[0];
|
26
|
+
+ ev_tstamp waittime = *(ev_tstamp *)args[1];
|
27
|
+
+ backend_poll (EV_A_ waittime);
|
28
|
+
+}
|
29
|
+
+#endif
|
30
|
+
+/* ######################################## */
|
31
|
+
+
|
32
|
+
int
|
33
|
+
ev_run (EV_P_ int flags)
|
34
|
+
{
|
35
|
+
+/* ########## COOLIO PATCHERY HO! ########## */
|
36
|
+
+#if defined(HAVE_RB_THREAD_BLOCKING_REGION)
|
37
|
+
+ void *poll_args[2];
|
38
|
+
+#endif
|
39
|
+
+/* ######################################## */
|
40
|
+
+
|
41
|
+
#if EV_FEATURE_API
|
42
|
+
++loop_depth;
|
43
|
+
#endif
|
44
|
+
@@ -3357,7 +3379,53 @@ ev_run (EV_P_ int flags)
|
45
|
+
++loop_count;
|
46
|
+
#endif
|
47
|
+
assert ((loop_done = EVBREAK_RECURSE, 1)); /* assert for side effect */
|
48
|
+
+
|
49
|
+
+/*
|
50
|
+
+########################## COOLIO PATCHERY HO! ##########################
|
51
|
+
+
|
52
|
+
+The original patch file is made by Tony Arcieri.
|
53
|
+
+https://github.com/celluloid/nio4r/blob/680143345726c5a64bb22376ca8fc3c6857019ae/ext/libev/ruby_gil.patch.
|
54
|
+
+
|
55
|
+
+According to the grandwizards of Ruby, locking and unlocking of the global
|
56
|
+
+interpreter lock are apparently too powerful a concept for a mere mortal to
|
57
|
+
+wield (although redefining what + and - do to numbers is totally cool).
|
58
|
+
+And so it came to pass that the only acceptable way to release the global
|
59
|
+
+interpreter lock is through a convoluted callback system that thakes a
|
60
|
+
+function pointer. While the grandwizard of libev foresaw this sort of scenario,
|
61
|
+
+he too attempted to place an API with callbacks on it, one that runs before
|
62
|
+
+the system call, and one that runs immediately after.
|
63
|
+
+
|
64
|
+
+And so it came to pass that trying to wrap everything up in callbacks created
|
65
|
+
+two incompatible APIs, Ruby's which releases the global interpreter lock and
|
66
|
+
+reacquires it when the callback returns, and libev's, which wants two
|
67
|
+
+callbacks, one which runs before the polling operation starts, and one which
|
68
|
+
+runs after it finishes.
|
69
|
+
+
|
70
|
+
+These two systems are incompatible as they both want to use callbacks to
|
71
|
+
+solve the same problem, however libev wants to use before/after callbacks,
|
72
|
+
+and Ruby wants to use an "around" callback. This presents a significant
|
73
|
+
+problem as these two patterns of callbacks are diametrical opposites of each
|
74
|
+
+other and thus cannot be composed.
|
75
|
+
+
|
76
|
+
+And thus we are left with no choice but to patch the internals of libev in
|
77
|
+
+order to release a mutex at just the precise moment.
|
78
|
+
+
|
79
|
+
+Let this be a lesson to the all: CALLBACKS FUCKING BLOW
|
80
|
+
+
|
81
|
+
+#######################################################################
|
82
|
+
+*/
|
83
|
+
+
|
84
|
+
+#if defined(HAVE_RB_THREAD_BLOCKING_REGION)
|
85
|
+
+ poll_args[0] = (void *)loop;
|
86
|
+
+ poll_args[1] = (void *)&waittime;
|
87
|
+
+ rb_thread_blocking_region(ev_backend_poll, (void *)&poll_args, RUBY_UBF_IO, 0);
|
88
|
+
+#else
|
89
|
+
backend_poll (EV_A_ waittime);
|
90
|
+
+#endif
|
91
|
+
+/*
|
92
|
+
+############################# END PATCHERY ############################
|
93
|
+
+*/
|
94
|
+
+
|
95
|
+
assert ((loop_done = EVBREAK_CANCEL, 1)); /* assert for side effect */
|
96
|
+
|
97
|
+
pipe_write_wanted = 0; /* just an optimisation, no fence needed */
|
data/lib/cool.io/listener.rb
CHANGED
@@ -21,6 +21,10 @@ module Coolio
|
|
21
21
|
@listen_socket.fileno
|
22
22
|
end
|
23
23
|
|
24
|
+
def listen(backlog)
|
25
|
+
@listen_socket.listen(backlog)
|
26
|
+
end
|
27
|
+
|
24
28
|
# Close the listener
|
25
29
|
def close
|
26
30
|
detach if attached?
|
@@ -53,9 +57,9 @@ module Coolio
|
|
53
57
|
end
|
54
58
|
end
|
55
59
|
|
56
|
-
|
57
|
-
DEFAULT_BACKLOG = 1024
|
60
|
+
DEFAULT_BACKLOG = 1024
|
58
61
|
|
62
|
+
class TCPListener < Listener
|
59
63
|
# Create a new Coolio::TCPListener on the specified address and port.
|
60
64
|
# Accepts the following options:
|
61
65
|
#
|
@@ -87,7 +91,9 @@ module Coolio
|
|
87
91
|
# Optionally, it can also take anyn existing UNIXServer object
|
88
92
|
# and create a Coolio::UNIXListener out of it.
|
89
93
|
def initialize(*args)
|
90
|
-
|
94
|
+
s = ::UNIXServer === args.first ? args.first : ::UNIXServer.new(*args)
|
95
|
+
s.instance_eval { listen(DEFAULT_BACKLOG) }
|
96
|
+
super(s)
|
91
97
|
end
|
92
98
|
end
|
93
99
|
end
|
data/lib/cool.io/server.rb
CHANGED
@@ -56,7 +56,7 @@ module Coolio
|
|
56
56
|
raise ArgumentError, "port must be an integer" if nil == port
|
57
57
|
::TCPServer.new(host, port)
|
58
58
|
end
|
59
|
-
listen_socket.instance_eval { listen(
|
59
|
+
listen_socket.instance_eval { listen(DEFAULT_BACKLOG) } # Change listen backlog to 1024
|
60
60
|
super(listen_socket, klass, *args, &block)
|
61
61
|
end
|
62
62
|
end
|
@@ -68,6 +68,7 @@ module Coolio
|
|
68
68
|
class UNIXServer < Server
|
69
69
|
def initialize(path, klass = UNIXSocket, *args, &block)
|
70
70
|
s = ::UNIXServer === path ? path : ::UNIXServer.new(path)
|
71
|
+
s.instance_eval { listen(DEFAULT_BACKLOG) }
|
71
72
|
super(s, klass, *args, &block)
|
72
73
|
end
|
73
74
|
end
|
data/lib/cool.io/version.rb
CHANGED
data/spec/unix_server_spec.rb
CHANGED
@@ -11,13 +11,15 @@ describe Cool.io::UNIXServer, :env => :win do
|
|
11
11
|
|
12
12
|
it "creates a new Cool.io::UNIXServer" do
|
13
13
|
listener = Cool.io::UNIXListener.new(@tmp.path)
|
14
|
+
listener.listen(24)
|
14
15
|
File.socket?(@tmp.path).should == true
|
15
16
|
end
|
16
17
|
|
17
18
|
it "builds off an existing ::UNIXServer" do
|
18
19
|
unix_server = ::UNIXServer.new(@tmp.path)
|
19
20
|
File.socket?(@tmp.path).should == true
|
20
|
-
listener = Cool.io::UNIXServer.new(unix_server)
|
21
|
+
listener = Cool.io::UNIXServer.new(unix_server, Coolio::UNIXSocket)
|
22
|
+
listener.listen(24)
|
21
23
|
File.socket?(@tmp.path).should == true
|
22
24
|
listener.fileno.should == unix_server.fileno
|
23
25
|
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: cool.io
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.2.
|
4
|
+
version: 1.2.1
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -10,7 +10,7 @@ authors:
|
|
10
10
|
autorequire:
|
11
11
|
bindir: bin
|
12
12
|
cert_chain: []
|
13
|
-
date:
|
13
|
+
date: 2014-02-21 00:00:00.000000000 Z
|
14
14
|
dependencies:
|
15
15
|
- !ruby/object:Gem::Dependency
|
16
16
|
name: rake-compiler
|
@@ -124,6 +124,7 @@ files:
|
|
124
124
|
- ext/libev/ev_vars.h
|
125
125
|
- ext/libev/ev_win32.c
|
126
126
|
- ext/libev/ev_wrap.h
|
127
|
+
- ext/libev/ruby_gil.patch
|
127
128
|
- ext/libev/test_libev_win32.c
|
128
129
|
- lib/.gitignore
|
129
130
|
- lib/cool.io.rb
|
@@ -164,7 +165,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
164
165
|
version: '0'
|
165
166
|
segments:
|
166
167
|
- 0
|
167
|
-
hash:
|
168
|
+
hash: 2606014626052723115
|
168
169
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
169
170
|
none: false
|
170
171
|
requirements:
|
@@ -173,7 +174,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
173
174
|
version: '0'
|
174
175
|
segments:
|
175
176
|
- 0
|
176
|
-
hash:
|
177
|
+
hash: 2606014626052723115
|
177
178
|
requirements: []
|
178
179
|
rubyforge_project:
|
179
180
|
rubygems_version: 1.8.23
|