io-event 1.11.2 → 1.12.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: 7c23033ceb02485410fbc8d330011826e9069a2d60cd0ca3483b575efe3d8c0e
4
- data.tar.gz: 6c6af10647b050c564682dfe3023a92c935c048ecd14472ab13732d6c33967b9
3
+ metadata.gz: 80ad33ec3e92cfe141ff91e691370fbb9349f627997f59e130ad1bb016b68ac2
4
+ data.tar.gz: b2d5c4d46dead9a1b08bcb0ae6afc7a4f75972168501d7bb2bea04b58bf4bdf2
5
5
  SHA512:
6
- metadata.gz: 7ded92b87ce6a9e74d87b7f6c8fc5de54ed6f913252897fe6c7d1bd478f990e5af1ffcf3003d250a2c5537e0c55926697f9d59ab09f8ba72650c3f2aa47cc1c7
7
- data.tar.gz: 9e63f1bf68bfde30503297abd9122cddc8caa24e7480f3ba316863e3f51f2b238e966d67969b24f6ed17e645a989db2df527119b627d1db4469008a28158ba6e
6
+ metadata.gz: e97d58a391676389971aefb44228a74949ca68a2552810b1b67f0ee2737344fdc0d303068050aa22c7a8def39733fde20d1ceeab6772dd125c9d74bca534a436
7
+ data.tar.gz: 55fa3477e391ac2775dfe9f999f7545bbe3240b2811143ad665a785beb7ff38df6f813c2fa20f93c1901d039d4ffcd60c23576393f79ffdd792d3a830f4e06e9
checksums.yaml.gz.sig CHANGED
Binary file
data/agent.md ADDED
@@ -0,0 +1,47 @@
1
+ # Agent
2
+
3
+ ## Context
4
+
5
+ This section provides links to documentation from installed packages. It is automatically generated and may be updated by running `bake agent:context:install`.
6
+
7
+ **Important:** Before performing any code, documentation, or analysis tasks, always read and apply the full content of any relevant documentation referenced in the following sections. These context files contain authoritative standards and best practices for documentation, code style, and project-specific workflows. **Do not proceed with any actions until you have read and incorporated the guidance from relevant context files.**
8
+
9
+ ### agent-context
10
+
11
+ Install and manage context files from Ruby gems.
12
+
13
+ #### [Usage Guide](.context/agent-context/usage.md)
14
+
15
+ `agent-context` is a tool that helps you discover and install contextual information from Ruby gems for AI agents. Gems can provide additional documentation, examples, and guidance in a `context/` ...
16
+
17
+ ### decode
18
+
19
+ Code analysis for documentation generation.
20
+
21
+ #### [Getting Started with Decode](.context/decode/getting-started.md)
22
+
23
+ The Decode gem provides programmatic access to Ruby code structure and metadata. It can parse Ruby files and extract definitions, comments, and documentation pragmas, enabling code analysis, docume...
24
+
25
+ #### [Documentation Coverage](.context/decode/coverage.md)
26
+
27
+ This guide explains how to test and monitor documentation coverage in your Ruby projects using the Decode gem's built-in bake tasks.
28
+
29
+ #### [Ruby Documentation](.context/decode/ruby-documentation.md)
30
+
31
+ This guide covers documentation practices and pragmas supported by the Decode gem for documenting Ruby code. These pragmas provide structured documentation that can be parsed and used to generate A...
32
+
33
+ ### sus
34
+
35
+ A fast and scalable test runner.
36
+
37
+ #### [Using Sus Testing Framework](.context/sus/usage.md)
38
+
39
+ Sus is a modern Ruby testing framework that provides a clean, BDD-style syntax for writing tests. It's designed to be fast, simple, and expressive.
40
+
41
+ #### [Mocking](.context/sus/mocking.md)
42
+
43
+ There are two types of mocking in sus: `receive` and `mock`. The `receive` matcher is a subset of full mocking and is used to set expectations on method calls, while `mock` can be used to replace m...
44
+
45
+ #### [Shared Test Behaviors and Fixtures](.context/sus/shared.md)
46
+
47
+ Sus provides shared test contexts which can be used to define common behaviours or tests that can be reused across one or more test files.
@@ -29,10 +29,7 @@ VALUE IO_Event_Selector_process_status_wait(rb_pid_t pid, int flags)
29
29
  int IO_Event_Selector_nonblock_set(int file_descriptor)
30
30
  {
31
31
  #ifdef _WIN32
32
- u_long nonblock = 1;
33
- ioctlsocket(file_descriptor, FIONBIO, &nonblock);
34
- // Windows does not provide any way to know this, so we always restore it back to unset:
35
- return 0;
32
+ rb_w32_set_nonblock(file_descriptor);
36
33
  #else
37
34
  // Get the current mode:
38
35
  int flags = fcntl(file_descriptor, F_GETFL, 0);
@@ -50,8 +47,6 @@ void IO_Event_Selector_nonblock_restore(int file_descriptor, int flags)
50
47
  {
51
48
  #ifdef _WIN32
52
49
  // Yolo...
53
- u_long nonblock = flags;
54
- ioctlsocket(file_descriptor, FIONBIO, &nonblock);
55
50
  #else
56
51
  // The flags didn't have O_NONBLOCK set, so it would have been set, so we need to restore it:
57
52
  if (!(flags & O_NONBLOCK)) {
@@ -336,19 +336,32 @@ static VALUE worker_pool_call(VALUE self, VALUE _blocking_operation) {
336
336
  pthread_mutex_unlock(&pool->mutex);
337
337
 
338
338
  // Block the current fiber until work is completed:
339
- int state;
339
+ int state = 0;
340
340
  while (true) {
341
- rb_protect(worker_pool_work_begin, (VALUE)&work, &state);
342
-
341
+ int current_state = 0;
342
+ rb_protect(worker_pool_work_begin, (VALUE)&work, &current_state);
343
+ if (DEBUG) fprintf(stderr, "-- worker_pool_call:work completed=%d, current_state=%d, state=%d\n", work.completed, current_state, state);
344
+
345
+ // Store the first exception state:
346
+ if (!state) {
347
+ state = current_state;
348
+ }
349
+
350
+ // If the work is still in the queue, we must wait for a worker to complete it (even if cancelled):
343
351
  if (work.completed) {
352
+ // The work was completed, we can exit the loop:
344
353
  break;
345
354
  } else {
346
355
  if (DEBUG) fprintf(stderr, "worker_pool_call:rb_fiber_scheduler_blocking_operation_cancel\n");
356
+ // Ensure the blocking operation is cancelled:
347
357
  rb_fiber_scheduler_blocking_operation_cancel(blocking_operation);
348
- // The work was not completed, we need to wait for it to be completed.
358
+
359
+ // The work was not completed, we need to wait for it to be completed, so we go around the loop again.
349
360
  }
350
361
  }
351
362
 
363
+ if (DEBUG) fprintf(stderr, "<- worker_pool_call:work completed=%d, state=%d\n", work.completed, state);
364
+
352
365
  if (state) {
353
366
  rb_jump_tag(state);
354
367
  } else {
@@ -82,7 +82,7 @@ class IO
82
82
  # Validate the heap invariant. Every element except the root must not be smaller than its parent element. Note that it MAY be equal.
83
83
  def valid?
84
84
  # Notice we skip index 0 on purpose, because it has no parent
85
- (1..(@contents.size - 1)).all? { |e| @contents[e] >= @contents[(e - 1) / 2] }
85
+ (1..(@contents.size - 1)).all? {|index| @contents[index] >= @contents[(index - 1) / 2]}
86
86
  end
87
87
 
88
88
  private
@@ -1,7 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  # Released under the MIT License.
4
- # Copyright, 2021-2024, by Samuel Williams.
4
+ # Copyright, 2021-2025, by Samuel Williams.
5
5
  # Copyright, 2023, by Math Ieu.
6
6
 
7
7
  require_relative "../interrupt"
@@ -199,7 +199,7 @@ module IO::Event
199
199
  result = Fiber.blocking{buffer.read(io, 0, offset)}
200
200
 
201
201
  if result < 0
202
- if again?(result)
202
+ if length > 0 and again?(result)
203
203
  self.io_wait(fiber, io, IO::READABLE)
204
204
  else
205
205
  return result
@@ -229,7 +229,7 @@ module IO::Event
229
229
  result = Fiber.blocking{buffer.write(io, 0, offset)}
230
230
 
231
231
  if result < 0
232
- if again?(result)
232
+ if length > 0 and again?(result)
233
233
  self.io_wait(fiber, io, IO::READABLE)
234
234
  else
235
235
  return result
@@ -305,96 +305,14 @@ module IO::Event
305
305
 
306
306
  return total
307
307
  end
308
- elsif Support.fiber_scheduler_v1?
309
- # Ruby <= 3.1, limited IO::Buffer support.
310
- def io_read(fiber, _io, buffer, length, offset = 0)
311
- # We need to avoid any internal buffering, so we use a duplicated IO object:
312
- io = IO.for_fd(_io.fileno, autoclose: false)
313
-
314
- total = 0
315
-
316
- maximum_size = buffer.size - offset
317
- while maximum_size > 0
318
- case result = blocking{io.read_nonblock(maximum_size, exception: false)}
319
- when :wait_readable
320
- if length > 0
321
- self.io_wait(fiber, io, IO::READABLE)
322
- else
323
- return EWOULDBLOCK
324
- end
325
- when :wait_writable
326
- if length > 0
327
- self.io_wait(fiber, io, IO::WRITABLE)
328
- else
329
- return EWOULDBLOCK
330
- end
331
- when nil
332
- break
333
- else
334
- buffer.set_string(result, offset)
335
-
336
- size = result.bytesize
337
- total += size
338
- offset += size
339
- break if size >= length
340
- length -= size
341
- end
342
-
343
- maximum_size = buffer.size - offset
344
- end
345
-
346
- return total
347
- rescue IOError => error
348
- return -Errno::EBADF::Errno
349
- rescue SystemCallError => error
350
- return -error.errno
351
- end
352
-
353
- def io_write(fiber, _io, buffer, length, offset = 0)
354
- # We need to avoid any internal buffering, so we use a duplicated IO object:
355
- io = IO.for_fd(_io.fileno, autoclose: false)
356
-
357
- total = 0
358
-
359
- maximum_size = buffer.size - offset
360
- while maximum_size > 0
361
- chunk = buffer.get_string(offset, maximum_size)
362
- case result = blocking{io.write_nonblock(chunk, exception: false)}
363
- when :wait_readable
364
- if length > 0
365
- self.io_wait(fiber, io, IO::READABLE)
366
- else
367
- return EWOULDBLOCK
368
- end
369
- when :wait_writable
370
- if length > 0
371
- self.io_wait(fiber, io, IO::WRITABLE)
372
- else
373
- return EWOULDBLOCK
374
- end
375
- else
376
- total += result
377
- offset += result
378
- break if result >= length
379
- length -= result
380
- end
381
-
382
- maximum_size = buffer.size - offset
383
- end
384
-
385
- return total
386
- rescue IOError => error
387
- return -Errno::EBADF::Errno
388
- rescue SystemCallError => error
389
- return -error.errno
390
- end
391
-
392
- def blocking(&block)
393
- fiber = Fiber.new(blocking: true, &block)
394
- return fiber.resume(fiber)
395
- end
396
308
  end
397
309
 
310
+ # Wait for a process to change state.
311
+ #
312
+ # @parameter fiber [Fiber] The fiber to resume after waiting.
313
+ # @parameter pid [Integer] The process ID to wait for.
314
+ # @parameter flags [Integer] Flags to pass to Process::Status.wait.
315
+ # @returns [Process::Status] The status of the waited process.
398
316
  def process_wait(fiber, pid, flags)
399
317
  Thread.new do
400
318
  Process::Status.wait(pid, flags)
@@ -414,6 +332,10 @@ module IO::Event
414
332
  end
415
333
  end
416
334
 
335
+ # Wait for IO events or a timeout.
336
+ #
337
+ # @parameter duration [Numeric | Nil] The maximum time to wait, or nil for no timeout.
338
+ # @returns [Integer] The number of ready IO objects.
417
339
  def select(duration = nil)
418
340
  if pop_ready
419
341
  # If we have popped items from the ready list, they may influence the duration calculation, so we don't delay the event loop:
@@ -14,35 +14,28 @@ class IO
14
14
  IO.const_defined?(:Buffer)
15
15
  end
16
16
 
17
- # The basic fiber scheduler was introduced along side the IO::Buffer class.
18
- #
19
- # @returns [Boolean] Whether the IO::Buffer class is available.
20
- #
21
- # To be removed on 31 Mar 2025.
22
- def self.fiber_scheduler_v1?
23
- IO.const_defined?(:Buffer)
24
- end
25
-
26
17
  # More advanced read/write methods and blocking controls were introduced in Ruby 3.2.
27
18
  #
28
19
  # To be removed on 31 Mar 2026.
29
20
  def self.fiber_scheduler_v2?
30
- # Some interface changes were back-ported incorrectly:
31
- # https://github.com/ruby/ruby/pull/10778
32
- # Specifically "Improvements to IO::Buffer read/write/pread/pwrite."
33
- # Missing correct size calculation.
34
- return false if RUBY_VERSION >= "3.2.5"
35
-
36
- IO.const_defined?(:Buffer) and Fiber.respond_to?(:blocking) and IO::Buffer.instance_method(:read).arity == -1
21
+ if RUBY_VERSION >= "3.2"
22
+ return true if RUBY_VERSION >= "3.2.6"
23
+
24
+ # Some interface changes were back-ported incorrectly and released in 3.2.5 <https://github.com/ruby/ruby/pull/10778> - Specifically "Improvements to IO::Buffer read/write/pread/pwrite." is missing correct size calculation.
25
+ return false if RUBY_VERSION >= "3.2.5"
26
+
27
+ # Feature detection:
28
+ IO.const_defined?(:Buffer) and Fiber.respond_to?(:blocking) and IO::Buffer.instance_method(:read).arity == -1
29
+ end
37
30
  end
38
31
 
39
32
  # Updated inferfaces for read/write and IO::Buffer were introduced in Ruby 3.3, including pread/pwrite.
40
33
  #
41
34
  # To become the default 31 Mar 2026.
42
35
  def self.fiber_scheduler_v3?
36
+ return true if RUBY_VERSION >= "3.3"
37
+
43
38
  if fiber_scheduler_v2?
44
- return true if RUBY_VERSION >= "3.3"
45
-
46
39
  # Feature detection if required:
47
40
  begin
48
41
  IO::Buffer.new.slice(0, 0).write(STDOUT)
@@ -7,6 +7,6 @@
7
7
  class IO
8
8
  # @namespace
9
9
  module Event
10
- VERSION = "1.11.2"
10
+ VERSION = "1.12.0"
11
11
  end
12
12
  end
data/license.md CHANGED
@@ -9,7 +9,7 @@ Copyright, 2022, by Bruno Sutic.
9
9
  Copyright, 2023, by Math Ieu.
10
10
  Copyright, 2024, by Pavel Rosický.
11
11
  Copyright, 2024, by Anthony Ross.
12
- Copyright, 2024, by Shizuo Fujita.
12
+ Copyright, 2024-2025, by Shizuo Fujita.
13
13
  Copyright, 2024, by Jean Boussier.
14
14
  Copyright, 2025, by Stanislav (Stas) Katkov.
15
15
 
data.tar.gz.sig CHANGED
Binary file
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: io-event
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.11.2
4
+ version: 1.12.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Samuel Williams
@@ -10,11 +10,11 @@ authors:
10
10
  - Jean Boussier
11
11
  - Benoit Daloze
12
12
  - Bruno Sutic
13
+ - Shizuo Fujita
13
14
  - Alex Matchneer
14
15
  - Anthony Ross
15
16
  - Delton Ding
16
17
  - Pavel Rosický
17
- - Shizuo Fujita
18
18
  - Stanislav (Stas) Katkov
19
19
  bindir: bin
20
20
  cert_chain:
@@ -54,6 +54,7 @@ extensions:
54
54
  - ext/extconf.rb
55
55
  extra_rdoc_files: []
56
56
  files:
57
+ - agent.md
57
58
  - design.md
58
59
  - ext/extconf.rb
59
60
  - ext/io/event/array.h
@@ -106,7 +107,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
106
107
  requirements:
107
108
  - - ">="
108
109
  - !ruby/object:Gem::Version
109
- version: '3.1'
110
+ version: 3.2.6
110
111
  required_rubygems_version: !ruby/object:Gem::Requirement
111
112
  requirements:
112
113
  - - ">="
metadata.gz.sig CHANGED
Binary file