io-wait 0.1.0 → 0.2.0

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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 5ea39ff5c3815f098f8c15eb5b493e27408afda30a88d11cd00564ab85438639
4
- data.tar.gz: 1a9ba20f028fe3259153bac2aa27b70870ef8e103d00c20cb6f7a267da94a6b5
3
+ metadata.gz: ac9aac81de884ac5961c9415e4347be5f26ae3ef6e52854834c76a105e4f7388
4
+ data.tar.gz: 118b4011fcaa3f94a48ff2d3be11db1b2049375f709426b177ab5a9bc4799d7f
5
5
  SHA512:
6
- metadata.gz: bebdf7aba83d894c28fa9763b0048047c437c67962a939e3d29a6b4cbefe1ac690afd8ef8ed372d013204b1298f7fab0f01cd45c35ced0bb4d62e4234818f0ae
7
- data.tar.gz: 0f9635692758b787c4dc873e449e0a3e893dee5427f122fbda17f9458d4f33916bd32c333bf76023a73285177ac70b4b576025504130423089467fdb703266b5
6
+ metadata.gz: 58cf2bc5cdc614eb7827a460decf662def72676011fbf9d4a853dfd71b66311dd10d81fcd100ac0a2d676d61009e6e3a4c80ac0f7c7d0d88f303a8a16f1510de
7
+ data.tar.gz: 700343ef7233d37f9e27d22bfab091af07e681e996619c8953553152b7b7598bb1843d2d969b8d268cac752ead4641b13f32380d2b5c43e8d4808e4176b64c89
data/Gemfile CHANGED
@@ -1,4 +1,4 @@
1
1
  source 'https://rubygems.org'
2
2
 
3
- # Specify your gem's dependencies in etc.gemspec
3
+ # Specify your gem's dependencies in io-wait.gemspec
4
4
  gemspec
data/Rakefile CHANGED
@@ -1,6 +1,8 @@
1
1
  require "bundler/gem_tasks"
2
2
  require "rake/testtask"
3
3
 
4
+ name = "io/wait"
5
+
4
6
  Rake::TestTask.new(:test) do |t|
5
7
  t.libs << "test/lib"
6
8
  t.ruby_opts << "-rhelper"
@@ -8,5 +10,7 @@ Rake::TestTask.new(:test) do |t|
8
10
  end
9
11
 
10
12
  require 'rake/extensiontask'
11
- Rake::ExtensionTask.new("io/wait")
13
+ Rake::ExtensionTask.new(name)
14
+ task :test => :compile
15
+
12
16
  task :default => :test
data/ext/io/wait/wait.c CHANGED
@@ -1,3 +1,4 @@
1
+ /* -*- c-file-style: "ruby"; indent-tabs-mode: t -*- */
1
2
  /**********************************************************************
2
3
 
3
4
  io/wait.c -
@@ -39,35 +40,6 @@
39
40
  #define FIONREAD_POSSIBLE_P(fd) ((void)(fd),Qtrue)
40
41
  #endif
41
42
 
42
- static VALUE io_ready_p _((VALUE io));
43
- static VALUE io_wait_readable _((int argc, VALUE *argv, VALUE io));
44
- static VALUE io_wait_writable _((int argc, VALUE *argv, VALUE io));
45
- void Init_wait _((void));
46
-
47
- static struct timeval *
48
- get_timeout(int argc, VALUE *argv, struct timeval *timerec)
49
- {
50
- VALUE timeout = Qnil;
51
- rb_check_arity(argc, 0, 1);
52
- if (!argc || NIL_P(timeout = argv[0])) {
53
- return NULL;
54
- }
55
- else {
56
- *timerec = rb_time_interval(timeout);
57
- return timerec;
58
- }
59
- }
60
-
61
- static int
62
- wait_for_single_fd(rb_io_t *fptr, int events, struct timeval *tv)
63
- {
64
- int i = rb_wait_for_single_fd(fptr->fd, events, tv);
65
- if (i < 0)
66
- rb_sys_fail(0);
67
- rb_io_check_closed(fptr);
68
- return (i & events);
69
- }
70
-
71
43
  /*
72
44
  * call-seq:
73
45
  * io.nread -> int
@@ -79,13 +51,12 @@ wait_for_single_fd(rb_io_t *fptr, int events, struct timeval *tv)
79
51
  static VALUE
80
52
  io_nread(VALUE io)
81
53
  {
82
- rb_io_t *fptr;
83
- int len;
54
+ rb_io_t *fptr = NULL;
84
55
  ioctl_arg n;
85
56
 
86
57
  GetOpenFile(io, fptr);
87
58
  rb_io_check_readable(fptr);
88
- len = rb_io_read_pending(fptr);
59
+ int len = rb_io_read_pending(fptr);
89
60
  if (len > 0) return INT2FIX(len);
90
61
  if (!FIONREAD_POSSIBLE_P(fptr->fd)) return INT2FIX(0);
91
62
  if (ioctl(fptr->fd, FIONREAD, &n)) return INT2FIX(0);
@@ -93,76 +64,114 @@ io_nread(VALUE io)
93
64
  return INT2FIX(0);
94
65
  }
95
66
 
67
+ static VALUE
68
+ io_wait_event(VALUE io, int event, VALUE timeout)
69
+ {
70
+ VALUE result = rb_io_wait(io, RB_INT2NUM(event), timeout);
71
+
72
+ if (!RB_TEST(result)) {
73
+ return Qnil;
74
+ }
75
+
76
+ int mask = RB_NUM2INT(result);
77
+
78
+ if (mask & event) {
79
+ return io;
80
+ }
81
+ else {
82
+ return Qfalse;
83
+ }
84
+ }
85
+
96
86
  /*
97
87
  * call-seq:
98
88
  * io.ready? -> true or false
99
89
  *
100
- * Returns true if input available without blocking, or false.
90
+ * Returns +true+ if input available without blocking, or +false+.
101
91
  */
102
92
 
103
93
  static VALUE
104
94
  io_ready_p(VALUE io)
105
95
  {
106
96
  rb_io_t *fptr;
107
- struct timeval tv = {0, 0};
108
97
 
109
98
  GetOpenFile(io, fptr);
110
99
  rb_io_check_readable(fptr);
111
100
  if (rb_io_read_pending(fptr)) return Qtrue;
112
- if (wait_for_single_fd(fptr, RB_WAITFD_IN, &tv))
113
- return Qtrue;
114
- return Qfalse;
101
+
102
+ return io_wait_event(io, RUBY_IO_READABLE, RB_INT2NUM(0));
115
103
  }
116
104
 
117
105
  /*
118
106
  * call-seq:
119
- * io.wait_readable -> IO, true or nil
120
- * io.wait_readable(timeout) -> IO, true or nil
107
+ * io.wait_readable -> true or false
108
+ * io.wait_readable(timeout) -> true or false
121
109
  *
122
- * Waits until IO is readable without blocking and returns +self+, or
123
- * +nil+ when times out.
110
+ * Waits until IO is readable and returns +true+, or
111
+ * +false+ when times out.
124
112
  * Returns +true+ immediately when buffered data is available.
125
113
  */
126
114
 
127
115
  static VALUE
128
116
  io_wait_readable(int argc, VALUE *argv, VALUE io)
129
117
  {
130
- rb_io_t *fptr;
131
- struct timeval timerec;
132
- struct timeval *tv;
118
+ rb_io_t *fptr = NULL;
133
119
 
134
- GetOpenFile(io, fptr);
120
+ RB_IO_POINTER(io, fptr);
135
121
  rb_io_check_readable(fptr);
136
- tv = get_timeout(argc, argv, &timerec);
122
+
137
123
  if (rb_io_read_pending(fptr)) return Qtrue;
138
- if (wait_for_single_fd(fptr, RB_WAITFD_IN, tv)) {
139
- return io;
140
- }
141
- return Qnil;
124
+
125
+ rb_check_arity(argc, 0, 1);
126
+ VALUE timeout = (argc == 1 ? argv[0] : Qnil);
127
+
128
+ return io_wait_event(io, RUBY_IO_READABLE, timeout);
142
129
  }
143
130
 
144
131
  /*
145
132
  * call-seq:
146
- * io.wait_writable -> IO
147
- * io.wait_writable(timeout) -> IO or nil
133
+ * io.wait_writable -> true or false
134
+ * io.wait_writable(timeout) -> true or false
148
135
  *
149
- * Waits until IO is writable without blocking and returns +self+ or
150
- * +nil+ when times out.
136
+ * Waits until IO is writable and returns +true+ or
137
+ * +false+ when times out.
151
138
  */
152
139
  static VALUE
153
140
  io_wait_writable(int argc, VALUE *argv, VALUE io)
154
141
  {
155
- rb_io_t *fptr;
156
- struct timeval timerec;
157
- struct timeval *tv;
142
+ rb_io_t *fptr = NULL;
158
143
 
159
- GetOpenFile(io, fptr);
144
+ RB_IO_POINTER(io, fptr);
160
145
  rb_io_check_writable(fptr);
161
- tv = get_timeout(argc, argv, &timerec);
162
- if (wait_for_single_fd(fptr, RB_WAITFD_OUT, tv)) {
163
- return io;
164
- }
165
- return Qnil;
146
+
147
+ rb_check_arity(argc, 0, 1);
148
+ VALUE timeout = (argc == 1 ? argv[0] : Qnil);
149
+
150
+ return io_wait_event(io, RUBY_IO_WRITABLE, timeout);
151
+ }
152
+
153
+ /*
154
+ * call-seq:
155
+ * io.wait_priority -> true or false
156
+ * io.wait_priority(timeout) -> true or false
157
+ *
158
+ * Waits until IO is priority and returns +true+ or
159
+ * +false+ when times out.
160
+ */
161
+ static VALUE
162
+ io_wait_priority(int argc, VALUE *argv, VALUE io)
163
+ {
164
+ rb_io_t *fptr = NULL;
165
+
166
+ RB_IO_POINTER(io, fptr);
167
+ rb_io_check_readable(fptr);
168
+
169
+ if (rb_io_read_pending(fptr)) return Qtrue;
170
+
171
+ rb_check_arity(argc, 0, 1);
172
+ VALUE timeout = argc == 1 ? argv[0] : Qnil;
173
+
174
+ return io_wait_event(io, RUBY_IO_PRIORITY, timeout);
166
175
  }
167
176
 
168
177
  static int
@@ -201,41 +210,60 @@ wait_mode_sym(VALUE mode)
201
210
 
202
211
  /*
203
212
  * call-seq:
204
- * io.wait(timeout = nil, mode = :read) -> IO, true or nil
213
+ * io.wait(events, timeout) -> event mask or false.
214
+ * io.wait(timeout = nil, mode = :read) -> event mask or false.
215
+ *
216
+ * Waits until the IO becomes ready for the specified events and returns the
217
+ * subset of events that become ready, or +false+ when times out.
218
+ *
219
+ * The events can be a bit mask of +IO::READABLE+, +IO::WRITABLE+ or
220
+ * +IO::PRIORITY+.
205
221
  *
206
- * Waits until IO is readable or writable without blocking and returns
207
- * +self+, or +nil+ when times out.
208
222
  * Returns +true+ immediately when buffered data is available.
223
+ *
209
224
  * Optional parameter +mode+ is one of +:read+, +:write+, or
210
225
  * +:read_write+.
211
226
  */
212
227
 
213
228
  static VALUE
214
- io_wait_readwrite(int argc, VALUE *argv, VALUE io)
229
+ io_wait(int argc, VALUE *argv, VALUE io)
215
230
  {
216
- rb_io_t *fptr;
217
- struct timeval timerec;
218
- struct timeval *tv = NULL;
219
- int event = 0;
220
- int i;
231
+ VALUE timeout = Qundef;
232
+ rb_io_event_t events = 0;
221
233
 
222
- GetOpenFile(io, fptr);
223
- for (i = 0; i < argc; ++i) {
224
- if (SYMBOL_P(argv[i])) {
225
- event |= wait_mode_sym(argv[i]);
234
+ if (argc != 2 || (RB_SYMBOL_P(argv[0]) || RB_SYMBOL_P(argv[1]))) {
235
+ for (int i = 0; i < argc; i += 1) {
236
+ if (RB_SYMBOL_P(argv[i])) {
237
+ events |= wait_mode_sym(argv[i]);
238
+ }
239
+ else if (timeout == Qundef) {
240
+ rb_time_interval(timeout = argv[i]);
241
+ }
242
+ else {
243
+ rb_raise(rb_eArgError, "timeout given more than once");
244
+ }
226
245
  }
227
- else {
228
- *(tv = &timerec) = rb_time_interval(argv[i]);
246
+ if (timeout == Qundef) timeout = Qnil;
247
+ }
248
+ else /* argc == 2 */ {
249
+ events = RB_NUM2UINT(argv[0]);
250
+ timeout = argv[1];
251
+ }
252
+
253
+ if (events == 0) {
254
+ events = RUBY_IO_READABLE;
255
+ }
256
+
257
+ if (events & RUBY_IO_READABLE) {
258
+ rb_io_t *fptr = NULL;
259
+ RB_IO_POINTER(io, fptr);
260
+
261
+ if (rb_io_read_pending(fptr)) {
262
+ return Qtrue;
229
263
  }
230
264
  }
231
- /* rb_time_interval() and might_mode() might convert the argument */
232
- rb_io_check_closed(fptr);
233
- if (!event) event = RB_WAITFD_IN;
234
- if ((event & RB_WAITFD_IN) && rb_io_read_pending(fptr))
235
- return Qtrue;
236
- if (wait_for_single_fd(fptr, event, tv))
237
- return io;
238
- return Qnil;
265
+
266
+ return io_wait_event(io, events, timeout);
239
267
  }
240
268
 
241
269
  /*
@@ -245,9 +273,16 @@ io_wait_readwrite(int argc, VALUE *argv, VALUE io)
245
273
  void
246
274
  Init_wait(void)
247
275
  {
276
+ #ifdef HAVE_RB_EXT_RACTOR_SAFE
277
+ RB_EXT_RACTOR_SAFE(true);
278
+ #endif
279
+
248
280
  rb_define_method(rb_cIO, "nread", io_nread, 0);
249
281
  rb_define_method(rb_cIO, "ready?", io_ready_p, 0);
250
- rb_define_method(rb_cIO, "wait", io_wait_readwrite, -1);
282
+
283
+ rb_define_method(rb_cIO, "wait", io_wait, -1);
284
+
251
285
  rb_define_method(rb_cIO, "wait_readable", io_wait_readable, -1);
252
286
  rb_define_method(rb_cIO, "wait_writable", io_wait_writable, -1);
287
+ rb_define_method(rb_cIO, "wait_priority", io_wait_priority, -1);
253
288
  }
data/io-wait.gemspec CHANGED
@@ -1,6 +1,8 @@
1
+ _VERSION = "0.2.0"
2
+
1
3
  Gem::Specification.new do |spec|
2
4
  spec.name = "io-wait"
3
- spec.version = "0.1.0"
5
+ spec.version = _VERSION
4
6
  spec.authors = ["Nobu Nakada"]
5
7
  spec.email = ["nobu@ruby-lang.org"]
6
8
 
@@ -8,15 +10,18 @@ Gem::Specification.new do |spec|
8
10
  spec.description = %q{Waits until IO is readable or writable without blocking.}
9
11
  spec.homepage = "https://github.com/ruby/io-wait"
10
12
  spec.licenses = ["Ruby", "BSD-2-Clause"]
11
- spec.required_ruby_version = Gem::Requirement.new(">= 2.3.0")
13
+ spec.required_ruby_version = Gem::Requirement.new(">= 3.0.0")
12
14
 
13
15
  spec.metadata["homepage_uri"] = spec.homepage
14
16
  spec.metadata["source_code_uri"] = spec.homepage
15
17
 
16
18
  spec.files = Dir.chdir(File.expand_path('..', __FILE__)) do
17
- `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
19
+ `git ls-files -z`.split("\x0").reject do |f|
20
+ f.match(%r{\A(?:test|spec|features)/|\A\.(?:git|travis)})
21
+ end
18
22
  end
23
+ spec.extensions = %w[ext/io/wait/extconf.rb]
19
24
  spec.bindir = "exe"
20
- spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
25
+ spec.executables = []
21
26
  spec.require_paths = ["lib"]
22
27
  end
@@ -0,0 +1,34 @@
1
+ task "build" => "changelogs"
2
+
3
+ changelog = proc do |output, ver = nil, prev = nil|
4
+ ver &&= Gem::Version.new(ver)
5
+ range = [[prev], [ver, "HEAD"]].map {|ver, branch| ver ? "v#{ver.to_s}" : branch}.compact.join("..")
6
+ IO.popen(%W[git log --format=fuller --topo-order --no-merges #{range}]) do |log|
7
+ line = log.gets
8
+ FileUtils.mkpath(File.dirname(output))
9
+ File.open(output, "wb") do |f|
10
+ f.print "-*- coding: utf-8 -*-\n\n", line
11
+ log.each_line do |line|
12
+ line.sub!(/^(?!:)(?:Author|Commit)?(?:Date)?: /, ' \&')
13
+ line.sub!(/ +$/, '')
14
+ f.print(line)
15
+ end
16
+ end
17
+ end
18
+ end
19
+
20
+ tags = IO.popen(%w[git tag -l v[0-9]*]).grep(/v(.*)/) {$1}
21
+ tags.sort_by! {|tag| tag.scan(/\d+/).map(&:to_i)}
22
+ tags.inject(nil) do |prev, tag|
23
+ task("logs/ChangeLog-#{tag}") {|t| changelog[t.name, tag, prev]}
24
+ tag
25
+ end
26
+
27
+ desc "Make ChangeLog"
28
+ task "ChangeLog", [:ver, :prev] do |t, ver: nil, prev: tags.last|
29
+ changelog[t.name, ver, prev]
30
+ end
31
+
32
+ changelogs = ["ChangeLog", *tags.map {|tag| "logs/ChangeLog-#{tag}"}]
33
+ task "changelogs" => changelogs
34
+ CLOBBER.concat(changelogs) << "logs"
@@ -0,0 +1,5 @@
1
+ task "build" => "date_epoch"
2
+
3
+ task "date_epoch" do
4
+ ENV["SOURCE_DATE_EPOCH"] = IO.popen(%W[git -C #{__dir__} log -1 --format=%ct], &:read).chomp
5
+ end
@@ -0,0 +1,44 @@
1
+ class << (helper = Bundler::GemHelper.instance)
2
+ def update_gemspec
3
+ path = gemspec.loaded_from
4
+ File.open(path, "r+b") do |f|
5
+ d = f.read
6
+ if d.sub!(/^(_VERSION\s*=\s*)".*"/) {$1 + gemspec.version.to_s.dump}
7
+ f.rewind
8
+ f.truncate(0)
9
+ f.print(d)
10
+ end
11
+ end
12
+ end
13
+
14
+ def commit_bump
15
+ sh(%W[git -C #{__dir__} commit -m bump\ up\ to\ #{gemspec.version}
16
+ #{gemspec.loaded_from}])
17
+ end
18
+
19
+ def version=(v)
20
+ gemspec.version = v
21
+ update_gemspec
22
+ commit_bump
23
+ end
24
+ end
25
+
26
+ major, minor, teeny = helper.gemspec.version.segments
27
+
28
+ task "bump:teeny" do
29
+ helper.version = Gem::Version.new("#{major}.#{minor}.#{teeny+1}")
30
+ end
31
+
32
+ task "bump:minor" do
33
+ helper.version = Gem::Version.new("#{major}.#{minor+1}.0")
34
+ end
35
+
36
+ task "bump:major" do
37
+ helper.version = Gem::Version.new("#{major+1}.0.0")
38
+ end
39
+
40
+ task "bump" => "bump:teeny"
41
+
42
+ task "tag" do
43
+ helper.__send__(:tag_version)
44
+ end
metadata CHANGED
@@ -1,34 +1,34 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: io-wait
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.0
4
+ version: 0.2.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Nobu Nakada
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2020-09-18 00:00:00.000000000 Z
11
+ date: 2021-10-21 00:00:00.000000000 Z
12
12
  dependencies: []
13
13
  description: Waits until IO is readable or writable without blocking.
14
14
  email:
15
15
  - nobu@ruby-lang.org
16
16
  executables: []
17
- extensions: []
17
+ extensions:
18
+ - ext/io/wait/extconf.rb
18
19
  extra_rdoc_files: []
19
20
  files:
20
- - ".gitignore"
21
- - ".travis.yml"
22
21
  - COPYING
23
22
  - Gemfile
24
23
  - README.md
25
24
  - Rakefile
26
- - bin/console
27
- - bin/setup
28
25
  - ext/io/wait/depend
29
26
  - ext/io/wait/extconf.rb
30
27
  - ext/io/wait/wait.c
31
28
  - io-wait.gemspec
29
+ - rakelib/changelogs.rake
30
+ - rakelib/epoch.rake
31
+ - rakelib/version.rake
32
32
  homepage: https://github.com/ruby/io-wait
33
33
  licenses:
34
34
  - Ruby
@@ -44,14 +44,14 @@ required_ruby_version: !ruby/object:Gem::Requirement
44
44
  requirements:
45
45
  - - ">="
46
46
  - !ruby/object:Gem::Version
47
- version: 2.3.0
47
+ version: 3.0.0
48
48
  required_rubygems_version: !ruby/object:Gem::Requirement
49
49
  requirements:
50
50
  - - ">="
51
51
  - !ruby/object:Gem::Version
52
52
  version: '0'
53
53
  requirements: []
54
- rubygems_version: 3.2.0.rc.1
54
+ rubygems_version: 3.3.0.dev
55
55
  signing_key:
56
56
  specification_version: 4
57
57
  summary: Waits until IO is readable or writable without blocking.
data/.gitignore DELETED
@@ -1,11 +0,0 @@
1
- /.bundle/
2
- /.yardoc
3
- /_yardoc/
4
- /coverage/
5
- /doc/
6
- /pkg/
7
- /spec/reports/
8
- /tmp/
9
- *.bundle
10
- *.dll
11
- *.so
data/.travis.yml DELETED
@@ -1,6 +0,0 @@
1
- ---
2
- language: ruby
3
- cache: bundler
4
- rvm:
5
- - 2.8.0
6
- before_install: gem install bundler -v 2.1.4
data/bin/console DELETED
@@ -1,14 +0,0 @@
1
- #!/usr/bin/env ruby
2
-
3
- require "bundler/setup"
4
- require "io/wait"
5
-
6
- # You can add fixtures and/or initialization code here to make experimenting
7
- # with your gem easier. You can also use a different console, if you like.
8
-
9
- # (If you use this, don't forget to add pry to your Gemfile!)
10
- # require "pry"
11
- # Pry.start
12
-
13
- require "irb"
14
- IRB.start(__FILE__)
data/bin/setup DELETED
@@ -1,8 +0,0 @@
1
- #!/usr/bin/env bash
2
- set -euo pipefail
3
- IFS=$'\n\t'
4
- set -vx
5
-
6
- bundle install
7
-
8
- # Do any other automated setup that you need to do here