rainbows 0.97.0 → 1.0.0pre1
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/.manifest +14 -2
- data/ChangeLog +87 -118
- data/GIT-VERSION-FILE +1 -1
- data/GIT-VERSION-GEN +1 -1
- data/GNUmakefile +1 -1
- data/README +1 -1
- data/bin/rainbows +15 -20
- data/lib/rainbows/actor_spawn.rb +20 -22
- data/lib/rainbows/app_pool.rb +89 -93
- data/lib/rainbows/base.rb +4 -61
- data/lib/rainbows/client.rb +9 -0
- data/lib/rainbows/configurator.rb +37 -39
- data/lib/rainbows/const.rb +18 -18
- data/lib/rainbows/dev_fd_response.rb +2 -1
- data/lib/rainbows/error.rb +39 -37
- data/lib/rainbows/ev_core.rb +103 -109
- data/lib/rainbows/event_machine.rb +188 -196
- data/lib/rainbows/fiber/base.rb +69 -88
- data/lib/rainbows/fiber/io/compat.rb +13 -0
- data/lib/rainbows/fiber/io/methods.rb +49 -0
- data/lib/rainbows/fiber/io/pipe.rb +7 -0
- data/lib/rainbows/fiber/io/socket.rb +7 -0
- data/lib/rainbows/fiber/io.rb +125 -84
- data/lib/rainbows/fiber/rev/heartbeat.rb +8 -0
- data/lib/rainbows/fiber/rev/kato.rb +22 -0
- data/lib/rainbows/fiber/rev/methods.rb +55 -0
- data/lib/rainbows/fiber/rev/server.rb +32 -0
- data/lib/rainbows/fiber/rev/sleeper.rb +15 -0
- data/lib/rainbows/fiber/rev.rb +6 -164
- data/lib/rainbows/fiber.rb +23 -5
- data/lib/rainbows/fiber_pool.rb +31 -37
- data/lib/rainbows/fiber_spawn.rb +21 -28
- data/lib/rainbows/http_server.rb +80 -80
- data/lib/rainbows/max_body.rb +26 -28
- data/lib/rainbows/process_client.rb +61 -0
- data/lib/rainbows/queue_pool.rb +19 -22
- data/lib/rainbows/read_timeout.rb +28 -0
- data/lib/rainbows/rev/client.rb +10 -10
- data/lib/rainbows/rev/core.rb +2 -3
- data/lib/rainbows/rev/thread.rb +1 -1
- data/lib/rainbows/rev_fiber_spawn.rb +21 -24
- data/lib/rainbows/revactor.rb +18 -15
- data/lib/rainbows/thread_pool.rb +2 -4
- data/lib/rainbows/thread_spawn.rb +1 -2
- data/lib/rainbows/writer_thread_pool.rb +14 -4
- data/lib/rainbows/writer_thread_spawn.rb +14 -4
- data/lib/rainbows.rb +7 -15
- data/local.mk.sample +3 -11
- data/rainbows.gemspec +2 -4
- data/t/kgio-pipe-response.ru +10 -0
- data/t/t0035-kgio-pipe-response.sh +70 -0
- data/t/test_isolate.rb +2 -1
- metadata +46 -30
- data/lib/rainbows/acceptor.rb +0 -26
- data/lib/rainbows/byte_slice.rb +0 -17
data/lib/rainbows/fiber/base.rb
CHANGED
@@ -2,103 +2,84 @@
|
|
2
2
|
# :enddoc:
|
3
3
|
require 'rainbows/fiber/io'
|
4
4
|
|
5
|
-
module Rainbows
|
6
|
-
module Fiber
|
5
|
+
module Rainbows::Fiber::Base
|
7
6
|
|
8
|
-
|
9
|
-
RD = []
|
7
|
+
include Rainbows::Base
|
10
8
|
|
11
|
-
|
12
|
-
|
9
|
+
# :stopdoc:
|
10
|
+
RD = Rainbows::Fiber::RD
|
11
|
+
WR = Rainbows::Fiber::WR
|
12
|
+
ZZ = Rainbows::Fiber::ZZ
|
13
|
+
# :startdoc:
|
13
14
|
|
14
|
-
|
15
|
-
|
15
|
+
# the scheduler method that powers both FiberSpawn and FiberPool
|
16
|
+
# concurrency models. It times out idle clients and attempts to
|
17
|
+
# schedules ones that were blocked on I/O. At most it'll sleep
|
18
|
+
# for one second (returned by the schedule_sleepers method) which
|
19
|
+
# will cause it.
|
20
|
+
def schedule(&block)
|
21
|
+
ret = begin
|
22
|
+
G.tick
|
23
|
+
RD.compact.each { |c| c.f.resume } # attempt to time out idle clients
|
24
|
+
t = schedule_sleepers
|
25
|
+
Kernel.select(RD.compact.concat(LISTENERS), WR.compact, nil, t) or return
|
26
|
+
rescue Errno::EINTR
|
27
|
+
retry
|
28
|
+
rescue Errno::EBADF, TypeError
|
29
|
+
LISTENERS.compact!
|
30
|
+
raise
|
31
|
+
end or return
|
16
32
|
|
17
|
-
#
|
18
|
-
|
19
|
-
# indefinitely to be woken up (nobody wants that in a web server,
|
20
|
-
# right?). Calling this directly is deprecated, use
|
21
|
-
# Rainbows.sleep(seconds) instead.
|
22
|
-
def self.sleep(seconds)
|
23
|
-
ZZ[::Fiber.current] = Time.now + seconds
|
24
|
-
::Fiber.yield
|
25
|
-
end
|
26
|
-
|
27
|
-
# base module used by FiberSpawn and FiberPool
|
28
|
-
module Base
|
29
|
-
include Rainbows::Base
|
30
|
-
|
31
|
-
# the scheduler method that powers both FiberSpawn and FiberPool
|
32
|
-
# concurrency models. It times out idle clients and attempts to
|
33
|
-
# schedules ones that were blocked on I/O. At most it'll sleep
|
34
|
-
# for one second (returned by the schedule_sleepers method) which
|
35
|
-
# will cause it.
|
36
|
-
def schedule(&block)
|
37
|
-
ret = begin
|
38
|
-
G.tick
|
39
|
-
RD.compact.each { |c| c.f.resume } # attempt to time out idle clients
|
40
|
-
t = schedule_sleepers
|
41
|
-
Kernel.select(RD.compact.concat(LISTENERS),
|
42
|
-
WR.compact, nil, t) or return
|
43
|
-
rescue Errno::EINTR
|
44
|
-
retry
|
45
|
-
rescue Errno::EBADF, TypeError
|
46
|
-
LISTENERS.compact!
|
47
|
-
raise
|
48
|
-
end or return
|
49
|
-
|
50
|
-
# active writers first, then _all_ readers for keepalive timeout
|
51
|
-
ret[1].concat(RD.compact).each { |c| c.f.resume }
|
33
|
+
# active writers first, then _all_ readers for keepalive timeout
|
34
|
+
ret[1].concat(RD.compact).each { |c| c.f.resume }
|
52
35
|
|
53
|
-
|
54
|
-
|
55
|
-
|
36
|
+
# accept is an expensive syscall, filter out listeners we don't want
|
37
|
+
(ret[0] & LISTENERS).each(&block)
|
38
|
+
end
|
56
39
|
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
end
|
70
|
-
}
|
71
|
-
fibs.each { |fib| fib.resume }
|
72
|
-
now = Time.now
|
73
|
-
max.nil? || max > (now + 1) ? 1 : max - now
|
40
|
+
# wakes up any sleepers that need to be woken and
|
41
|
+
# returns an interval to IO.select on
|
42
|
+
def schedule_sleepers
|
43
|
+
max = nil
|
44
|
+
now = Time.now
|
45
|
+
fibs = []
|
46
|
+
ZZ.delete_if { |fib, time|
|
47
|
+
if now >= time
|
48
|
+
fibs << fib
|
49
|
+
else
|
50
|
+
max = time
|
51
|
+
false
|
74
52
|
end
|
53
|
+
}
|
54
|
+
fibs.each { |fib| fib.resume }
|
55
|
+
now = Time.now
|
56
|
+
max.nil? || max > (now + 1) ? 1 : max - now
|
57
|
+
end
|
75
58
|
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
59
|
+
def wait_headers_readable(client)
|
60
|
+
io = client.to_io
|
61
|
+
expire = nil
|
62
|
+
begin
|
63
|
+
return io.recv_nonblock(1, Socket::MSG_PEEK)
|
64
|
+
rescue Errno::EAGAIN
|
65
|
+
return if expire && expire < Time.now
|
66
|
+
expire ||= Time.now + G.kato
|
67
|
+
client.wait_readable
|
68
|
+
retry
|
69
|
+
end
|
70
|
+
end
|
88
71
|
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
72
|
+
def process(client)
|
73
|
+
G.cur += 1
|
74
|
+
process_client(client)
|
75
|
+
ensure
|
76
|
+
G.cur -= 1
|
77
|
+
ZZ.delete(client.f)
|
78
|
+
end
|
96
79
|
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
end
|
102
|
-
end
|
80
|
+
def self.setup(klass, app)
|
81
|
+
require 'rainbows/fiber/body'
|
82
|
+
klass.__send__(:include, Rainbows::Fiber::Body)
|
83
|
+
self.const_set(:APP, app)
|
103
84
|
end
|
104
85
|
end
|
@@ -0,0 +1,13 @@
|
|
1
|
+
# -*- encoding: binary -*-
|
2
|
+
# :enddoc:
|
3
|
+
#
|
4
|
+
# Used to make Rainbows::Fiber::IO behave like 0.97.0 and earlier
|
5
|
+
module Rainbows::Fiber::IO::Compat
|
6
|
+
def initialize(io, fiber = Fiber.current)
|
7
|
+
@to_io, @f = io, fiber
|
8
|
+
end
|
9
|
+
|
10
|
+
def close
|
11
|
+
@to_io.close
|
12
|
+
end
|
13
|
+
end
|
@@ -0,0 +1,49 @@
|
|
1
|
+
# -*- encoding: binary -*-
|
2
|
+
#
|
3
|
+
# :enddoc:
|
4
|
+
|
5
|
+
# this is used to augment Kgio::Socket and Kgio::Pipe-enhanced classes
|
6
|
+
# for use with Rainbows! Do no use this directly, see
|
7
|
+
# Rainbows::Fiber::IO::Pipe and Rainbows::Fiber::IO::Socket instead.
|
8
|
+
module Rainbows::Fiber::IO::Methods
|
9
|
+
RD = Rainbows::Fiber::RD
|
10
|
+
WR = Rainbows::Fiber::WR
|
11
|
+
attr_accessor :f
|
12
|
+
|
13
|
+
# for wrapping output response bodies
|
14
|
+
def each(&block)
|
15
|
+
if buf = kgio_read(16384)
|
16
|
+
yield buf
|
17
|
+
yield buf while kgio_read(16384, buf)
|
18
|
+
end
|
19
|
+
self
|
20
|
+
end
|
21
|
+
|
22
|
+
def close
|
23
|
+
fd = fileno
|
24
|
+
RD[fd] = WR[fd] = nil
|
25
|
+
super
|
26
|
+
end
|
27
|
+
|
28
|
+
def wait_readable
|
29
|
+
fd = fileno
|
30
|
+
@f = Fiber.current
|
31
|
+
RD[fd] = self
|
32
|
+
Fiber.yield
|
33
|
+
RD[fd] = nil
|
34
|
+
end
|
35
|
+
|
36
|
+
def wait_writable
|
37
|
+
fd = fileno
|
38
|
+
@f = Fiber.current
|
39
|
+
WR[fd] = self
|
40
|
+
Fiber.yield
|
41
|
+
WR[fd] = nil
|
42
|
+
end
|
43
|
+
|
44
|
+
def self.included(klass)
|
45
|
+
if klass.method_defined?(:kgio_write)
|
46
|
+
klass.__send__(:alias_method, :write, :kgio_write)
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
@@ -0,0 +1,7 @@
|
|
1
|
+
# -*- encoding: binary -*-
|
2
|
+
# A Fiber-aware Pipe class, gives users the illusion of a synchronous
|
3
|
+
# interface that yields away from the current Fiber whenever
|
4
|
+
# the underlying descriptor is blocked on reads or write
|
5
|
+
class Rainbows::Fiber::IO::Pipe < Kgio::Pipe
|
6
|
+
include Rainbows::Fiber::IO::Methods
|
7
|
+
end
|
@@ -0,0 +1,7 @@
|
|
1
|
+
# -*- encoding: binary -*-
|
2
|
+
# A Fiber-aware Socket class, gives users the illusion of a synchronous
|
3
|
+
# interface that yields away from the current Fiber whenever
|
4
|
+
# the underlying descriptor is blocked on reads or write
|
5
|
+
class Rainbows::Fiber::IO::Socket < Kgio::Socket
|
6
|
+
include Rainbows::Fiber::IO::Methods
|
7
|
+
end
|
data/lib/rainbows/fiber/io.rb
CHANGED
@@ -1,93 +1,134 @@
|
|
1
1
|
# -*- encoding: binary -*-
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
::
|
56
|
-
WR[fileno] = nil
|
57
|
-
end
|
58
|
-
|
59
|
-
def write(buf)
|
60
|
-
begin
|
61
|
-
(w = to_io.write_nonblock(buf)) == buf.bytesize and return
|
62
|
-
buf = byte_slice(buf, w..-1)
|
63
|
-
rescue Errno::EAGAIN
|
2
|
+
|
3
|
+
# A Fiber-aware IO class, gives users the illusion of a synchronous
|
4
|
+
# interface that yields away from the current Fiber whenever
|
5
|
+
# the underlying descriptor is blocked on reads or write
|
6
|
+
#
|
7
|
+
# This is a stable, legacy interface and should be preserved for all
|
8
|
+
# future versions of Rainbows! However, new apps should use
|
9
|
+
# Rainbows::Fiber::IO::Socket or Rainbows::Fiber::IO::Pipe instead.
|
10
|
+
|
11
|
+
class Rainbows::Fiber::IO
|
12
|
+
attr_accessor :to_io
|
13
|
+
|
14
|
+
# :stopdoc:
|
15
|
+
# see Rainbows::Fiber::IO::Compat for initialize implementation
|
16
|
+
class << self
|
17
|
+
alias :[] :new
|
18
|
+
end
|
19
|
+
# :startdoc:
|
20
|
+
|
21
|
+
# needed to write errors with
|
22
|
+
def write_nonblock(buf)
|
23
|
+
@to_io.write_nonblock(buf)
|
24
|
+
end
|
25
|
+
|
26
|
+
def kgio_addr
|
27
|
+
@to_io.kgio_addr
|
28
|
+
end
|
29
|
+
|
30
|
+
# for wrapping output response bodies
|
31
|
+
def each(&block)
|
32
|
+
buf = readpartial(16384)
|
33
|
+
yield buf
|
34
|
+
yield buf while readpartial(16384, buf)
|
35
|
+
rescue EOFError
|
36
|
+
self
|
37
|
+
end
|
38
|
+
|
39
|
+
def closed?
|
40
|
+
@to_io.closed?
|
41
|
+
end
|
42
|
+
|
43
|
+
def fileno
|
44
|
+
@to_io.fileno
|
45
|
+
end
|
46
|
+
|
47
|
+
def write(buf)
|
48
|
+
if @to_io.respond_to?(:kgio_trywrite)
|
49
|
+
begin
|
50
|
+
case rv = @to_io.kgio_trywrite(buf)
|
51
|
+
when nil
|
52
|
+
return
|
53
|
+
when String
|
54
|
+
buf = rv
|
55
|
+
when Kgio::WaitWritable
|
64
56
|
wait_writable
|
65
|
-
retry
|
66
|
-
end while true
|
67
|
-
end
|
68
|
-
|
69
|
-
# used for reading headers (respecting keepalive_timeout)
|
70
|
-
def read_timeout
|
71
|
-
expire = nil
|
72
|
-
begin
|
73
|
-
to_io.read_nonblock(16384)
|
74
|
-
rescue Errno::EAGAIN
|
75
|
-
return if expire && expire < Time.now
|
76
|
-
expire ||= Time.now + G.kato
|
77
|
-
wait_readable
|
78
|
-
retry
|
79
57
|
end
|
80
|
-
end
|
58
|
+
end while true
|
59
|
+
else
|
60
|
+
begin
|
61
|
+
(rv = @to_io.write_nonblock(buf)) == buf.bytesize and return
|
62
|
+
buf = byte_slice(buf, rv..-1)
|
63
|
+
rescue Errno::EAGAIN
|
64
|
+
wait_writable
|
65
|
+
end while true
|
66
|
+
end
|
67
|
+
end
|
68
|
+
|
69
|
+
def byte_slice(buf, range) # :nodoc:
|
70
|
+
if buf.encoding != Encoding::BINARY
|
71
|
+
buf.dup.force_encoding(Encoding::BINARY)[range]
|
72
|
+
else
|
73
|
+
buf[range]
|
74
|
+
end
|
75
|
+
end
|
76
|
+
|
77
|
+
# used for reading headers (respecting keepalive_timeout)
|
78
|
+
def read_timeout
|
79
|
+
expire = nil
|
80
|
+
begin
|
81
|
+
return @to_io.read_nonblock(16384)
|
82
|
+
rescue Errno::EAGAIN
|
83
|
+
return if expire && expire < Time.now
|
84
|
+
expire ||= Time.now + G.kato
|
85
|
+
wait_readable
|
86
|
+
end while true
|
87
|
+
end
|
81
88
|
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
89
|
+
def readpartial(length, buf = "")
|
90
|
+
if @to_io.respond_to?(:kgio_tryread)
|
91
|
+
begin
|
92
|
+
rv = @to_io.kgio_tryread(length, buf)
|
93
|
+
case rv
|
94
|
+
when nil
|
95
|
+
raise EOFError, "end of file reached", []
|
96
|
+
when Kgio::WaitReadable
|
86
97
|
wait_readable
|
87
|
-
|
98
|
+
else
|
99
|
+
return rv
|
88
100
|
end
|
89
|
-
end
|
90
|
-
|
101
|
+
end while true
|
102
|
+
else
|
103
|
+
begin
|
104
|
+
return @to_io.read_nonblock(length, buf)
|
105
|
+
rescue Errno::EAGAIN
|
106
|
+
wait_readable
|
107
|
+
end while true
|
91
108
|
end
|
92
109
|
end
|
110
|
+
|
111
|
+
def kgio_read(*args)
|
112
|
+
@to_io.kgio_read(*args)
|
113
|
+
end
|
114
|
+
|
115
|
+
def kgio_read!(*args)
|
116
|
+
@to_io.kgio_read!(*args)
|
117
|
+
end
|
118
|
+
|
119
|
+
def kgio_trywrite(*args)
|
120
|
+
@to_io.kgio_trywrite(*args)
|
121
|
+
end
|
122
|
+
|
123
|
+
autoload :Socket, 'rainbows/fiber/io/socket'
|
124
|
+
autoload :Pipe, 'rainbows/fiber/io/pipe'
|
93
125
|
end
|
126
|
+
|
127
|
+
# :stopdoc:
|
128
|
+
require 'rainbows/fiber/io/methods'
|
129
|
+
require 'rainbows/fiber/io/compat'
|
130
|
+
Rainbows::Client.__send__(:include, Rainbows::Fiber::IO::Methods)
|
131
|
+
Rainbows::Fiber::IO.__send__(:include, Rainbows::Fiber::IO::Compat)
|
132
|
+
Rainbows::Fiber::IO.__send__(:include, Rainbows::Fiber::IO::Methods)
|
133
|
+
Kgio.wait_readable = :wait_readable
|
134
|
+
Kgio.wait_writable = :wait_writable
|
@@ -0,0 +1,22 @@
|
|
1
|
+
# -*- encoding: binary -*-
|
2
|
+
# :enddoc:
|
3
|
+
# keep-alive timeout class
|
4
|
+
class Rainbows::Fiber::Rev::Kato < Rev::TimerWatcher
|
5
|
+
def initialize
|
6
|
+
@watch = []
|
7
|
+
super(1, true)
|
8
|
+
end
|
9
|
+
|
10
|
+
def <<(fiber)
|
11
|
+
@watch << fiber
|
12
|
+
enable unless enabled?
|
13
|
+
end
|
14
|
+
|
15
|
+
def on_timer
|
16
|
+
@watch.uniq!
|
17
|
+
while f = @watch.shift
|
18
|
+
f.resume if f.alive?
|
19
|
+
end
|
20
|
+
disable
|
21
|
+
end
|
22
|
+
end
|
@@ -0,0 +1,55 @@
|
|
1
|
+
# -*- encoding: binary -*-
|
2
|
+
# :enddoc:
|
3
|
+
module Rainbows::Fiber::Rev::Methods
|
4
|
+
class Watcher < Rev::IOWatcher
|
5
|
+
def initialize(fio, flag)
|
6
|
+
@f = fio.f || Fiber.current
|
7
|
+
super(fio, flag)
|
8
|
+
attach(Rev::Loop.default)
|
9
|
+
end
|
10
|
+
|
11
|
+
def on_readable
|
12
|
+
@f.resume
|
13
|
+
end
|
14
|
+
|
15
|
+
alias on_writable on_readable
|
16
|
+
end
|
17
|
+
|
18
|
+
def initialize(*args)
|
19
|
+
@f = Fiber.current
|
20
|
+
super(*args)
|
21
|
+
@r = @w = false
|
22
|
+
end
|
23
|
+
|
24
|
+
def close
|
25
|
+
@w.detach if @w
|
26
|
+
@r.detach if @r
|
27
|
+
@r = @w = false
|
28
|
+
super
|
29
|
+
end
|
30
|
+
|
31
|
+
def wait_writable
|
32
|
+
@w ||= Watcher.new(self, :w)
|
33
|
+
@w.enable unless @w.enabled?
|
34
|
+
Fiber.yield
|
35
|
+
@w.disable
|
36
|
+
end
|
37
|
+
|
38
|
+
def wait_readable
|
39
|
+
@r ||= Watcher.new(self, :r)
|
40
|
+
@r.enable unless @r.enabled?
|
41
|
+
KATO << @f
|
42
|
+
Fiber.yield
|
43
|
+
@r.disable
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
[
|
48
|
+
Rainbows::Fiber::IO,
|
49
|
+
Rainbows::Client,
|
50
|
+
# the next two trigger autoload, ugh, oh well...
|
51
|
+
Rainbows::Fiber::IO::Socket,
|
52
|
+
Rainbows::Fiber::IO::Pipe
|
53
|
+
].each do |klass|
|
54
|
+
klass.__send__(:include, Rainbows::Fiber::Rev::Methods)
|
55
|
+
end
|
@@ -0,0 +1,32 @@
|
|
1
|
+
# -*- encoding: binary -*-
|
2
|
+
# :enddoc:
|
3
|
+
class Rainbows::Fiber::Rev::Server < Rev::IOWatcher
|
4
|
+
G = Rainbows::G
|
5
|
+
include Rainbows::ProcessClient
|
6
|
+
|
7
|
+
def to_io
|
8
|
+
@io
|
9
|
+
end
|
10
|
+
|
11
|
+
def initialize(io)
|
12
|
+
@io = io
|
13
|
+
super(self, :r)
|
14
|
+
end
|
15
|
+
|
16
|
+
def close
|
17
|
+
detach if attached?
|
18
|
+
@io.close
|
19
|
+
end
|
20
|
+
|
21
|
+
def on_readable
|
22
|
+
return if G.cur >= MAX
|
23
|
+
c = @io.kgio_tryaccept and Fiber.new { process(c) }.resume
|
24
|
+
end
|
25
|
+
|
26
|
+
def process(io)
|
27
|
+
G.cur += 1
|
28
|
+
process_client(io)
|
29
|
+
ensure
|
30
|
+
G.cur -= 1
|
31
|
+
end
|
32
|
+
end
|
@@ -0,0 +1,15 @@
|
|
1
|
+
# -*- encoding: binary -*-
|
2
|
+
# :enddoc:
|
3
|
+
class Rainbows::Fiber::Rev::Sleeper < Rev::TimerWatcher
|
4
|
+
|
5
|
+
def initialize(seconds)
|
6
|
+
@f = Fiber.current
|
7
|
+
super(seconds, false)
|
8
|
+
attach(Rev::Loop.default)
|
9
|
+
Fiber.yield
|
10
|
+
end
|
11
|
+
|
12
|
+
def on_timer
|
13
|
+
@f.resume
|
14
|
+
end
|
15
|
+
end
|