ori-rb 0.4.7 → 0.4.8

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: 958209a6ea858a765a4f3f642d195cdca3e7bfc9c760d3761403d01fdac6ef33
4
- data.tar.gz: bf4787b1c567aa2749ca6e72d572218c7e613751122e8d1440ee5102e7c92b7c
3
+ metadata.gz: 275fec2a2a0a918b10e34443cd062b7d70bdbedabb55d4b6ecb33de40c4ab20a
4
+ data.tar.gz: d17b29ea758c370e790feded2cd97000a7d8d2b63f58a4157b2a1cff6b59d3a3
5
5
  SHA512:
6
- metadata.gz: 64a8f68cfdbccd65ab1d7553f92784ca55f46ab74c9ea3b6d3eadae1e3720b75aecec468a412d47a5f8e448946bf4c270280205b2a9368bb77d62d042a7993b7
7
- data.tar.gz: 7c95388c4077a57fe10dd8d474c985703ac551e3daf7806afa3e9de28e5c905cc668d826429b84d186686f84917c77801e2ee678776d96ee61bb94fecaca45ac
6
+ metadata.gz: 41975ccf93c63dc710021d5fc9823e293af37197ef9d163aa369236c0f4f9948ea8c28aba679cbdcd1176d3caffd00ed662f80f38c32521f7e020e5b390a99f4
7
+ data.tar.gz: e9000159fddf3054c49096a3e885a16df864e405348c97d4a74f6305ddd25c0a46d01e15fda81bb5026c1e3f288e5b1c5f00bc0a4b552f72aee8c9ad44524451
data/README.md CHANGED
@@ -19,6 +19,7 @@ Ori provides a set of primitives that allow you to build concurrent applications
19
19
  - [`Ori::Mutex`](#orimutex)
20
20
  - [`Ori::Semaphore`](#orisemaphore)
21
21
  - [`Ori::Timeout`](#oritimeout)
22
+ - [`Ori::Broadcast`](#oribroadcast)
22
23
  - [Releases](#releases)
23
24
  - [License](#license)
24
25
 
@@ -428,6 +429,67 @@ Timeout!
428
429
 
429
430
  </details>
430
431
 
432
+ #### `Ori::Broadcast`
433
+
434
+ Broadcast provides fan-out message delivery to multiple subscribers. Unlike a `Channel`, where each message is consumed by a single reader, every subscriber to a `Broadcast` receives every message published after they subscribe:
435
+
436
+ ```ruby
437
+ Ori.sync do |scope|
438
+ broadcast = Ori::Broadcast.new
439
+ sub1 = broadcast.subscribe
440
+ sub2 = broadcast.subscribe
441
+
442
+ # Publisher
443
+ scope.fork do
444
+ broadcast << "Hello"
445
+ broadcast << "World"
446
+ end
447
+
448
+ # Both subscribers receive all messages
449
+ scope.fork do
450
+ 2.times { puts "Sub 1: #{sub1.take}" }
451
+ end
452
+
453
+ scope.fork do
454
+ 2.times { puts "Sub 2: #{sub2.take}" }
455
+ end
456
+ end
457
+ ```
458
+
459
+ **Output:**
460
+
461
+ ```
462
+ Sub 1: Hello
463
+ Sub 2: Hello
464
+ Sub 1: World
465
+ Sub 2: World
466
+ ```
467
+
468
+ Subscriptions work with `Ori.select` and pattern matching:
469
+
470
+ ```ruby
471
+ Ori.sync do |scope|
472
+ broadcast = Ori::Broadcast.new
473
+ sub = broadcast.subscribe
474
+ timeout = Ori::Timeout.new(0.5)
475
+
476
+ scope.fork { broadcast << :event }
477
+
478
+ case Ori.select([sub, timeout])
479
+ in Ori::Broadcast::Subscription(value) then puts "Got: #{value}"
480
+ in Ori::Timeout then puts "No events"
481
+ end
482
+ end
483
+ ```
484
+
485
+ Subscribers can unsubscribe at any time to stop receiving future messages:
486
+
487
+ ```ruby
488
+ sub = broadcast.subscribe
489
+ # ...
490
+ sub.unsubscribe
491
+ ```
492
+
431
493
  ## Releases
432
494
 
433
495
  The procedure to publish a new release version is as follows:
@@ -0,0 +1,79 @@
1
+ # typed: true
2
+
3
+ module Ori
4
+ #: [E]
5
+ class Broadcast
6
+ def initialize
7
+ @subscriptions = [] #: Array[Subscription[E]]
8
+ end
9
+
10
+ #: () -> Subscription[E]
11
+ def subscribe
12
+ subscription = Subscription.new(self)
13
+ @subscriptions << subscription
14
+ subscription
15
+ end
16
+
17
+ #: (Subscription[E] subscription) -> void
18
+ def unsubscribe(subscription)
19
+ @subscriptions.delete(subscription)
20
+ end
21
+
22
+ #: (E item) -> void
23
+ def publish(item)
24
+ @subscriptions.each { |sub| sub.__send_item(item) }
25
+ end
26
+ alias_method(:<<, :publish)
27
+
28
+ #: [E]
29
+ class Subscription
30
+ include(Ori::Selectable)
31
+
32
+ #: (Broadcast[E] broadcast) -> void
33
+ def initialize(broadcast)
34
+ @broadcast = broadcast
35
+ @queue = [] #: Array[E]
36
+ end
37
+
38
+ #: () -> E
39
+ def take
40
+ Fiber.yield(self) until value?
41
+ @queue.shift #: as E
42
+ end
43
+
44
+ #: () -> E
45
+ def peek
46
+ Fiber.yield(self) until value?
47
+ @queue.first #: as E
48
+ end
49
+
50
+ #: () -> bool
51
+ def value?
52
+ !@queue.empty?
53
+ end
54
+
55
+ #: () -> Subscription[E]
56
+ def await
57
+ peek
58
+ self
59
+ end
60
+
61
+ #: () -> Array[E]
62
+ def deconstruct
63
+ Ori.sync { peek }
64
+ [take]
65
+ end
66
+
67
+ #: () -> void
68
+ def unsubscribe
69
+ @broadcast.unsubscribe(self)
70
+ end
71
+
72
+ # @api private
73
+ #: (E item) -> void
74
+ def __send_item(item)
75
+ @queue << item
76
+ end
77
+ end
78
+ end
79
+ end
data/lib/ori/scope.rb CHANGED
@@ -457,7 +457,7 @@ module Ori
457
457
  # TODO: shuffle blocked before processing?
458
458
  blocked.each do |fiber, resource|
459
459
  case resource
460
- when Ori::Channel
460
+ when Ori::Channel, Ori::Broadcast::Subscription
461
461
  fibers_to_resume << fiber if resource.value?
462
462
  when Ori::Promise
463
463
  fibers_to_resume << fiber if resource.resolved?
@@ -621,7 +621,7 @@ module Ori
621
621
  when CancellationError
622
622
  @tracer&.record(id, :cancelled, result.message)
623
623
  task_or_fiber.kill
624
- when Ori::Channel, Ori::Promise, Ori::Semaphore, Ori::ReentrantSemaphore
624
+ when Ori::Channel, Ori::Promise, Ori::Semaphore, Ori::ReentrantSemaphore, Ori::Broadcast::Subscription
625
625
  @tracer&.record(id, :resource_wait, result.class.name)
626
626
  blocked[fiber] = result
627
627
  when Task
data/lib/ori/version.rb CHANGED
@@ -1,5 +1,5 @@
1
1
  # typed: strict
2
2
 
3
3
  module Ori
4
- VERSION = "0.4.7"
4
+ VERSION = "0.4.8"
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.7
4
+ version: 0.4.8
5
5
  platform: ruby
6
6
  authors:
7
7
  - Jahfer Husain
@@ -63,6 +63,7 @@ files:
63
63
  - docs/images/example_trace.png
64
64
  - docs/images/example_trace_tag.png
65
65
  - lib/ori.rb
66
+ - lib/ori/broadcast.rb
66
67
  - lib/ori/channel.rb
67
68
  - lib/ori/lazy.rb
68
69
  - lib/ori/mutex.rb