barlume 0.0.1.rc.1 → 0.0.1.rc.2

Sign up to get free protection for your applications and to get access to all the features.
@@ -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