lightio 0.4.2 → 0.4.3

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
- SHA1:
3
- metadata.gz: d60e525147d0be04ceecef1b5d5707dbaeeba6d1
4
- data.tar.gz: 69c611c348c2837484857e850834e6bc93fc6c44
2
+ SHA256:
3
+ metadata.gz: 0461dd68b60dfa05c34fabdcd916ef074de8e634634174fc5253dbc5083d221a
4
+ data.tar.gz: 0715bf64fe6b6150d629136b621eec9d6a79c72dc7110e19082dd4e59b14a0a9
5
5
  SHA512:
6
- metadata.gz: a53025d4e89dcfab86d8c41af53b0a8ac078d86d9a220549a364638be22be4da133c303ce3e738a910b6a9844907a5c4ee506f27fa041728930770ea0ac1ea61
7
- data.tar.gz: 60e88d7aed7cf946368cc1f2aa6786d644c00d30fa9f2c0855b5cb9fb1c41d4837e0e98b52beb85fbaa761af9c39beaa92dda8cfcbdea6afb584b0859bcc831f
6
+ metadata.gz: 8c7796bdbcb7cc253979813fe394fe65dec6eab3ee53384042a267fa5cf2fef316a946b732e0adc42f1c343c53c4602f7149617d7626066984156ea8fc581d0b
7
+ data.tar.gz: 71e6b9f3b63d6e236ea6fb5b0629f6634fe9d60d459d63f78fd5b7406027ca5858add3e0f0d502278938db0d6e2b4d8e930171850a9fa7305b695b6fc5de3ce5
data/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- lightio (0.4.2)
4
+ lightio (0.4.3)
5
5
  nio4r (~> 2.2)
6
6
 
7
7
  GEM
data/README.md CHANGED
@@ -5,6 +5,7 @@
5
5
  [![Build Status](https://travis-ci.org/socketry/lightio.svg?branch=master)](https://travis-ci.org/socketry/lightio)
6
6
  [![Coverage Status](https://coveralls.io/repos/github/socketry/lightio/badge.svg?branch=master)](https://coveralls.io/github/socketry/lightio?branch=master)
7
7
  [![MIT licensed](https://img.shields.io/badge/license-MIT-blue.svg)](https://github.com/jjyr/lightio/blob/master/LICENSE.txt)
8
+ [![Gitter](https://badges.gitter.im/join.svg)](https://gitter.im/lightio-dev/Lobby)
8
9
 
9
10
  LightIO provide green thread to ruby. Like Golang's goroutine, or Crystal's fiber. In LightIO it called beam.
10
11
 
@@ -12,6 +12,7 @@ module LightIO::Core
12
12
  @value = nil
13
13
  @ioloop = IOloop.current
14
14
  @state = :init
15
+ @light_fiber = nil
15
16
  end
16
17
 
17
18
  def done?
@@ -98,6 +98,7 @@ module LightIO::Library
98
98
  else
99
99
  mock_obj = allocate
100
100
  mock_obj.instance_variable_set(:@obj, obj)
101
+ mock_obj.__send__(:call_lightio_initialize)
101
102
  mock_obj
102
103
  end
103
104
  end
@@ -106,9 +107,15 @@ module LightIO::Library
106
107
  def initialize(*args)
107
108
  obj = self.class.send(:call_method_from_ancestors, :mock_klass).send(:origin_new, *args)
108
109
  @obj = obj
110
+ call_lightio_initialize
111
+ @obj
109
112
  end
110
113
 
111
114
  private
115
+ def call_lightio_initialize
116
+ __send__(:lightio_initialize) if respond_to?(:lightio_initialize, true)
117
+ end
118
+
112
119
  def light_io_raw_obj
113
120
  @obj
114
121
  end
@@ -1,3 +1,5 @@
1
+ require 'io/wait'
2
+
1
3
  module LightIO::Library
2
4
  class IO
3
5
  include Base
@@ -19,8 +21,25 @@ module LightIO::Library
19
21
  end
20
22
  end
21
23
 
24
+ def lightio_initialize
25
+ @readbuf = StringIO.new
26
+ @readbuf.set_encoding(@obj.external_encoding) if @obj.respond_to?(:external_encoding)
27
+ @eof = nil
28
+ @seek = 0
29
+ end
30
+
22
31
  def wait(timeout = nil, mode = :read)
23
- io_watcher.wait(timeout, mode) && self
32
+ # avoid wait if can immediately return
33
+ wait_result = if RUBY_VERSION < '2.4'
34
+ if mode == :read
35
+ @obj.wait_readable(0)
36
+ elsif mode == :write
37
+ @obj.wait_writable(0)
38
+ end
39
+ else
40
+ @obj.wait(0, mode)
41
+ end
42
+ (wait_result || io_watcher.wait(timeout, mode)) && self
24
43
  end
25
44
 
26
45
  def wait_readable(timeout = nil)
@@ -31,30 +50,21 @@ module LightIO::Library
31
50
  wait(timeout, :write) && self
32
51
  end
33
52
 
34
- def read(length=nil, outbuf=nil)
35
- raise ArgumentError, "negative length #{length} given" if length && length < 0
36
- (outbuf ||= "").clear
37
- loop do
38
- readlen = length.nil? ? 4096 : length - outbuf.size
39
- if (data = wait_nonblock(:read_nonblock, readlen))
40
- outbuf << data
41
- if length == outbuf.size
42
- return outbuf
43
- end
44
- else
45
- return outbuf.empty? && length ? nil : outbuf
46
- end
53
+ def read(length = nil, outbuf = nil)
54
+ while !fill_read_buf && (length.nil? || length > @readbuf.length - @readbuf.pos)
55
+ wait_readable
47
56
  end
57
+ @readbuf.read(length, outbuf)
48
58
  end
49
59
 
50
- def readpartial(maxlen, outbuf=nil)
51
- (outbuf ||= "").clear
52
- if (data = wait_nonblock(:read_nonblock, maxlen))
53
- outbuf << data
54
- else
55
- raise EOFError, 'end of file reached'
60
+ def readpartial(maxlen, outbuf = nil)
61
+ raise ArgumentError, "negative length #{maxlen} given" if maxlen < 0
62
+ fill_read_buf
63
+ while @readbuf.eof? && !io_eof?
64
+ wait_readable
65
+ fill_read_buf
56
66
  end
57
- outbuf
67
+ @readbuf.readpartial(maxlen, outbuf)
58
68
  end
59
69
 
60
70
  def getbyte
@@ -62,8 +72,13 @@ module LightIO::Library
62
72
  end
63
73
 
64
74
  def getc
65
- wait_readable
66
- @obj.getc
75
+ fill_read_buf
76
+ until (c = @readbuf.getc)
77
+ return nil if nonblock_eof?
78
+ wait_readable
79
+ fill_read_buf
80
+ end
81
+ c
67
82
  end
68
83
 
69
84
  def readline(*args)
@@ -73,11 +88,10 @@ module LightIO::Library
73
88
  end
74
89
 
75
90
  def readlines(*args)
76
- result = []
77
- until eof?
78
- result << readline(*args)
91
+ until fill_read_buf
92
+ wait_readable
79
93
  end
80
- result
94
+ @readbuf.readlines(*args)
81
95
  end
82
96
 
83
97
  def readchar
@@ -93,8 +107,13 @@ module LightIO::Library
93
107
  end
94
108
 
95
109
  def eof
96
- wait_readable
97
- @obj.eof
110
+ # until eof have a value
111
+ fill_read_buf
112
+ while @readbuf.eof? && @eof.nil?
113
+ wait_readable
114
+ fill_read_buf
115
+ end
116
+ nonblock_eof?
98
117
  end
99
118
 
100
119
  alias eof? eof
@@ -103,19 +122,17 @@ module LightIO::Library
103
122
  raise ArgumentError, "wrong number of arguments (given #{args.size}, expected 0..2)" if args.size > 2
104
123
  sep = $/
105
124
  if args[0].is_a?(Numeric)
106
- limit = args.shift
125
+ limit = args[0]
107
126
  else
108
- sep = args.shift if args.size > 0
109
- limit = args.shift if args.first.is_a?(Numeric)
127
+ sep = args[0] if args.size > 0
128
+ limit = args[1] if args[1].is_a?(Numeric)
110
129
  end
111
- s = ''
112
- while (c = getbyte)
113
- s << c
114
- break if limit && s.size == limit
115
- break if c == sep
130
+ until fill_read_buf
131
+ break if limit && limit <= @readbuf.length
132
+ break if sep && @readbuf.string.index(sep)
133
+ wait_readable
116
134
  end
117
- s = nil if s.empty?
118
- $_ = s
135
+ @readbuf.gets(*args)
119
136
  end
120
137
 
121
138
  def print(*obj)
@@ -135,11 +152,79 @@ module LightIO::Library
135
152
  end
136
153
  end
137
154
 
155
+ def flush
156
+ @obj.flush
157
+ self
158
+ end
159
+
138
160
  def close(*args)
139
161
  # close watcher before io closed
140
162
  io_watcher.close
141
163
  @obj.close
142
164
  end
165
+
166
+ private
167
+
168
+ def nonblock_eof?
169
+ @readbuf.eof? && io_eof?
170
+ end
171
+
172
+ def io_eof?
173
+ @eof
174
+ end
175
+
176
+ BUF_CHUNK_SIZE = 1024 * 16
177
+
178
+ def fill_read_buf
179
+ return true if @eof
180
+ while (data = @obj.read_nonblock(BUF_CHUNK_SIZE, exception: false))
181
+ case data
182
+ when :wait_readable, :wait_writable
183
+ # set eof to unknown(nil)
184
+ @eof = nil
185
+ return nil
186
+ else
187
+ # set eof to false
188
+ @eof = false if @eof.nil?
189
+ @readbuf.string << data
190
+ end
191
+ end
192
+ # set eof to true
193
+ @eof = true
194
+ end
195
+ end
196
+
197
+ def set_encoding(*args)
198
+ @readbuf.set_encoding(*args)
199
+ super(*args)
200
+ end
201
+
202
+ def lineno
203
+ @readbuf.lineno
204
+ end
205
+
206
+ def lineno= no
207
+ @readbuf.lineno = no
208
+ end
209
+
210
+ def rewind
211
+ # clear buf if seek offset is not zero
212
+ unless @seek.zero?
213
+ @seek = 0
214
+ @readbuf.string.clear
215
+ end
216
+ @readbuf.rewind
217
+ end
218
+
219
+ def seek(*args)
220
+ @readbuf.string.clear
221
+ @seek = args[0]
222
+ @obj.seek(*args)
223
+ end
224
+
225
+ def binmode
226
+ @obj.binmode
227
+ self
143
228
  end
144
229
 
145
230
  prepend IOMethods
@@ -153,6 +153,7 @@ module LightIO::Library
153
153
  @obj = socket
154
154
  wait_nonblock(:connect_nonblock, remote_address)
155
155
  @obj
156
+ lightio_initialize
156
157
  end
157
158
 
158
159
  private
@@ -167,6 +168,7 @@ module LightIO::Library
167
168
 
168
169
  def initialize(*args)
169
170
  @obj = ::TCPServer.send(:origin_new, *args)
171
+ lightio_initialize
170
172
  end
171
173
 
172
174
  def accept
@@ -1,3 +1,3 @@
1
1
  module LightIO
2
- VERSION = "0.4.2"
2
+ VERSION = "0.4.3"
3
3
  end
@@ -21,16 +21,19 @@ module LightIO::Watchers
21
21
  @io = io
22
22
  @ioloop = LightIO::Core::IOloop.current
23
23
  @waiting = false
24
- ObjectSpace.define_finalizer(self, self.class.finalizer(@monitor))
25
24
  @error = nil
26
25
  # maintain socket status, see https://github.com/socketry/lightio/issues/1
27
26
  @readiness = nil
27
+ @monitor = nil
28
28
  end
29
29
 
30
30
  # NIO::Monitor
31
31
  def monitor(interests=:rw)
32
32
  @monitor ||= begin
33
- @ioloop.add_io_wait(@io, interests) {callback_on_waiting}
33
+ raise @error if @error
34
+ monitor = @ioloop.add_io_wait(@io, interests) {callback_on_waiting}
35
+ ObjectSpace.define_finalizer(self, self.class.finalizer(monitor))
36
+ monitor
34
37
  end
35
38
  end
36
39
 
@@ -41,7 +44,13 @@ module LightIO::Watchers
41
44
  end
42
45
 
43
46
  extend Forwardable
44
- def_delegators :monitor, :interests, :interests=, :closed?
47
+ def_delegators :monitor, :interests, :interests=
48
+
49
+ def closed?
50
+ # check @monitor exists, avoid unnecessary monitor created
51
+ return true unless @monitor
52
+ monitor.closed?
53
+ end
45
54
 
46
55
  # this method return previous IO.select status
47
56
  # should avoid to directly use
@@ -90,9 +99,9 @@ module LightIO::Watchers
90
99
  end
91
100
 
92
101
  def close
102
+ set_close_error
93
103
  return if closed?
94
104
  monitor.close
95
- @error = IOError.new('closed stream')
96
105
  callback_on_waiting
97
106
  end
98
107
 
@@ -107,6 +116,10 @@ module LightIO::Watchers
107
116
  end
108
117
 
109
118
  private
119
+ def set_close_error
120
+ @error ||= IOError.new('closed stream')
121
+ end
122
+
110
123
  def check_monitor(mode)
111
124
  case mode
112
125
  when :read
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: lightio
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.4.2
4
+ version: 0.4.3
5
5
  platform: ruby
6
6
  authors:
7
7
  - Jiang Jinyang
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2018-02-15 00:00:00.000000000 Z
11
+ date: 2018-02-27 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: nio4r
@@ -153,7 +153,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
153
153
  version: '0'
154
154
  requirements: []
155
155
  rubyforge_project:
156
- rubygems_version: 2.6.14
156
+ rubygems_version: 2.7.3
157
157
  signing_key:
158
158
  specification_version: 4
159
159
  summary: LightIO is a ruby networking library, that combines ruby fiber and fast IO