ori-rb 0.4.4 → 0.4.5

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.
Files changed (4) hide show
  1. checksums.yaml +4 -4
  2. data/lib/ori/scope.rb +58 -11
  3. data/lib/ori/version.rb +1 -1
  4. metadata +1 -1
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: dd8326ee1d0ef86eff23c6b472b82ee72d2253e41d1367f053aeb878ed926320
4
- data.tar.gz: 02b872fdd48ef913857e022f9333f5a447c59493a2dd5ccdbccee5486c479d0d
3
+ metadata.gz: 982c11168837e41b1cb170b200732867a648c00546ef530b5f390da2436f4c63
4
+ data.tar.gz: 42a74eeba76762d3ec9ed5f3dd5e379be15d941a7a04a4ee7431da732e03b3bf
5
5
  SHA512:
6
- metadata.gz: 102ff1557da066713c20b08e87f29e01fff6c07978c9a384d657df6dfb2bfc4f6e95edb0f966e58b68ff44b4430232a95d23be846bba66838848792e8f3dcd86
7
- data.tar.gz: 76e6f9e1e3ed9d2dfbf8078325560a4ca40dcc770c5a2ba6ec16e58ed3809203e18a15d859ead27d236f0d9439a342326b64fe31edf81ff426e1b85926ed5107
6
+ metadata.gz: 200f9cb47a64c132688613fffb42b5a642c288f47004821e60ee451758c4fb241e9a2136e26ac23053db33e474bb9aad082949d03f7e04f1197fdc2fe09ead11
7
+ data.tar.gz: 38817593a3040a762ad3fff44e18352dfa7c0367e47a3e8aa7434222ce059cedc58c113b249df39a0f93cecf4fe87189dccd25820a5d2a870b6448cebf791e17
data/lib/ori/scope.rb CHANGED
@@ -54,9 +54,10 @@ module Ori
54
54
  @cancelled = false
55
55
  @closed = false
56
56
 
57
- # Cross-thread wakeup mechanism for unblock
57
+ # Cross-thread wakeup mechanism for unblock and fiber_interrupt
58
58
  @wakeup_mutex = ::Mutex.new
59
59
  @wakeup_queue = [] #: Array[Fiber]
60
+ @pending_interrupts = {} #: Hash[Fiber, Exception]
60
61
  @wakeup_reader, @wakeup_writer = IO.pipe
61
62
 
62
63
  # Instead, use thread-local storage
@@ -79,6 +80,9 @@ module Ori
79
80
  process_available_work
80
81
  Fiber.yield if parent_scope && pending_work?
81
82
  end
83
+ rescue Interrupt => error
84
+ puts "Scope interrupted! Shutting down..."
85
+ shutdown!(error)
82
86
  ensure
83
87
  close_scope
84
88
  @parent_scope&.deregister_child_scope(self)
@@ -174,8 +178,8 @@ module Ori
174
178
  0
175
179
  end
176
180
  ensure
177
- cleanup_io_wait(fiber, io, added)
178
- cleanup_timeout(fiber) if timeout
181
+ cleanup_io_wait(fiber, io, added) if added
182
+ cleanup_timeout(fiber) if timeout && fiber
179
183
  end
180
184
 
181
185
  def io_select(readables, writables, exceptables, timeout)
@@ -224,7 +228,7 @@ module Ori
224
228
  Fiber.yield
225
229
  end
226
230
  ensure
227
- cleanup_timeout(fiber)
231
+ cleanup_timeout(fiber) if fiber
228
232
  end
229
233
 
230
234
  def block(...)
@@ -246,6 +250,14 @@ module Ori
246
250
  @wakeup_writer.write_nonblock(".") rescue nil # rubocop:disable Style/RescueModifier
247
251
  end
248
252
 
253
+ def fiber_interrupt(fiber, exception)
254
+ @wakeup_mutex.synchronize do
255
+ @pending_interrupts[fiber] = exception
256
+ @wakeup_queue << fiber
257
+ end
258
+ @wakeup_writer.write_nonblock(".") rescue nil # rubocop:disable Style/RescueModifier
259
+ end
260
+
249
261
  def io_read(io, buffer, length, offset)
250
262
  return @parent_scope.io_read(io, buffer, length, offset) unless fiber_ids.key?(Fiber.current)
251
263
 
@@ -486,8 +498,39 @@ module Ori
486
498
  end
487
499
 
488
500
  def drain_wakeup_queue
489
- fibers = @wakeup_mutex.synchronize { @wakeup_queue.shift(@wakeup_queue.size) }
490
- fibers.each { |fiber| resume_fiber(fiber) if fiber.alive? }
501
+ interrupts = nil
502
+ fibers = @wakeup_mutex.synchronize do
503
+ unless @pending_interrupts.empty?
504
+ interrupts = @pending_interrupts.dup
505
+ @pending_interrupts.clear
506
+ end
507
+ @wakeup_queue.shift(@wakeup_queue.size)
508
+ end
509
+
510
+ fibers.each do |fiber|
511
+ next unless fiber.alive?
512
+
513
+ if (exception = interrupts&.delete(fiber))
514
+ interrupt_fiber(fiber, exception)
515
+ else
516
+ resume_fiber(fiber)
517
+ end
518
+ end
519
+ end
520
+
521
+ def interrupt_fiber(fiber, exception)
522
+ id = fiber_ids[fiber]
523
+ @tracer&.record(id, :interrupted, exception.message)
524
+
525
+ # Remove from wait states before cancelling
526
+ waiting.delete(fiber)
527
+ blocked.delete(fiber)
528
+
529
+ if (task = task_queue[fiber])
530
+ task.cancel(exception)
531
+ else
532
+ fiber.kill
533
+ end
491
534
  end
492
535
 
493
536
  def close_scope
@@ -691,15 +734,19 @@ module Ori
691
734
  end
692
735
 
693
736
  def cleanup_io_wait(fiber, io, added)
694
- readable[io].delete(fiber) if added[:readable]
695
- writable[io].delete(fiber) if added[:writable]
737
+ state = thread_local_state&.[](object_id)
738
+ return unless state
696
739
 
697
- readable.delete(io) if readable[io]&.empty?
698
- writable.delete(io) if writable[io]&.empty?
740
+ state.readable[io]&.delete(fiber) if added[:readable]
741
+ state.writable[io]&.delete(fiber) if added[:writable]
742
+
743
+ state.readable.delete(io) if state.readable[io]&.empty?
744
+ state.writable.delete(io) if state.writable[io]&.empty?
699
745
  end
700
746
 
701
747
  def cleanup_timeout(fiber)
702
- waiting.delete(fiber)
748
+ state = thread_local_state&.[](object_id)
749
+ state&.waiting&.delete(fiber)
703
750
  end
704
751
 
705
752
  # Add helper method to access thread-local state
data/lib/ori/version.rb CHANGED
@@ -1,5 +1,5 @@
1
1
  # typed: strict
2
2
 
3
3
  module Ori
4
- VERSION = "0.4.4"
4
+ VERSION = "0.4.5"
5
5
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: ori-rb
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.4.4
4
+ version: 0.4.5
5
5
  platform: ruby
6
6
  authors:
7
7
  - Jahfer Husain