async-io 1.8.0 → 1.8.1

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: b298c4c118c511eaabda86500a8d08bf02b01cd156e0858cb962f4d3005ce665
4
- data.tar.gz: 1a231a883488b441d599991043409204b2f282df470fdd8b15d18afa6f9b8e06
3
+ metadata.gz: a8d2a5bb8ab12fac26be40774eb239426d8533b68b42d95866884e03fda6e824
4
+ data.tar.gz: 1cf9d4063d70649b936354195b83bd25eb49ff53b7a76d33178d2b80269cd319
5
5
  SHA512:
6
- metadata.gz: 8b87b6ca52a9e6164e4c6e549eaa2581d2c71908488f1f8235f0a2a8bbe25dd6e551a419b65f9ebd4be6b5c0182e99315c552cf36cc309777d311cd79397accc
7
- data.tar.gz: 1cd79fdb63398e13ce10041b4facf4bb1dc5498065c18eac8f3265cd2f842f6360b6f31e2b41acf11df29c62096810940050f4e51a7bceb4e9e242af9cfbf81d
6
+ metadata.gz: 7b58035212d0d4b063e5c511bfce3ded7f02e5e8524e4b0c47d2e654ca447d92f8f65441cd5ab577c413eacfff71e3ec1dd26c224fd72bf18decc00fcd791334
7
+ data.tar.gz: 3570983e37a2d827b5ead5bc7d0c2b36a2522bb95241ec54334923e999d2a51ec3829649ccd8eae9af1a501695d5f11c9b1d1469f0bb04508a5ccb2b4a0be938
@@ -75,6 +75,9 @@ module Async
75
75
  def self.wrap(socket, context)
76
76
  io = @wrapped_klass.new(socket.to_io, context)
77
77
 
78
+ # We detach the socket from the reactor, otherwise it's possible to add the file descriptor to the selector twice, which is bad.
79
+ socket.reactor = nil
80
+
78
81
  # This ensures that when the internal IO is closed, it also closes the internal socket:
79
82
  io.sync_close = true
80
83
 
@@ -24,7 +24,11 @@ require_relative 'generic'
24
24
  module Async
25
25
  module IO
26
26
  class Stream
27
- def initialize(io, block_size: 1024*8, sync: true)
27
+ # The default block size for IO buffers.
28
+ # BLOCK_SIZE = ENV.fetch('BLOCK_SIZE', 1024*16).to_i
29
+ BLOCK_SIZE = 1024*8
30
+
31
+ def initialize(io, block_size: BLOCK_SIZE, sync: true)
28
32
  @io = io
29
33
  @eof = false
30
34
 
@@ -45,11 +49,7 @@ module Async
45
49
  return '' if size == 0
46
50
 
47
51
  if size
48
- if size <= @block_size
49
- fill_read_buffer until @eof or @read_buffer.size >= size
50
- else
51
- fill_read_buffer(size - @read_buffer.size) until @eof or @read_buffer.size >= size
52
- end
52
+ fill_read_buffer until @eof or @read_buffer.size >= size
53
53
  else
54
54
  fill_read_buffer until @eof
55
55
  end
@@ -68,6 +68,28 @@ module Async
68
68
  return consume_read_buffer(size)
69
69
  end
70
70
 
71
+ # Efficiently read data from the stream until encountering pattern.
72
+ # @param pattern [String] The pattern to match.
73
+ # @return [String] The contents of the stream up until the pattern, which is consumed but not returned.
74
+ def read_until(pattern, offset = 0)
75
+ until index = @read_buffer.index(pattern, offset)
76
+ offset = @read_buffer.size
77
+
78
+ return unless fill_read_buffer
79
+ end
80
+
81
+ matched = @read_buffer.slice!(0, index)
82
+ @read_buffer.slice!(0, pattern.bytesize)
83
+
84
+ return matched
85
+ end
86
+
87
+ def peek
88
+ until yield(@read_buffer) || @eof
89
+ fill_read_buffer
90
+ end
91
+ end
92
+
71
93
  # Writes `string` to the buffer. When the buffer is full or #sync is true the
72
94
  # buffer is flushed to the underlying `io`.
73
95
  # @param string the string to write to the buffer.
@@ -79,7 +101,8 @@ module Async
79
101
  @write_buffer << string
80
102
 
81
103
  if @write_buffer.size >= @block_size
82
- flush
104
+ syswrite(@write_buffer)
105
+ @write_buffer.clear
83
106
  end
84
107
  end
85
108
 
@@ -117,8 +140,8 @@ module Async
117
140
 
118
141
  # Closes the stream and flushes any unwritten data.
119
142
  def close
120
- flush rescue nil
121
-
143
+ flush
144
+ ensure
122
145
  @io.close
123
146
  end
124
147
 
@@ -131,41 +154,24 @@ module Async
131
154
 
132
155
  alias eof eof?
133
156
 
134
- # Efficiently read data from the stream until encountering pattern.
135
- # @param pattern [String] The pattern to match.
136
- # @return [String] The contents of the stream up until the pattern, which is consumed but not returned.
137
- def read_until(pattern)
138
- index = @read_buffer.index(pattern)
139
-
140
- until index
141
- offset = @read_buffer.size
142
-
143
- fill_read_buffer
144
-
145
- return if @eof
146
-
147
- index = @read_buffer.index(pattern, offset)
148
- end
149
-
150
- matched = @read_buffer.slice!(0, index)
151
- @read_buffer.slice!(0, pattern.bytesize)
152
-
153
- return matched
154
- end
155
-
156
- def peek
157
- until yield(@read_buffer) || @eof
158
- fill_read_buffer
159
- end
160
- end
161
-
162
157
  private
163
158
 
164
159
  # Fills the buffer from the underlying stream.
165
- def fill_read_buffer(size = @block_size)
166
- if !sysread(size, @read_buffer)
167
- @eof = true
160
+ def fill_read_buffer
161
+ Async.logger.debug(self){"fill_read_buffer..."}
162
+
163
+ # Can we read directly into the buffer? (Ruby doesn't support append, only replace):
164
+ if chunk = @io.read(@block_size)
165
+ Async.logger.debug(self){"@io.read -> #{chunk.size} bytes"}
166
+ @read_buffer << chunk
167
+ return true
168
168
  end
169
+
170
+ Async.logger.debug(self){"@io.read -> #{chunk.inspect}"}
171
+
172
+ # We didn't read anything, so we must be at eof:
173
+ @eof = true
174
+ return false
169
175
  end
170
176
 
171
177
  # Consumes at most `size` bytes from the buffer.
@@ -209,15 +215,6 @@ module Async
209
215
 
210
216
  return written
211
217
  end
212
-
213
- # Read to
214
- def sysread(size, buffer)
215
- if buffer.empty?
216
- @io.read(size, buffer)
217
- elsif chunk = @io.read(size)
218
- buffer << chunk
219
- end
220
- end
221
218
  end
222
219
  end
223
220
  end
@@ -20,6 +20,6 @@
20
20
 
21
21
  module Async
22
22
  module IO
23
- VERSION = "1.8.0"
23
+ VERSION = "1.8.1"
24
24
  end
25
25
  end
@@ -49,6 +49,17 @@ RSpec.describe Async::IO::Stream do
49
49
  end
50
50
  end
51
51
 
52
+ describe '#read_until' do
53
+ it "can read a line" do
54
+ io.write("hello\nworld\n")
55
+ io.seek(0)
56
+
57
+ expect(stream.read_until("\n")).to be == 'hello'
58
+ expect(stream.read_until("\n")).to be == 'world'
59
+ expect(stream.read_until("\n")).to be_nil
60
+ end
61
+ end
62
+
52
63
  describe '#flush' do
53
64
  it "should not call write if write buffer is empty" do
54
65
  expect(io).to_not receive(:write)
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: async-io
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.8.0
4
+ version: 1.8.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Samuel Williams
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2018-04-26 00:00:00.000000000 Z
11
+ date: 2018-04-27 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: async