cool.io 1.2.0 → 1.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/.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
|