barlume 0.0.1.rc.1 → 0.0.1.rc.2
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/barlume.gemspec +2 -1
- data/examples/echo.rb +78 -0
- data/examples/slowpokes.rb +75 -0
- data/lib/barlume/lanterna.rb +243 -65
- data/lib/barlume/lanterna/dpoll.rb +204 -0
- data/lib/barlume/lanterna/epoll.rb +98 -70
- data/lib/barlume/lanterna/{utils.rb → helpers.rb} +6 -3
- data/lib/barlume/lanterna/kqueue.rb +88 -101
- data/lib/barlume/lanterna/poll.rb +67 -66
- data/lib/barlume/lanterna/port.rb +211 -0
- data/lib/barlume/lanterna/select.rb +22 -44
- data/lib/barlume/lucciola.rb +221 -10
- data/lib/barlume/version.rb +1 -1
- data/test/benchmark.client.rb +17 -0
- data/test/benchmark.server.rb +35 -0
- data/test/flood.js +28 -0
- metadata +30 -5
- data/examples/test.rb +0 -27
@@ -42,9 +42,7 @@ class Kqueue < Lanterna; begin
|
|
42
42
|
end
|
43
43
|
|
44
44
|
attach_function :kqueue, [], :int
|
45
|
-
attach_function :kevent, [:int, :pointer, :int, :pointer, :int, :pointer], :int
|
46
|
-
|
47
|
-
MAX = 4294967295
|
45
|
+
attach_function :kevent, [:int, :pointer, :int, :pointer, :int, :pointer], :int, :blocking => true
|
48
46
|
|
49
47
|
EVFILT_READ = -1
|
50
48
|
EVFILT_WRITE = -2
|
@@ -100,145 +98,134 @@ class Kqueue < Lanterna; begin
|
|
100
98
|
}
|
101
99
|
end
|
102
100
|
|
101
|
+
attr_reader :size
|
102
|
+
|
103
103
|
def initialize
|
104
104
|
super
|
105
105
|
|
106
106
|
FFI.raise_if((@fd = C.kqueue) < 0)
|
107
107
|
|
108
|
-
|
109
|
-
|
110
|
-
end
|
108
|
+
@timeout = C::TimeSpec.new
|
109
|
+
@ev = C::Kevent.new
|
111
110
|
|
112
|
-
|
113
|
-
end
|
111
|
+
FFI.raise_if(C.kevent(@fd, C::EV_SET(@ev, @breaker.to_i, C::EVFILT_READ, C::EV_ADD | C::EV_ENABLE, 0, 0, 0), 1, nil, 0, nil) < 0)
|
114
112
|
|
115
|
-
|
116
|
-
@events.size / C::Kevent.size
|
113
|
+
self.size = 4096
|
117
114
|
end
|
118
115
|
|
119
116
|
def size= (n)
|
120
117
|
@events = FFI::MemoryPointer.new C::Kevent.size, n
|
118
|
+
@size = @events.size / C::Kevent.size
|
121
119
|
end
|
122
120
|
|
123
|
-
def
|
124
|
-
|
125
|
-
@last = nil
|
126
|
-
}
|
127
|
-
end
|
121
|
+
def edge_triggered?; @edge; end
|
122
|
+
def level_triggered?; !@edge; end
|
128
123
|
|
129
|
-
def
|
130
|
-
|
131
|
-
begin
|
132
|
-
FFI.raise_if(C.kevent(@fd, C::EV_SET(C::Kevent.new, what.to_i, C::EVFILT_READ, C::EV_DELETE | C::EV_DISABLE, 0, 0, 0), 1, nil, 0, nil) < 0)
|
133
|
-
rescue Errno::ENOENT; end
|
124
|
+
def edge_triggered!
|
125
|
+
@edge = true
|
134
126
|
|
135
|
-
|
136
|
-
|
137
|
-
|
127
|
+
each {|l|
|
128
|
+
if l.readable?
|
129
|
+
FFI.raise_if(C.kevent(@fd, C::EV_SET(@ev, l.to_i, C::EVFILT_READ, C::EV_ADD | C::EV_ENABLE | C::EV_CLEAR, 0, 0, l.to_i), 1, nil, 0, nil) < 0)
|
130
|
+
end
|
138
131
|
|
139
|
-
|
132
|
+
if l.writable?
|
133
|
+
FFI.raise_if(C.kevent(@fd, C::EV_SET(@ev, l.to_i, C::EVFILT_WRITE, C::EV_ADD | C::EV_ENABLE | C::EV_CLEAR, 0, 0, l.to_i), 1, nil, 0, nil) < 0)
|
134
|
+
end
|
140
135
|
}
|
141
136
|
end
|
142
137
|
|
143
|
-
def
|
144
|
-
|
145
|
-
|
146
|
-
Available.new(to(:read), to(:write), to(:error))
|
147
|
-
end
|
138
|
+
def level_triggered!
|
139
|
+
@edge = false
|
148
140
|
|
149
|
-
|
150
|
-
|
141
|
+
each {|l|
|
142
|
+
if l.readable?
|
143
|
+
FFI.raise_if(C.kevent(@fd, C::EV_SET(@ev, l.to_i, C::EVFILT_READ, C::EV_ADD | C::EV_ENABLE, 0, 0, l.to_i), 1, nil, 0, nil) < 0)
|
144
|
+
end
|
151
145
|
|
152
|
-
|
153
|
-
|
154
|
-
|
155
|
-
|
156
|
-
end
|
146
|
+
if l.writable?
|
147
|
+
FFI.raise_if(C.kevent(@fd, C::EV_SET(@ev, l.to_i, C::EVFILT_WRITE, C::EV_ADD | C::EV_ENABLE, 0, 0, l.to_i), 1, nil, 0, nil) < 0)
|
148
|
+
end
|
149
|
+
}
|
157
150
|
end
|
158
151
|
|
159
|
-
def
|
160
|
-
|
152
|
+
def remove (*)
|
153
|
+
super {|l|
|
154
|
+
begin
|
155
|
+
FFI.raise_if(C.kevent(@fd, C::EV_SET(@ev, l.to_i, C::EVFILT_READ, C::EV_DELETE | C::EV_DISABLE, 0, 0, 0), 1, nil, 0, nil) < 0)
|
156
|
+
rescue Errno::ENOENT, Errno::ENOTDIR; end
|
161
157
|
|
162
|
-
|
163
|
-
|
164
|
-
|
165
|
-
|
166
|
-
end
|
158
|
+
begin
|
159
|
+
FFI.raise_if(C.kevent(@fd, C::EV_SET(@ev, l.to_i, C::EVFILT_WRITE, C::EV_DELETE | C::EV_DISABLE, 0, 0, 0), 1, nil, 0, nil) < 0)
|
160
|
+
rescue Errno::ENOENT, Errno::ENOTDIR; end
|
161
|
+
}
|
167
162
|
end
|
168
163
|
|
169
|
-
def
|
170
|
-
|
164
|
+
def readable! (*)
|
165
|
+
super {|l|
|
166
|
+
FFI.raise_if(C.kevent(@fd, C::EV_SET(@ev, l.to_i, C::EVFILT_READ, C::EV_ADD | C::EV_ENABLE | (edge_triggered? ? C::EV_CLEAR : 0), 0, 0, 0), 1, nil, 0, nil) < 0)
|
167
|
+
}
|
168
|
+
end
|
171
169
|
|
172
|
-
|
170
|
+
def no_readable! (*)
|
171
|
+
super {|l|
|
172
|
+
FFI.raise_if(C.kevent(@fd, C::EV_SET(@ev, l.to_i, C::EVFILT_READ, C::EV_ADD | C::EV_DISABLE, 0, 0, 0), 1, nil, 0, nil) < 0)
|
173
|
+
}
|
174
|
+
end
|
173
175
|
|
174
|
-
|
175
|
-
|
176
|
-
|
176
|
+
def writable! (*)
|
177
|
+
super {|l|
|
178
|
+
FFI.raise_if(C.kevent(@fd, C::EV_SET(@ev, l.to_i, C::EVFILT_WRITE, C::EV_ADD | C::EV_ENABLE | (edge_triggered? ? C::EV_CLEAR : 0), 0, 0, 0), 1, nil, 0, nil) < 0)
|
179
|
+
}
|
180
|
+
end
|
177
181
|
|
178
|
-
|
179
|
-
|
180
|
-
|
181
|
-
|
182
|
-
|
183
|
-
index = FFI::Pointer.new(index)
|
182
|
+
def no_writable! (*)
|
183
|
+
super {|l|
|
184
|
+
FFI.raise_if(C.kevent(@fd, C::EV_SET(@ev, l.to_i, C::EVFILT_WRITE, C::EV_ADD | C::EV_DISABLE, 0, 0, 0), 1, nil, 0, nil) < 0)
|
185
|
+
}
|
186
|
+
end
|
184
187
|
|
185
|
-
|
186
|
-
|
187
|
-
}
|
188
|
-
else
|
189
|
-
descriptors.each_with_index {|descriptor, index|
|
190
|
-
index = FFI::Pointer.new(index)
|
188
|
+
def available (timeout = nil, &block)
|
189
|
+
return enum_for :available, timeout unless block
|
191
190
|
|
192
|
-
|
193
|
-
|
194
|
-
|
191
|
+
if timeout
|
192
|
+
@timeout[:tv_sec] = timeout.to_i
|
193
|
+
@timeout[:tv_nsec] = (timeout - timeout.to_i) * 1000
|
195
194
|
end
|
196
195
|
|
197
|
-
|
198
|
-
end
|
196
|
+
FFI.raise_if((length = C.kevent(@fd, nil, 0, @events, size, timeout ? @timeout : nil)) < 0)
|
199
197
|
|
200
|
-
|
201
|
-
|
198
|
+
if length == 0
|
199
|
+
yield :timeout, timeout
|
202
200
|
|
203
|
-
|
204
|
-
|
205
|
-
p = C::Kevent.new(@events + (n * C::Kevent.size))
|
206
|
-
index = p[:udata].address
|
201
|
+
return self
|
202
|
+
end
|
207
203
|
|
208
|
-
|
209
|
-
|
204
|
+
n = 0
|
205
|
+
size = C::Kevent.size
|
206
|
+
while n < length
|
207
|
+
p = C::Kevent.new(@events + (n * size))
|
208
|
+
fd = p[:ident]
|
209
|
+
lucciola = self[fd]
|
210
|
+
|
211
|
+
if lucciola
|
212
|
+
if (p[:flags] & C::EV_ERROR).nonzero?
|
213
|
+
yield :error, lucciola
|
214
|
+
elsif p[:filter] == C::EVFILT_READ
|
215
|
+
yield :readable, lucciola
|
216
|
+
elsif p[:filter] == C::EVFILT_WRITE
|
217
|
+
yield :writable, lucciola
|
210
218
|
end
|
211
|
-
|
212
|
-
|
213
|
-
|
214
|
-
|
215
|
-
when :write then C::EVFILT_WRITE
|
219
|
+
elsif fd == @breaker.to_i
|
220
|
+
yield :break, @breaker.reason
|
221
|
+
else
|
222
|
+
raise "#{fd} isn't trapped here"
|
216
223
|
end
|
217
224
|
|
218
|
-
|
219
|
-
p = C::Kevent.new(@events + (n * C::Kevent.size))
|
220
|
-
index = p[:udata].address
|
221
|
-
|
222
|
-
if index != C::MAX && p[:filter] == filter
|
223
|
-
result << descriptors[index]
|
224
|
-
end
|
225
|
-
}
|
226
|
-
end
|
227
|
-
|
228
|
-
result
|
229
|
-
end
|
230
|
-
|
231
|
-
def kevent (timeout = nil)
|
232
|
-
if timeout
|
233
|
-
timeout = C::TimeSpec.new.tap {|t|
|
234
|
-
t[:tv_sec] = timeout.to_i
|
235
|
-
t[:tv_nsec] = (timeout - timeout.to_i) * 1000
|
236
|
-
}
|
225
|
+
n += 1
|
237
226
|
end
|
238
227
|
|
239
|
-
|
240
|
-
|
241
|
-
@breaker.flush
|
228
|
+
self
|
242
229
|
end
|
243
230
|
rescue Exception
|
244
231
|
def self.supported?
|
@@ -17,8 +17,6 @@
|
|
17
17
|
# along with barlume. If not, see <http://www.gnu.org/licenses/>.
|
18
18
|
#++
|
19
19
|
|
20
|
-
require 'ffi'
|
21
|
-
|
22
20
|
module Barlume; class Lanterna
|
23
21
|
|
24
22
|
class Poll < Lanterna; begin
|
@@ -34,7 +32,7 @@ class Poll < Lanterna; begin
|
|
34
32
|
:revents, :short
|
35
33
|
end
|
36
34
|
|
37
|
-
attach_function :poll, [:pointer, :ulong, :int], :int
|
35
|
+
attach_function :poll, [:pointer, :ulong, :int], :int, :blocking => true
|
38
36
|
|
39
37
|
attach_function :malloc, [:size_t], :pointer
|
40
38
|
attach_function :realloc, [:pointer, :size_t], :pointer
|
@@ -72,101 +70,104 @@ class Poll < Lanterna; begin
|
|
72
70
|
pfd[:events] = C::POLLIN
|
73
71
|
end
|
74
72
|
|
75
|
-
def add (
|
76
|
-
super
|
77
|
-
next unless l
|
78
|
-
|
73
|
+
def add (*)
|
74
|
+
super {|l|
|
79
75
|
@set.autorelease = false
|
80
|
-
@set = FFI::AutoPointer.new(C.realloc(@set, (descriptors.length + 1) * C::PollFD.size), C.method(:free))
|
76
|
+
@set = FFI::AutoPointer.new(C.realloc(@set, (@descriptors.length + 1) * C::PollFD.size), C.method(:free))
|
81
77
|
|
82
|
-
pfd = C::PollFD.new(@set + descriptors.length * C::PollFD.size)
|
78
|
+
pfd = C::PollFD.new(@set + (@descriptors.length * C::PollFD.size))
|
83
79
|
pfd[:fd] = l.to_i
|
84
|
-
|
85
|
-
@last = nil
|
86
80
|
}
|
87
81
|
end
|
88
82
|
|
89
|
-
def remove (
|
90
|
-
|
91
|
-
index =
|
83
|
+
def remove (*)
|
84
|
+
super {|l|
|
85
|
+
index = index_of(l)
|
92
86
|
offset = (index + 1) * C::PollFD.size
|
93
87
|
pointer = @set + offset
|
94
88
|
|
95
|
-
pointer.write_bytes((pointer + C::PollFD.size).read_bytes((descriptors.length - index) * C::PollFD.size))
|
89
|
+
pointer.write_bytes((pointer + C::PollFD.size).read_bytes((@descriptors.length - index) * C::PollFD.size))
|
96
90
|
|
97
91
|
@set.autorelease = false
|
98
|
-
@set = FFI::AutoPointer.new(C.realloc(@set,
|
99
|
-
|
100
|
-
super(l)
|
92
|
+
@set = FFI::AutoPointer.new(C.realloc(@set, @descriptors.length * C::PollFD.size), C.method(:free))
|
101
93
|
}
|
102
94
|
end
|
103
95
|
|
104
|
-
def
|
105
|
-
|
96
|
+
def readable! (*)
|
97
|
+
super {|l|
|
98
|
+
pfd = C::PollFD.new(@set + ((index_of(l) + 1) * C::PollFD.size))
|
99
|
+
pfd[:events] |= C::POLLIN
|
100
|
+
}
|
101
|
+
end
|
106
102
|
|
107
|
-
|
103
|
+
def no_readable! (*)
|
104
|
+
super {|l|
|
105
|
+
pfd = C::PollFD.new(@set + ((index_of(l) + 1) * C::PollFD.size))
|
106
|
+
pfd[:events] &= ~C::POLLIN
|
107
|
+
}
|
108
108
|
end
|
109
109
|
|
110
|
-
def
|
111
|
-
|
110
|
+
def writable! (*)
|
111
|
+
super {|l|
|
112
|
+
pfd = C::PollFD.new(@set + ((index_of(l) + 1) * C::PollFD.size))
|
113
|
+
pfd[:events] |= C::POLLOUT
|
114
|
+
}
|
115
|
+
end
|
112
116
|
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
|
117
|
-
|
117
|
+
def no_writable! (*)
|
118
|
+
super {|l|
|
119
|
+
pfd = C::PollFD.new(@set + ((index_of(l) + 1) * C::PollFD.size))
|
120
|
+
pfd[:events] &= ~C::POLLOUT
|
121
|
+
}
|
118
122
|
end
|
119
123
|
|
120
|
-
def
|
121
|
-
|
124
|
+
def available (timeout = nil, &block)
|
125
|
+
return enum_for :available, timeout unless block
|
122
126
|
|
123
|
-
|
124
|
-
[to(:write), to(:error)]
|
125
|
-
else
|
126
|
-
to :write
|
127
|
-
end
|
128
|
-
end
|
127
|
+
FFI.raise_if((length = C.poll(@set, @descriptors.length + 1, timeout ? timeout * 1000 : -1)) < 0)
|
129
128
|
|
130
|
-
|
131
|
-
|
129
|
+
if length == 0
|
130
|
+
yield :timeout, timeout
|
132
131
|
|
133
|
-
|
134
|
-
when :both then C::POLLIN | C::POLLOUT
|
135
|
-
when :read then C::POLLIN
|
136
|
-
when :write then C::POLLOUT
|
132
|
+
return self
|
137
133
|
end
|
138
134
|
|
139
|
-
|
140
|
-
|
141
|
-
|
142
|
-
}
|
143
|
-
|
144
|
-
@last = what
|
145
|
-
end
|
135
|
+
if (C::PollFD.new(@set)[:revents] & C::POLLIN).nonzero?
|
136
|
+
yield :break, @breaker.reason
|
137
|
+
end
|
146
138
|
|
147
|
-
|
139
|
+
n = 0
|
140
|
+
size = C::PollFD.size
|
148
141
|
result = []
|
149
|
-
|
150
|
-
|
151
|
-
|
152
|
-
|
153
|
-
|
142
|
+
while n < @descriptors.length
|
143
|
+
p = C::PollFD.new(@set + ((n + 1) * size))
|
144
|
+
events = p[:revents]
|
145
|
+
fd = p[:fd]
|
146
|
+
lucciola = self[fd]
|
147
|
+
|
148
|
+
if (events & (C::POLLERR | C::POLLHUP)).nonzero?
|
149
|
+
result << [:error, lucciola]
|
150
|
+
else
|
151
|
+
if (events & C::POLLIN).nonzero?
|
152
|
+
result << [:readable, lucciola]
|
153
|
+
end
|
154
|
+
|
155
|
+
if (events & C::POLLOUT).nonzero?
|
156
|
+
result << [:writable, lucciola]
|
157
|
+
end
|
158
|
+
end
|
154
159
|
|
155
|
-
|
156
|
-
|
160
|
+
n += 1
|
161
|
+
end
|
157
162
|
|
158
|
-
|
159
|
-
result << descriptors[n - 1]
|
160
|
-
end
|
161
|
-
}
|
163
|
+
result.each(&block)
|
162
164
|
|
163
|
-
|
165
|
+
self
|
164
166
|
end
|
165
167
|
|
166
|
-
|
167
|
-
|
168
|
-
|
169
|
-
@breaker.flush
|
168
|
+
private
|
169
|
+
def index_of (what)
|
170
|
+
@descriptors.keys.index(what.to_i)
|
170
171
|
end
|
171
172
|
rescue Exception
|
172
173
|
def self.supported?
|
@@ -0,0 +1,211 @@
|
|
1
|
+
#--
|
2
|
+
# Copyleft meh. [http://meh.paranoid.pk | meh@paranoici.org]
|
3
|
+
#
|
4
|
+
# This file is part of barlume.
|
5
|
+
#
|
6
|
+
# barlume is free software: you can redistribute it and/or modify
|
7
|
+
# it under the terms of the GNU Affero General Public License as published
|
8
|
+
# by the Free Software Foundation, either version 3 of the License, or
|
9
|
+
# (at your option) any later version.
|
10
|
+
#
|
11
|
+
# barlume is distributed in the hope that it will be useful,
|
12
|
+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
13
|
+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
14
|
+
# GNU Affero General Public License for more details.
|
15
|
+
#
|
16
|
+
# You should have received a copy of the GNU Affero General Public License
|
17
|
+
# along with barlume. If not, see <http://www.gnu.org/licenses/>.
|
18
|
+
#++
|
19
|
+
|
20
|
+
module Barlume; class Lanterna
|
21
|
+
|
22
|
+
class Port < Lanterna; begin
|
23
|
+
module C
|
24
|
+
extend FFI::Library
|
25
|
+
|
26
|
+
ffi_lib FFI::Library::LIBC
|
27
|
+
|
28
|
+
class PortEvent < FFI::Struct
|
29
|
+
layout \
|
30
|
+
:events, :int,
|
31
|
+
:source, :ushort,
|
32
|
+
:pad, :ushort,
|
33
|
+
:object, :uintptr_t,
|
34
|
+
:user, :pointer
|
35
|
+
end
|
36
|
+
|
37
|
+
class TimeSpec < FFI::Struct
|
38
|
+
layout \
|
39
|
+
:tv_sec, :time_t,
|
40
|
+
:tv_nsec, :int
|
41
|
+
end
|
42
|
+
|
43
|
+
attach_function :port_create, [], :int
|
44
|
+
attach_function :port_associate, [:int, :int, :uintptr_t, :int, :pointer], :int
|
45
|
+
attach_function :port_dissociate, [:int, :int, :uintptr_t], :int
|
46
|
+
attach_function :port_send, [:int, :int, :pointer], :int
|
47
|
+
attach_function :port_sendn, [:pointer, :pointer, :uint, :int, :pointer], :int
|
48
|
+
attach_function :port_get, [:int, :pointer, :pointer], :int
|
49
|
+
attach_function :port_getn, [:int, :pointer, :uint, :pointer, :pointer], :int
|
50
|
+
attach_function :port_alert, [:int, :int, :int, :pointer], :int
|
51
|
+
|
52
|
+
SOURCE_AIO = 1
|
53
|
+
SOURCE_TIMER = 2
|
54
|
+
SOURCE_USER = 3
|
55
|
+
SOURCE_FD = 4
|
56
|
+
SOURCE_ALERT = 5
|
57
|
+
SOURCE_MQ = 6
|
58
|
+
SOURCE_FILE = 7
|
59
|
+
|
60
|
+
POLLIN = 0x001
|
61
|
+
POLLPRI = 0x002
|
62
|
+
POLLOUT = 0x004
|
63
|
+
|
64
|
+
POLLERR = 0x008
|
65
|
+
POLLHUP = 0x010
|
66
|
+
POLLNVAL = 0x020
|
67
|
+
|
68
|
+
POLLRDNORM = 0x040
|
69
|
+
POLLRDBAND = 0x080
|
70
|
+
POLLWRNORM = 0x100
|
71
|
+
POLLWRBAND = 0x200
|
72
|
+
|
73
|
+
POLLMSG = 0x0400
|
74
|
+
POLLREMOVE = 0x1000
|
75
|
+
POLLRDHUP = 0x2000
|
76
|
+
end
|
77
|
+
|
78
|
+
def self.supported?
|
79
|
+
true
|
80
|
+
end
|
81
|
+
|
82
|
+
def self.new (*)
|
83
|
+
super.tap {|c|
|
84
|
+
ObjectSpace.define_finalizer c, finalizer(c.instance_variable_get :@fd)
|
85
|
+
}
|
86
|
+
end
|
87
|
+
|
88
|
+
def self.finalizer (fd)
|
89
|
+
proc {
|
90
|
+
IO.for_fd(fd).close
|
91
|
+
}
|
92
|
+
end
|
93
|
+
|
94
|
+
attr_reader :size
|
95
|
+
|
96
|
+
def initialize
|
97
|
+
super
|
98
|
+
|
99
|
+
FFI.raise_if((@fd = C.port_create) < 0)
|
100
|
+
FFI.raise_if(C.port_associate(@fd, C::SOURCE_FD, @breaker.to_i, C::POLLIN, nil) < 0)
|
101
|
+
|
102
|
+
@timeout = C::TimeSpec.new
|
103
|
+
@length = FFI::MemoryPointer.new :uint
|
104
|
+
|
105
|
+
self.size = 4096
|
106
|
+
end
|
107
|
+
|
108
|
+
def size= (n)
|
109
|
+
@events = FFI::MemoryPointer.new C::PortEvent.size, n
|
110
|
+
@size = @events.size / C::PortEvent.size
|
111
|
+
end
|
112
|
+
|
113
|
+
def add (*)
|
114
|
+
super {|l|
|
115
|
+
FFI.raise_if(C.port_associate(@fd, C::SOURCE_FD, l.to_i, C::POLLIN, nil) < 0)
|
116
|
+
}
|
117
|
+
end
|
118
|
+
|
119
|
+
def remove (*)
|
120
|
+
super {|l|
|
121
|
+
begin
|
122
|
+
FFI.raise_if(C.port_dissociate(@fd, C::SOURCE_FD, l.to_i) < 0)
|
123
|
+
rescue Errno::EIDRM; end
|
124
|
+
}
|
125
|
+
end
|
126
|
+
|
127
|
+
def readable! (*)
|
128
|
+
super {|l|
|
129
|
+
FFI.raise_if(C.port_associate(@fd, C::SOURCE_FD, l.to_i, C::POLLIN | (l.writable? ? C::POLLOUT : 0), nil) < 0)
|
130
|
+
}
|
131
|
+
end
|
132
|
+
|
133
|
+
def no_readable! (*)
|
134
|
+
super {|l|
|
135
|
+
FFI.raise_if(C.port_associate(@fd, C::SOURCE_FD, l.to_i, (l.writable? ? C::POLLOUT : 0), nil) < 0)
|
136
|
+
}
|
137
|
+
end
|
138
|
+
|
139
|
+
def writable! (*)
|
140
|
+
super {|l|
|
141
|
+
FFI.raise_if(C.port_associate(@fd, C::SOURCE_FD, l.to_i, C::POLLOUT | (l.readable? ? C::POLLIN : 0), nil) < 0)
|
142
|
+
}
|
143
|
+
end
|
144
|
+
|
145
|
+
def no_writable! (*)
|
146
|
+
super {|l|
|
147
|
+
FFI.raise_if(C.port_associate(@fd, C::SOURCE_FD, l.to_i, (l.readable? ? C::POLLIN : 0), nil) < 0)
|
148
|
+
}
|
149
|
+
end
|
150
|
+
|
151
|
+
def available (timeout = nil, &block)
|
152
|
+
return enum_for :available, timeout unless block
|
153
|
+
|
154
|
+
if timeout
|
155
|
+
@timeout[:tv_sec] = timeout.to_i
|
156
|
+
@timeout[:tv_nsec] = (timeout - timeout.to_i) * 1000
|
157
|
+
end
|
158
|
+
|
159
|
+
@length.write_uint 1
|
160
|
+
|
161
|
+
if C.port_getn(@fd, @events, size, @length, timeout ? @timeout : nil) < 0
|
162
|
+
FFI.raise_unless FFI.errno == Errno::ETIME::Errno
|
163
|
+
|
164
|
+
yield :timeout, timeout
|
165
|
+
|
166
|
+
return self
|
167
|
+
end
|
168
|
+
|
169
|
+
n = 0
|
170
|
+
size = C::PortEvent.size
|
171
|
+
length = @length.read_uint
|
172
|
+
while n < length
|
173
|
+
p = C::PortEvent.new(@events + (n * size))
|
174
|
+
events = p[:events]
|
175
|
+
fd = p[:object]
|
176
|
+
lucciola = self[fd]
|
177
|
+
|
178
|
+
if lucciola
|
179
|
+
FFI.raise_if(C.port_associate(@fd, C::SOURCE_FD, lucciola.to_i, (lucciola.readable? ? C::POLLIN : 0) | (lucciola.writable? ? C::POLLOUT : 0), nil) < 0)
|
180
|
+
|
181
|
+
if (events & (C::POLLERR | C::POLLHUP)).nonzero?
|
182
|
+
yield :error, lucciola
|
183
|
+
else
|
184
|
+
if (events & C::POLLIN).nonzero?
|
185
|
+
yield :readable, lucciola
|
186
|
+
end
|
187
|
+
|
188
|
+
if (events & C::POLLOUT).nonzero?
|
189
|
+
yield :writable, lucciola
|
190
|
+
end
|
191
|
+
end
|
192
|
+
elsif fd == @breaker.to_i
|
193
|
+
FFI.raise_if(C.port_associate(@fd, C::SOURCE_FD, @breaker.to_i, C::POLLIN, nil) < 0)
|
194
|
+
|
195
|
+
yield :break, @breaker.reason
|
196
|
+
else
|
197
|
+
raise "#{fd} isn't trapped here"
|
198
|
+
end
|
199
|
+
|
200
|
+
n += 1
|
201
|
+
end
|
202
|
+
|
203
|
+
self
|
204
|
+
end
|
205
|
+
rescue Exception
|
206
|
+
def self.supported?
|
207
|
+
false
|
208
|
+
end
|
209
|
+
end; end
|
210
|
+
|
211
|
+
end; end
|