io-wait 0.1.0 → 0.2.0

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: 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