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.
@@ -24,59 +24,37 @@ class Select < Lanterna
24
24
  true
25
25
  end
26
26
 
27
- def add (*)
28
- super.tap {
29
- @descriptors_with_breaker = nil
30
- }
31
- end
27
+ def available (timeout = nil, &block)
28
+ return enum_for :available, timeout unless block
32
29
 
33
- def remove (*)
34
- super.tap {
35
- @descriptors_with_breaker = nil
36
- }
37
- end
30
+ readable, writable, error = IO.select([@breaker.to_io] + @readable.values, @writable.values, @descriptors.values, timeout)
38
31
 
39
- def available (timeout = nil)
40
- readable, writable, error = IO.select(descriptors_with_breaker, descriptors, descriptors, timeout)
32
+ unless readable
33
+ yield :timeout, timeout
41
34
 
42
- if readable && readable.delete(@breaker.to_io)
43
- @breaker.flush
35
+ return self
44
36
  end
45
37
 
46
- Available.new(readable || [], writable || [], error || [])
47
- end
38
+ error.each {|io|
39
+ readable.delete(io)
40
+ writable.delete(io)
48
41
 
49
- def readable (timeout = nil)
50
- readable, writable, error = IO.select(descriptors_with_breaker, nil, descriptors, timeout)
51
-
52
- if readable && readable.delete(@breaker.to_io)
53
- @breaker.flush
54
- end
55
-
56
- if report_errors?
57
- [readable || [], error || []]
58
- else
59
- readable || []
60
- end
61
- end
62
-
63
- def writable (timeout = nil)
64
- readable, writable, error = IO.select([@breaker], descriptors, descriptors, timeout)
42
+ yield :error, io
43
+ }
65
44
 
66
- if readable && readable.delete(@breaker.to_io)
67
- @breaker.flush
68
- end
45
+ readable.each {|io|
46
+ if io == @breaker.to_io
47
+ yield :break, @breaker.reason
48
+ else
49
+ yield :readable, io
50
+ end
51
+ }
69
52
 
70
- if report_errors?
71
- [writable || [], error || []]
72
- else
73
- writable || []
74
- end
75
- end
53
+ writable.each {|io|
54
+ yield :writable, io
55
+ }
76
56
 
77
- private
78
- def descriptors_with_breaker
79
- @descriptors_with_breaker ||= [@breaker.to_io] + descriptors
57
+ self
80
58
  end
81
59
  end
82
60
 
@@ -18,6 +18,7 @@
18
18
  #++
19
19
 
20
20
  require 'fcntl'
21
+ require 'socket'
21
22
 
22
23
  module Barlume
23
24
 
@@ -44,13 +45,7 @@ class Lucciola
44
45
 
45
46
  def method_missing (id, *args, &block)
46
47
  if @io.respond_to? id
47
- begin
48
- return @io.__send__ id, *args, &block
49
- rescue EOFError
50
- @closed = true
51
-
52
- raise
53
- end
48
+ return @io.__send__ id, *args, &block
54
49
  end
55
50
 
56
51
  super
@@ -74,8 +69,16 @@ class Lucciola
74
69
  @closed or @io.respond_to?(:closed?) ? @io.closed? : false
75
70
  end
76
71
 
72
+ def alive?
73
+ if @io.is_a?(Socket)
74
+ !!@io.getsockopt(Socket::SOL_SOCKET, Socket::SO_TYPE).nonzero?
75
+ else
76
+ !@io.closed?
77
+ end
78
+ end
79
+
77
80
  def nonblocking?
78
- (@io.fcntl(Fcntl::F_GETFL, 0) & Fcntl::O_NONBLOCK).nonzero?
81
+ !(@io.fcntl(Fcntl::F_GETFL, 0) & Fcntl::O_NONBLOCK).zero?
79
82
  end
80
83
 
81
84
  alias asynchronous? nonblocking?
@@ -84,12 +87,220 @@ class Lucciola
84
87
  !nonblocking?
85
88
  end
86
89
 
90
+ alias synchronous? blocking?
91
+
87
92
  def blocking!
88
- @io.fcntl(Fcntl::F_SETFL, @io.fcntl(Fcntl::F_GETFL, 0) | Fcntl::O_NONBLOCK)
93
+ if block_given?
94
+ if was_nonblocking = nonblocking?
95
+ @io.fcntl(Fcntl::F_SETFL, @io.fcntl(Fcntl::F_GETFL, 0) & ~Fcntl::O_NONBLOCK)
96
+ end
97
+
98
+ begin
99
+ return yield
100
+ ensure
101
+ nonblocking! if was_nonblocking
102
+ end
103
+ else
104
+ @io.fcntl(Fcntl::F_SETFL, @io.fcntl(Fcntl::F_GETFL, 0) & ~Fcntl::O_NONBLOCK)
105
+ end
106
+
107
+ self
89
108
  end
90
109
 
110
+ alias sychronous! blocking!
111
+
91
112
  def nonblocking!
92
- @io.fcntl(Fcntl::F_SETFL, @io.fcntl(Fcntl::F_GETFL, 0) & ~Fcntl::O_NONBLOCK)
113
+ if block_given?
114
+ if was_blocking = blocking?
115
+ @io.fcntl(Fcntl::F_SETFL, @io.fcntl(Fcntl::F_GETFL, 0) | Fcntl::O_NONBLOCK)
116
+ end
117
+
118
+ begin
119
+ return yield
120
+ ensure
121
+ blocking! if was_blocking
122
+ end
123
+ else
124
+ @io.fcntl(Fcntl::F_SETFL, @io.fcntl(Fcntl::F_GETFL, 0) | Fcntl::O_NONBLOCK)
125
+ end
126
+
127
+ self
128
+ end
129
+
130
+ alias asynchronous! nonblocking!
131
+
132
+ def no_delay?
133
+ raise 'no_delay is TCP only' unless @io.is_a? TCPSocket
134
+
135
+ @io.getsockopt(Socket::IPPROTO_TCP, Socket::TCP_NODELAY).nonzero?
136
+ end
137
+
138
+ def delay?
139
+ !no_delay?
140
+ end
141
+
142
+ def no_delay!
143
+ raise 'no_delay is TCP only' unless @io.is_a? TCPSocket
144
+
145
+ @io.setsockopt(Socket::IPPROTO_TCP, Socket::TCP_NODELAY, 1)
146
+
147
+ self
148
+ end
149
+
150
+ def delay!
151
+ raise 'no_delay is TCP only' unless @io.is_a? TCPSocket
152
+
153
+ @io.setsockopt(Socket::IPPROTO_TCP, Socket::TCP_NODELAY, 0)
154
+
155
+ self
156
+ end
157
+
158
+ def transaction
159
+ unless to_io.is_a?(TCPSocket) && Socket.const_defined?(:TCP_CORK)
160
+ raise 'transaction is not supported on this kind of IO'
161
+ end
162
+
163
+ begin
164
+ @io.setsockopt Socket::IPPROTO_TCP, Socket::TCP_CORK, 1
165
+
166
+ yield self
167
+ ensure
168
+ @io.setsockopt Socket::IPPROTO_TCP, Socket::TCP_CORK, 0
169
+ end
170
+
171
+ self
172
+ end
173
+
174
+ def trap_in (lanterna)
175
+ raise 'already trapped' if @lanterna
176
+
177
+ @lanterna = lanterna
178
+ end
179
+
180
+ def set_free
181
+ raise 'not trapped' unless @lanterna
182
+
183
+ if @lanterna.has?(self)
184
+ @lanterna.remove(self)
185
+ end
186
+
187
+ @lanterna = nil
188
+ end
189
+
190
+ def readable?
191
+ raise 'not trapped' unless @lanterna
192
+
193
+ @lanterna.readable? self
194
+ end
195
+
196
+ def readable!
197
+ raise 'not trapped' unless @lanterna
198
+
199
+ @lanterna.readable! self
200
+
201
+ self
202
+ end
203
+
204
+ def no_readable!
205
+ raise 'not trapped' unless @lanterna
206
+
207
+ @lanterna.no_readable! self
208
+
209
+ self
210
+ end
211
+
212
+ def writable?
213
+ raise 'not trapped' unless @lanterna
214
+
215
+ @lanterna.writable? self
216
+ end
217
+
218
+ def writable!
219
+ raise 'not trapped' unless @lanterna
220
+
221
+ @lanterna.writable! self
222
+
223
+ self
224
+ end
225
+
226
+ def no_writable!
227
+ raise 'not trapped' unless @lanterna
228
+
229
+ @lanterna.no_writable! self
230
+
231
+ self
232
+ end
233
+
234
+ def delete!
235
+ raise 'not trapped' unless @lanterna
236
+
237
+ @lanterna.remove self
238
+
239
+ self
240
+ end
241
+
242
+ def accept (*args)
243
+ if blocking?
244
+ @io.accept(*args)
245
+ else
246
+ @io.accept_nonblock(*args)
247
+ end
248
+ end
249
+
250
+ def accept_nonblock (*args)
251
+ nonblocking! {
252
+ accept(*args)
253
+ }
254
+ end
255
+
256
+ def accept_block (*args)
257
+ blocking! {
258
+ accept(*args)
259
+ }
260
+ end
261
+
262
+ def read (*args)
263
+ if (result = @io.sysread(*args)).nil?
264
+ @closed = true
265
+ end
266
+
267
+ result
268
+ rescue EOFError
269
+ @closed = true
270
+
271
+ raise
272
+ end
273
+
274
+ def read_nonblock (*args)
275
+ nonblocking! {
276
+ read(*args)
277
+ }
278
+ end
279
+
280
+ def read_block (*args)
281
+ blocking! {
282
+ read(*args)
283
+ }
284
+ end
285
+
286
+ def write (*args)
287
+ @io.syswrite(*args)
288
+ rescue EOFError
289
+ @closed = true
290
+
291
+ raise
292
+ end
293
+
294
+ def write_nonblock (*args)
295
+ nonblocking! {
296
+ write(*args)
297
+ }
298
+ end
299
+
300
+ def write_block (*args)
301
+ blocking! {
302
+ write(*args)
303
+ }
93
304
  end
94
305
 
95
306
  def to_io
@@ -19,6 +19,6 @@
19
19
 
20
20
  module Barlume
21
21
  def self.version
22
- '0.0.1.rc.1'
22
+ '0.0.1.rc.2'
23
23
  end
24
24
  end
@@ -0,0 +1,17 @@
1
+ #! /usr/bin/env ruby
2
+ require 'socket'
3
+ require 'thread'
4
+
5
+ 2.times.map {
6
+ Thread.new {
7
+ sockets = []
8
+
9
+ 100.times {
10
+ sockets << TCPSocket.new('localhost', 43215)
11
+ }
12
+
13
+ sockets.each {|socket|
14
+ socket.puts 'a' * 4096
15
+ }
16
+ }
17
+ }.each(&:join)
@@ -0,0 +1,35 @@
1
+ #! /usr/bin/env ruby
2
+ require 'barlume'
3
+
4
+ lantern = Barlume::Lanterna.best
5
+ server = lantern.add(TCPServer.new(43215))
6
+ bytes = 0
7
+ clients = 0
8
+
9
+ puts "Using #{lantern.name}..."
10
+
11
+ trap 'INT' do
12
+ puts "Received #{bytes} bytes from #{clients} clients"
13
+ exit!
14
+ end
15
+
16
+ loop do
17
+ lantern.readable.each {|lucciola|
18
+ if lucciola == server
19
+ while client = server.accept_nonblock rescue nil
20
+ clients += 1
21
+ lantern.add(client)
22
+ end
23
+ else
24
+ begin
25
+ while value = lucciola.read(2048)
26
+ bytes += value.bytesize
27
+ end
28
+ rescue EOFError, Errno::EAGAIN; end
29
+
30
+ if lucciola.closed?
31
+ lantern.remove(lucciola)
32
+ end
33
+ end
34
+ }
35
+ end
@@ -0,0 +1,28 @@
1
+ var net = require('net');
2
+
3
+ var created = 255,
4
+ answered = 0,
5
+ errored = 0,
6
+ time = +new Date;
7
+
8
+
9
+ function createClient() {
10
+ var socket = net.createConnection(1337, '127.0.0.1');
11
+ socket.setEncoding('utf8');
12
+ socket
13
+ .on('connect', function() { socket.write('lol'); })
14
+ .on('data', function(c) {
15
+ errored += c !== 'lol' ? 1 : 0;
16
+ if(++answered === created) {
17
+ var t = +new Date - time;
18
+ console.log('Time (ms): ' + t);
19
+ console.log('Errored: ' + errored);
20
+ process.exit();
21
+ }
22
+ });
23
+ }
24
+
25
+ for(var i=0; i <= created; i++) {
26
+ createClient();
27
+ }
28
+
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: barlume
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.1.rc.1
4
+ version: 0.0.1.rc.2
5
5
  prerelease: 6
6
6
  platform: ruby
7
7
  authors:
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2012-07-19 00:00:00.000000000 Z
12
+ date: 2012-07-29 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: ffi
@@ -27,6 +27,22 @@ dependencies:
27
27
  - - ! '>='
28
28
  - !ruby/object:Gem::Version
29
29
  version: '0'
30
+ - !ruby/object:Gem::Dependency
31
+ name: backports
32
+ requirement: !ruby/object:Gem::Requirement
33
+ none: false
34
+ requirements:
35
+ - - ! '>='
36
+ - !ruby/object:Gem::Version
37
+ version: '0'
38
+ type: :runtime
39
+ prerelease: false
40
+ version_requirements: !ruby/object:Gem::Requirement
41
+ none: false
42
+ requirements:
43
+ - - ! '>='
44
+ - !ruby/object:Gem::Version
45
+ version: '0'
30
46
  description:
31
47
  email: meh@paranoici.org
32
48
  executables: []
@@ -35,16 +51,22 @@ extra_rdoc_files: []
35
51
  files:
36
52
  - README.md
37
53
  - barlume.gemspec
38
- - examples/test.rb
54
+ - examples/echo.rb
55
+ - examples/slowpokes.rb
39
56
  - lib/barlume.rb
40
57
  - lib/barlume/lanterna.rb
58
+ - lib/barlume/lanterna/dpoll.rb
41
59
  - lib/barlume/lanterna/epoll.rb
60
+ - lib/barlume/lanterna/helpers.rb
42
61
  - lib/barlume/lanterna/kqueue.rb
43
62
  - lib/barlume/lanterna/poll.rb
63
+ - lib/barlume/lanterna/port.rb
44
64
  - lib/barlume/lanterna/select.rb
45
- - lib/barlume/lanterna/utils.rb
46
65
  - lib/barlume/lucciola.rb
47
66
  - lib/barlume/version.rb
67
+ - test/benchmark.client.rb
68
+ - test/benchmark.server.rb
69
+ - test/flood.js
48
70
  homepage: http://github.com/meh/barlume
49
71
  licenses: []
50
72
  post_install_message:
@@ -69,4 +91,7 @@ rubygems_version: 1.8.24
69
91
  signing_key:
70
92
  specification_version: 3
71
93
  summary: A dim light over asynchronous I/O land.
72
- test_files: []
94
+ test_files:
95
+ - test/benchmark.client.rb
96
+ - test/benchmark.server.rb
97
+ - test/flood.js