ori-rb 0.4
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 +7 -0
- data/.rubocop.yml +8 -0
- data/.ruby-version +1 -0
- data/LICENSE +9 -0
- data/README.md +444 -0
- data/Rakefile +17 -0
- data/docs/images/example_boundary.png +0 -0
- data/docs/images/example_boundary_cancellation.png +0 -0
- data/docs/images/example_channel.png +0 -0
- data/docs/images/example_mutex.png +0 -0
- data/docs/images/example_promise.png +0 -0
- data/docs/images/example_semaphore.png +0 -0
- data/docs/images/example_trace.png +0 -0
- data/docs/images/example_trace_tag.png +0 -0
- data/lib/ori/channel.rb +148 -0
- data/lib/ori/lazy.rb +163 -0
- data/lib/ori/mutex.rb +9 -0
- data/lib/ori/out/index.html +146 -0
- data/lib/ori/out/script.js +3 -0
- data/lib/ori/promise.rb +39 -0
- data/lib/ori/reentrant_semaphore.rb +68 -0
- data/lib/ori/scope.rb +620 -0
- data/lib/ori/select.rb +35 -0
- data/lib/ori/selectable.rb +9 -0
- data/lib/ori/semaphore.rb +49 -0
- data/lib/ori/task.rb +78 -0
- data/lib/ori/timeout.rb +16 -0
- data/lib/ori/tracer.rb +335 -0
- data/lib/ori/version.rb +5 -0
- data/lib/ori.rb +68 -0
- data/mise-tasks/test +15 -0
- data/mise.toml +40 -0
- data/sorbet/config +8 -0
- data/sorbet/rbi/gems/.gitattributes +1 -0
- data/sorbet/rbi/gems/ast@2.4.3.rbi +585 -0
- data/sorbet/rbi/gems/benchmark@0.4.1.rbi +619 -0
- data/sorbet/rbi/gems/date@3.4.1.rbi +75 -0
- data/sorbet/rbi/gems/erb@5.1.1.rbi +845 -0
- data/sorbet/rbi/gems/erubi@1.13.1.rbi +155 -0
- data/sorbet/rbi/gems/io-console@0.8.1.rbi +9 -0
- data/sorbet/rbi/gems/json@2.15.1.rbi +2101 -0
- data/sorbet/rbi/gems/language_server-protocol@3.17.0.5.rbi +9 -0
- data/sorbet/rbi/gems/lint_roller@1.1.0.rbi +240 -0
- data/sorbet/rbi/gems/logger@1.7.0.rbi +963 -0
- data/sorbet/rbi/gems/minitest@5.26.0.rbi +2234 -0
- data/sorbet/rbi/gems/netrc@0.11.0.rbi +159 -0
- data/sorbet/rbi/gems/nio4r@2.7.4.rbi +293 -0
- data/sorbet/rbi/gems/parallel@1.27.0.rbi +291 -0
- data/sorbet/rbi/gems/parser@3.3.9.0.rbi +5535 -0
- data/sorbet/rbi/gems/pp@0.6.3.rbi +376 -0
- data/sorbet/rbi/gems/prettyprint@0.2.0.rbi +477 -0
- data/sorbet/rbi/gems/prism@1.5.2.rbi +42056 -0
- data/sorbet/rbi/gems/psych@5.2.6.rbi +2469 -0
- data/sorbet/rbi/gems/racc@1.8.1.rbi +160 -0
- data/sorbet/rbi/gems/rainbow@3.1.1.rbi +403 -0
- data/sorbet/rbi/gems/rake@13.3.0.rbi +3036 -0
- data/sorbet/rbi/gems/rbi@0.3.7.rbi +7115 -0
- data/sorbet/rbi/gems/rbs@3.9.5.rbi +6978 -0
- data/sorbet/rbi/gems/rdoc@6.15.0.rbi +12777 -0
- data/sorbet/rbi/gems/regexp_parser@2.11.3.rbi +3845 -0
- data/sorbet/rbi/gems/reline@0.6.2.rbi +9 -0
- data/sorbet/rbi/gems/rexml@3.4.4.rbi +5285 -0
- data/sorbet/rbi/gems/rubocop-ast@1.47.1.rbi +7780 -0
- data/sorbet/rbi/gems/rubocop-shopify@2.17.1.rbi +9 -0
- data/sorbet/rbi/gems/rubocop-sorbet@0.11.0.rbi +2506 -0
- data/sorbet/rbi/gems/rubocop@1.81.1.rbi +63489 -0
- data/sorbet/rbi/gems/ruby-progressbar@1.13.0.rbi +1318 -0
- data/sorbet/rbi/gems/spoom@1.6.3.rbi +6985 -0
- data/sorbet/rbi/gems/stringio@3.1.7.rbi +9 -0
- data/sorbet/rbi/gems/tapioca@0.16.11.rbi +3628 -0
- data/sorbet/rbi/gems/thor@1.4.0.rbi +4399 -0
- data/sorbet/rbi/gems/tsort@0.2.0.rbi +393 -0
- data/sorbet/rbi/gems/unicode-display_width@3.2.0.rbi +132 -0
- data/sorbet/rbi/gems/unicode-emoji@4.1.0.rbi +251 -0
- data/sorbet/rbi/gems/vernier@1.8.1-96ce5c739bfe6a18d2f4393f4219a1bf48674b87.rbi +904 -0
- data/sorbet/rbi/gems/yard-sorbet@0.9.0.rbi +435 -0
- data/sorbet/rbi/gems/yard@0.9.37.rbi +18379 -0
- data/sorbet/rbi/gems/zeitwerk@2.7.3.rbi +1429 -0
- data/sorbet/shims/fiber.rbi +21 -0
- data/sorbet/shims/io.rbi +8 -0
- data/sorbet/shims/random.rbi +9 -0
- data/sorbet/shims/rdoc.rbi +3 -0
- data/sorbet/tapioca/require.rb +7 -0
- metadata +169 -0
data/lib/ori/lazy.rb
ADDED
@@ -0,0 +1,163 @@
|
|
1
|
+
# typed: true
|
2
|
+
|
3
|
+
module Ori
|
4
|
+
class Lazy
|
5
|
+
def initialize(init_proc)
|
6
|
+
@proc = init_proc
|
7
|
+
end
|
8
|
+
|
9
|
+
def internal
|
10
|
+
@internal ||= @proc.call
|
11
|
+
end
|
12
|
+
|
13
|
+
def initialized?
|
14
|
+
instance_variable_defined?(:@internal)
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
class LazyEnumerable < Lazy
|
19
|
+
def each(&block)
|
20
|
+
return enum_for(:each) unless block_given?
|
21
|
+
return self unless initialized?
|
22
|
+
|
23
|
+
internal.each(&block)
|
24
|
+
end
|
25
|
+
|
26
|
+
def delete_if(&block)
|
27
|
+
return self unless initialized?
|
28
|
+
|
29
|
+
internal.delete_if(&block)
|
30
|
+
end
|
31
|
+
|
32
|
+
def any?(&block)
|
33
|
+
return false unless initialized?
|
34
|
+
|
35
|
+
internal.any?(&block)
|
36
|
+
end
|
37
|
+
|
38
|
+
def empty?
|
39
|
+
return true unless initialized?
|
40
|
+
|
41
|
+
internal.empty?
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
class LazyArray < LazyEnumerable
|
46
|
+
INIT = proc { [] }
|
47
|
+
def initialize
|
48
|
+
super(INIT)
|
49
|
+
end
|
50
|
+
|
51
|
+
def [](index)
|
52
|
+
internal[index] if initialized?
|
53
|
+
end
|
54
|
+
|
55
|
+
def push(value)
|
56
|
+
internal.push(value)
|
57
|
+
end
|
58
|
+
|
59
|
+
def []=(index, value)
|
60
|
+
internal[index] = value
|
61
|
+
end
|
62
|
+
|
63
|
+
alias_method :<<, :push
|
64
|
+
|
65
|
+
def size
|
66
|
+
return 0 unless initialized?
|
67
|
+
|
68
|
+
internal.size
|
69
|
+
end
|
70
|
+
|
71
|
+
def shift
|
72
|
+
return unless initialized?
|
73
|
+
|
74
|
+
internal.shift
|
75
|
+
end
|
76
|
+
end
|
77
|
+
|
78
|
+
class LazyHash < LazyEnumerable
|
79
|
+
INIT = proc { {} }
|
80
|
+
|
81
|
+
def initialize
|
82
|
+
super(INIT)
|
83
|
+
end
|
84
|
+
|
85
|
+
def [](key)
|
86
|
+
internal[key] if initialized?
|
87
|
+
end
|
88
|
+
|
89
|
+
def []=(key, value)
|
90
|
+
internal[key] = value
|
91
|
+
end
|
92
|
+
|
93
|
+
def delete(key)
|
94
|
+
internal.delete(key) if initialized?
|
95
|
+
end
|
96
|
+
|
97
|
+
def key?(key)
|
98
|
+
return false unless initialized?
|
99
|
+
|
100
|
+
internal.key?(key)
|
101
|
+
end
|
102
|
+
|
103
|
+
def fetch(index, default = nil)
|
104
|
+
internal[index] || default
|
105
|
+
end
|
106
|
+
|
107
|
+
def reject(&block)
|
108
|
+
return self unless initialized?
|
109
|
+
|
110
|
+
internal.reject(&block)
|
111
|
+
end
|
112
|
+
|
113
|
+
def keys
|
114
|
+
return [] unless initialized?
|
115
|
+
|
116
|
+
internal.keys
|
117
|
+
end
|
118
|
+
|
119
|
+
def values
|
120
|
+
return [] unless initialized?
|
121
|
+
|
122
|
+
internal.values
|
123
|
+
end
|
124
|
+
|
125
|
+
def none?
|
126
|
+
return true unless initialized?
|
127
|
+
|
128
|
+
internal.none?
|
129
|
+
end
|
130
|
+
end
|
131
|
+
|
132
|
+
class LazyHashSet < LazyEnumerable
|
133
|
+
INIT = proc { Hash.new { |hash, key| hash[key] = Set.new } }
|
134
|
+
|
135
|
+
def initialize
|
136
|
+
super(INIT)
|
137
|
+
end
|
138
|
+
|
139
|
+
def [](key)
|
140
|
+
internal[key]
|
141
|
+
end
|
142
|
+
|
143
|
+
def []=(key, value)
|
144
|
+
internal[key] = value
|
145
|
+
end
|
146
|
+
|
147
|
+
def none?(&block)
|
148
|
+
return true unless initialized?
|
149
|
+
|
150
|
+
internal.none?(&block)
|
151
|
+
end
|
152
|
+
|
153
|
+
def keys
|
154
|
+
return [] unless initialized?
|
155
|
+
|
156
|
+
internal.keys
|
157
|
+
end
|
158
|
+
|
159
|
+
def delete(key)
|
160
|
+
internal.delete(key) if initialized?
|
161
|
+
end
|
162
|
+
end
|
163
|
+
end
|
data/lib/ori/mutex.rb
ADDED
@@ -0,0 +1,146 @@
|
|
1
|
+
<!DOCTYPE html>
|
2
|
+
<html>
|
3
|
+
<head>
|
4
|
+
<style>
|
5
|
+
body {
|
6
|
+
font-family: system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Open Sans', 'Helvetica Neue', sans-serif;
|
7
|
+
}
|
8
|
+
|
9
|
+
.vis-nesting-group.scope {
|
10
|
+
background-color: #e8f6ff !important;
|
11
|
+
border: none !important;
|
12
|
+
border-bottom: 1px solid #ccc !important;
|
13
|
+
}
|
14
|
+
.vis-group.scope {
|
15
|
+
background-color: #ffffd9;
|
16
|
+
}
|
17
|
+
|
18
|
+
.vis-nested-group.fiber {
|
19
|
+
background-color: #ffe8e8 !important;
|
20
|
+
border: none !important;
|
21
|
+
border-bottom: 1px solid #ccc !important;
|
22
|
+
}
|
23
|
+
|
24
|
+
.vis-item {
|
25
|
+
border: none;
|
26
|
+
}
|
27
|
+
|
28
|
+
.vis-item.created, .vis-item.opened {
|
29
|
+
background-color: #fff;
|
30
|
+
border-color: #ccc;
|
31
|
+
}
|
32
|
+
|
33
|
+
.vis-item.yielded {
|
34
|
+
background-color: #fff7ba;
|
35
|
+
border-color: #cab200;
|
36
|
+
border-style: dashed !important;
|
37
|
+
}
|
38
|
+
|
39
|
+
.vis-item.awaiting {
|
40
|
+
background-color: #fff;
|
41
|
+
border-color: #ccc;
|
42
|
+
}
|
43
|
+
|
44
|
+
.vis-item.sleeping {
|
45
|
+
background-color: #ffd7f9;
|
46
|
+
border-color: #f595e6;
|
47
|
+
border-style: dashed !important;
|
48
|
+
}
|
49
|
+
|
50
|
+
.vis-item.resuming {
|
51
|
+
background-color: #dddcff;
|
52
|
+
border-color: #a09dff;
|
53
|
+
}
|
54
|
+
|
55
|
+
.vis-item.completed, .vis-item.closed {
|
56
|
+
background-color: #e2ffe2;
|
57
|
+
border-color: #91df91;
|
58
|
+
}
|
59
|
+
|
60
|
+
.vis-item.waiting_io {
|
61
|
+
background-color: #ffd7f9;
|
62
|
+
border-color: #f595e6;
|
63
|
+
border-style: dashed !important;
|
64
|
+
}
|
65
|
+
|
66
|
+
.vis-item.error {
|
67
|
+
background-color: #ff5858;
|
68
|
+
border-color: #e12222;
|
69
|
+
color: #fff;
|
70
|
+
}
|
71
|
+
|
72
|
+
.vis-item.cancelled {
|
73
|
+
background-color: #450404;
|
74
|
+
border-color: #000;
|
75
|
+
color: #fff;
|
76
|
+
}
|
77
|
+
|
78
|
+
.vis-item.cancelling {
|
79
|
+
background-color: #ff9393;
|
80
|
+
border-color: #ff6363;
|
81
|
+
color: #fff;
|
82
|
+
}
|
83
|
+
|
84
|
+
.vis-item.tag {
|
85
|
+
background-color: #fef49c;
|
86
|
+
border-color: #d9cf78;
|
87
|
+
font-family: "HanziPen SC";
|
88
|
+
color: #6f6a40;
|
89
|
+
}
|
90
|
+
|
91
|
+
.vis-item.resource_wait {
|
92
|
+
background-color: #fff7ba;
|
93
|
+
border-color: #cab200;
|
94
|
+
border-style: dashed !important;
|
95
|
+
}
|
96
|
+
|
97
|
+
.vis-item.memcached_read {
|
98
|
+
background-color: #c4f2ef;
|
99
|
+
border-color: #84c1bd;
|
100
|
+
}
|
101
|
+
|
102
|
+
.vis-item.memcached_write {
|
103
|
+
background-color: #b5efb9;
|
104
|
+
border-color: #81c385;
|
105
|
+
}
|
106
|
+
</style>
|
107
|
+
</head>
|
108
|
+
<body>
|
109
|
+
<div id="visualization"></div>
|
110
|
+
<p><pre>cmd+scroll to zoom</pre></p>
|
111
|
+
<script type="text/javascript" src="https://unpkg.com/vis-timeline/standalone/umd/vis-timeline-graph2d.min.js"></script>
|
112
|
+
<script type="module" src="script.js"></script>
|
113
|
+
|
114
|
+
<script type="module">
|
115
|
+
import { dataset, groups } from "./script.js";
|
116
|
+
const container = document.getElementById("visualization");
|
117
|
+
|
118
|
+
const items = new vis.DataSet(dataset);
|
119
|
+
const vis_groups = new vis.DataSet(groups);
|
120
|
+
const timeline = new vis.Timeline(container);
|
121
|
+
|
122
|
+
const min = Math.min(...dataset.map(item => item.start));
|
123
|
+
const max = Math.max(...dataset.map(item => item.end)) || Math.max(...dataset.map(item => item.start));
|
124
|
+
|
125
|
+
timeline.setOptions({
|
126
|
+
editable: false,
|
127
|
+
start: 0,
|
128
|
+
end: max * 1.3,
|
129
|
+
min: 0,
|
130
|
+
max: max * 1.3,
|
131
|
+
align: "left",
|
132
|
+
showTooltips: true,
|
133
|
+
showMajorLabels: false,
|
134
|
+
selectable: false,
|
135
|
+
zoomKey: "metaKey",
|
136
|
+
tooltip: {
|
137
|
+
template: ({data}) => data ? JSON.stringify(data) : "",
|
138
|
+
delay: 200,
|
139
|
+
},
|
140
|
+
order: (a, b) => b.start - a.start
|
141
|
+
});
|
142
|
+
timeline.setGroups(vis_groups);
|
143
|
+
timeline.setItems(items);
|
144
|
+
</script>
|
145
|
+
</body>
|
146
|
+
</html>
|
@@ -0,0 +1,3 @@
|
|
1
|
+
export const groups = [{"id":"main","content":"Root Scope","value":1,"className":"main-scope","nestedGroups":["scope_0193a84b-d670-7066-83b3-7413095d5d28"],"showNested":true},{"id":"scope_0193a84b-d670-7066-83b3-7413095d5d28","order":"0193a84b-d670-7066-83b3-7413095d5d28","content":"Scope 0193a84b-d670-7066-83b3-7413095d5d28","value":2,"className":"scope","showNested":false,"nestedGroups":["fiber_0193a84b-d670-70a7-a1d1-978f760caca3","fiber_0193a84b-d670-70d4-b26a-e0d21d5496bd","fiber_0193a84b-d670-70f9-9d7d-5a00cc080632"]},{"id":"fiber_0193a84b-d670-70a7-a1d1-978f760caca3","content":"Fiber 0193a84b-d670-70a7-a1d1-978f760caca3","value":3,"className":"fiber","showNested":false},{"id":"fiber_0193a84b-d670-70d4-b26a-e0d21d5496bd","content":"Fiber 0193a84b-d670-70d4-b26a-e0d21d5496bd","value":3,"className":"fiber","showNested":false},{"id":"fiber_0193a84b-d670-70f9-9d7d-5a00cc080632","content":"Fiber 0193a84b-d670-70f9-9d7d-5a00cc080632","value":3,"className":"fiber","showNested":false}];
|
2
|
+
|
3
|
+
export const dataset = [{"group":"scope_0193a84b-d670-7066-83b3-7413095d5d28","content":"opened","start":"0","className":"opened","data":null},{"group":"scope_0193a84b-d670-7066-83b3-7413095d5d28","content":"awaiting","start":"35","className":"awaiting","data":null},{"group":"scope_0193a84b-d670-7066-83b3-7413095d5d28","content":"awaiting","start":"10501","className":"awaiting","data":null},{"group":"scope_0193a84b-d670-7066-83b3-7413095d5d28","content":"closed","start":"10531","className":"closed","data":null},{"group":"fiber_0193a84b-d670-70a7-a1d1-978f760caca3","content":"created","start":"8","className":"created","data":null},{"group":"fiber_0193a84b-d670-70a7-a1d1-978f760caca3","content":"resuming","start":"10","className":"resuming","data":null},{"group":"fiber_0193a84b-d670-70d4-b26a-e0d21d5496bd","content":"created","start":"16","className":"created","data":null},{"group":"fiber_0193a84b-d670-70d4-b26a-e0d21d5496bd","content":"resuming","start":"16","className":"resuming","data":null},{"group":"fiber_0193a84b-d670-70d4-b26a-e0d21d5496bd","content":"sleeping","start":"21","className":"sleeping","data":0.01},{"group":"fiber_0193a84b-d670-70d4-b26a-e0d21d5496bd","content":"yielded","start":"23","className":"yielded","data":null},{"group":"fiber_0193a84b-d670-70f9-9d7d-5a00cc080632","content":"created","start":"25","className":"created","data":null},{"group":"fiber_0193a84b-d670-70f9-9d7d-5a00cc080632","content":"resuming","start":"25","className":"resuming","data":null},{"group":"fiber_0193a84b-d670-70f9-9d7d-5a00cc080632","content":"yielded","start":"28","className":"yielded","data":null},{"group":"fiber_0193a84b-d670-70a7-a1d1-978f760caca3","content":"completed","start":"33","className":"completed","data":null},{"group":"fiber_0193a84b-d670-70f9-9d7d-5a00cc080632","content":"resuming","start":"43","className":"resuming","data":null},{"group":"fiber_0193a84b-d670-70f9-9d7d-5a00cc080632","content":"yielded","start":"44","className":"yielded","data":null},{"group":"fiber_0193a84b-d670-70d4-b26a-e0d21d5496bd","content":"resuming","start":"10482","className":"resuming","data":null},{"group":"fiber_0193a84b-d670-70d4-b26a-e0d21d5496bd","content":"completed","start":"10497","className":"completed","data":null},{"group":"fiber_0193a84b-d670-70f9-9d7d-5a00cc080632","content":"resuming","start":"10514","className":"resuming","data":null},{"group":"fiber_0193a84b-d670-70f9-9d7d-5a00cc080632","content":"completed","start":"10518","className":"completed","data":null}];
|
data/lib/ori/promise.rb
ADDED
@@ -0,0 +1,39 @@
|
|
1
|
+
# typed: true
|
2
|
+
|
3
|
+
module Ori
|
4
|
+
#: [E]
|
5
|
+
class Promise
|
6
|
+
include(Ori::Selectable)
|
7
|
+
|
8
|
+
def initialize
|
9
|
+
@resolved = false
|
10
|
+
@value = nil
|
11
|
+
end
|
12
|
+
|
13
|
+
#: (E value) -> void
|
14
|
+
def resolve(value)
|
15
|
+
raise "Promise already resolved" if resolved?
|
16
|
+
|
17
|
+
@resolved = true
|
18
|
+
@value = value
|
19
|
+
end
|
20
|
+
|
21
|
+
#: () -> bool
|
22
|
+
def resolved?
|
23
|
+
@resolved
|
24
|
+
end
|
25
|
+
|
26
|
+
def deconstruct
|
27
|
+
await unless resolved?
|
28
|
+
[@value]
|
29
|
+
end
|
30
|
+
|
31
|
+
#: () -> E
|
32
|
+
def await
|
33
|
+
return @value if resolved?
|
34
|
+
|
35
|
+
Fiber.yield(self) until resolved?
|
36
|
+
@value
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
@@ -0,0 +1,68 @@
|
|
1
|
+
# typed: true
|
2
|
+
|
3
|
+
module Ori
|
4
|
+
class ReentrantSemaphore
|
5
|
+
include(Ori::Selectable)
|
6
|
+
|
7
|
+
def initialize(num_tickets)
|
8
|
+
raise ArgumentError, "Number of tickets must be positive" if num_tickets <= 0
|
9
|
+
|
10
|
+
@tickets = num_tickets
|
11
|
+
@available = num_tickets
|
12
|
+
@owners = Hash.new(0) # Track fiber -> acquire count
|
13
|
+
end
|
14
|
+
|
15
|
+
def sync
|
16
|
+
acquire
|
17
|
+
begin
|
18
|
+
yield
|
19
|
+
ensure
|
20
|
+
release
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
def release
|
25
|
+
current = Fiber.current
|
26
|
+
|
27
|
+
if @owners[current] > 0
|
28
|
+
@owners[current] -= 1
|
29
|
+
if @owners[current] == 0
|
30
|
+
@owners.delete(current)
|
31
|
+
@available += 1
|
32
|
+
end
|
33
|
+
return true
|
34
|
+
end
|
35
|
+
|
36
|
+
raise "Cannot release semaphore - not owned by current fiber"
|
37
|
+
end
|
38
|
+
|
39
|
+
def acquire
|
40
|
+
current = Fiber.current
|
41
|
+
|
42
|
+
# If this fiber already owns the semaphore, increment its count
|
43
|
+
if @owners[current] > 0
|
44
|
+
@owners[current] += 1
|
45
|
+
return true
|
46
|
+
end
|
47
|
+
|
48
|
+
# Otherwise wait for an available ticket
|
49
|
+
Fiber.yield(self) until available?
|
50
|
+
@available -= 1
|
51
|
+
@owners[current] = 1
|
52
|
+
true
|
53
|
+
end
|
54
|
+
|
55
|
+
def available?
|
56
|
+
@available > 0 || @owners[Fiber.current] > 0
|
57
|
+
end
|
58
|
+
|
59
|
+
def count
|
60
|
+
@available
|
61
|
+
end
|
62
|
+
|
63
|
+
def await
|
64
|
+
Fiber.yield until available?
|
65
|
+
true
|
66
|
+
end
|
67
|
+
end
|
68
|
+
end
|