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.
@@ -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
- if C.kevent(@fd, C::EV_SET(C::Kevent.new, @breaker.to_i, C::EVFILT_READ, C::EV_ADD | C::EV_ENABLE, 0, 0, FFI::Pointer.new(C::MAX)), 1, nil, 0, nil) < 0
109
- FFI.raise
110
- end
108
+ @timeout = C::TimeSpec.new
109
+ @ev = C::Kevent.new
111
110
 
112
- self.size = 4096
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
- def size
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 add (*)
124
- super.tap {
125
- @last = nil
126
- }
127
- end
121
+ def edge_triggered?; @edge; end
122
+ def level_triggered?; !@edge; end
128
123
 
129
- def remove (what)
130
- super.tap {|l|
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
- begin
136
- FFI.raise_if(C.kevent(@fd, C::EV_SET(C::Kevent.new, what.to_i, C::EVFILT_WRITE, C::EV_DELETE | C::EV_DISABLE, 0, 0, 0), 1, nil, 0, nil) < 0)
137
- rescue Errno::ENOENT; end
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
- @last = nil
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 available (timeout = nil)
144
- set :both; kevent timeout
145
-
146
- Available.new(to(:read), to(:write), to(:error))
147
- end
138
+ def level_triggered!
139
+ @edge = false
148
140
 
149
- def readable (timeout = nil)
150
- set :read; kevent timeout
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
- if report_errors?
153
- [to(:read), to(:error)]
154
- else
155
- to :read
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 writable (timeout = nil)
160
- set :write; kevent timeout
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
- if report_errors?
163
- [to(:write), to(:error)]
164
- else
165
- to :write
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 set (what)
170
- return if @last == what
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
- ev = C::Kevent.new
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
- if what == :read
175
- descriptors.each_with_index {|descriptor, index|
176
- index = FFI::Pointer.new(index)
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
- FFI.raise_if(C.kevent(@fd, C::EV_SET(ev, descriptor.to_i, C::EVFILT_READ, C::EV_ADD | C::EV_ENABLE, 0, 0, index), 1, nil, 0, nil) < 0)
179
- FFI.raise_if(C.kevent(@fd, C::EV_SET(ev, descriptor.to_i, C::EVFILT_WRITE, C::EV_ADD | C::EV_DISABLE, 0, 0, index), 1, nil, 0, nil) < 0)
180
- }
181
- elsif what == :write
182
- descriptors.each_with_index {|descriptor, index|
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
- FFI.raise_if(C.kevent(@fd, C::EV_SET(ev, descriptor.to_i, C::EVFILT_WRITE, C::EV_ADD | C::EV_ENABLE, 0, 0, index), 1, nil, 0, nil) < 0)
186
- FFI.raise_if(C.kevent(@fd, C::EV_SET(ev, descriptor.to_i, C::EVFILT_READ, C::EV_ADD | C::EV_DISABLE, 0, 0, index), 1, nil, 0, nil) < 0)
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
- FFI.raise_if(C.kevent(@fd, C::EV_SET(ev, descriptor.to_i, C::EVFILT_WRITE, C::EV_ADD | C::EV_ENABLE, 0, 0, index), 1, nil, 0, nil) < 0)
193
- FFI.raise_if(C.kevent(@fd, C::EV_SET(ev, descriptor.to_i, C::EVFILT_READ, C::EV_ADD | C::EV_ENABLE, 0, 0, index), 1, nil, 0, nil) < 0)
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
- @last = what
198
- end
196
+ FFI.raise_if((length = C.kevent(@fd, nil, 0, @events, size, timeout ? @timeout : nil)) < 0)
199
197
 
200
- def to (what)
201
- result = []
198
+ if length == 0
199
+ yield :timeout, timeout
202
200
 
203
- if what == :error
204
- 0.upto(@length - 1) {|n|
205
- p = C::Kevent.new(@events + (n * C::Kevent.size))
206
- index = p[:udata].address
201
+ return self
202
+ end
207
203
 
208
- if p != index && (p[:flags] & C::EV_ERROR).nonzero?
209
- result << descriptors[index]
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
- else
213
- filter = case what
214
- when :read then C::EVFILT_READ
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
- 0.upto(@length - 1) {|n|
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
- FFI.raise_if((@length = C.kevent(@fd, nil, 0, @events, size, timeout)) < 0)
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 (what)
76
- super.tap {|l|
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 (what)
90
- Lucciola.wrap(what).tap {|l|
91
- index = descriptors.index(l)
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, (descriptors.length) * C::PollFD.size), C.method(:free))
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 available (timeout = nil)
105
- set :both; poll timeout
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
- Available.new(to(:read), to(:write), to(:error))
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 readable (timeout = nil)
111
- set :read; poll timeout
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
- if report_errors?
114
- [to(:read), to(:error)]
115
- else
116
- to :read
117
- end
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 writable (timeout = nil)
121
- set :write; poll timeout
124
+ def available (timeout = nil, &block)
125
+ return enum_for :available, timeout unless block
122
126
 
123
- if report_errors?
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
- def set (what)
131
- return if @last == what
129
+ if length == 0
130
+ yield :timeout, timeout
132
131
 
133
- events = case what
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
- 1.upto(descriptors.length) {|n|
140
- pfd = C::PollFD.new(@set + (n * C::PollFD.size))
141
- pfd[:events] = events
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
- def to (what)
139
+ n = 0
140
+ size = C::PollFD.size
148
141
  result = []
149
- events = case what
150
- when :read then C::POLLIN
151
- when :write then C::POLLOUT
152
- when :error then C::POLLERR | C::POLLHUP
153
- end
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
- 1.upto(descriptors.length) {|n|
156
- pfd = C::PollFD.new(@set + (n * C::PollFD.size))
160
+ n += 1
161
+ end
157
162
 
158
- if (pfd[:revents] & events).nonzero?
159
- result << descriptors[n - 1]
160
- end
161
- }
163
+ result.each(&block)
162
164
 
163
- result
165
+ self
164
166
  end
165
167
 
166
- def poll (timeout = nil)
167
- FFI.raise_if(C.poll(@set, descriptors.length + 1, timeout ? timeout * 1000 : -1) < 0)
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