summaryrefslogtreecommitdiff
path: root/bootstraptest
diff options
context:
space:
mode:
authorKoichi Sasada <ko1@atdot.net>2023-03-02 18:27:44 +0900
committerKoichi Sasada <ko1@atdot.net>2023-03-03 00:08:02 +0900
commit5875fce6ce678c444456cc7eed6f28ef000dac24 (patch)
treed18dce5e9da1c5991b154774a579cd0918a7cef5 /bootstraptest
parent5f3c7ac19674b822c72e09e40cfb58fc71ac501e (diff)
downloadruby-5875fce6ce678c444456cc7eed6f28ef000dac24.tar.gz
`Ractor::Selector#empty?`
It returns the waiting set is empty or not. Also add Ractor::Selector's tests.
Diffstat (limited to 'bootstraptest')
-rw-r--r--bootstraptest/test_ractor.rb96
1 files changed, 96 insertions, 0 deletions
diff --git a/bootstraptest/test_ractor.rb b/bootstraptest/test_ractor.rb
index 3d0fdfa283..5f7cba3947 100644
--- a/bootstraptest/test_ractor.rb
+++ b/bootstraptest/test_ractor.rb
@@ -1617,4 +1617,100 @@ assert_match /\Atest_ractor\.rb:1:\s+warning:\s+Ractor is experimental/, %q{
eval("Ractor.new{}.take", nil, "test_ractor.rb", 1)
}
+## Ractor::Selector
+
+# Selector#empty? returns true
+assert_equal 'true', %q{
+ s = Ractor::Selector.new
+ s.empty?
+}
+
+# Selector#empty? returns false if there is target ractors
+assert_equal 'false', %q{
+ s = Ractor::Selector.new
+ s.add Ractor.new{}
+ s.empty?
+}
+
+# Selector#clear removes all ractors from the waiting list
+assert_equal 'true', %q{
+ s = Ractor::Selector.new
+ s.add Ractor.new{10}
+ s.add Ractor.new{20}
+ s.clear
+ s.empty?
+}
+
+# Selector#wait can wait multiple ractors
+assert_equal '[10, 20, true]', %q{
+ s = Ractor::Selector.new
+ s.add Ractor.new{10}
+ s.add Ractor.new{20}
+ r, v = s.wait
+ vs = []
+ vs << v
+ r, v = s.wait
+ vs << v
+ [*vs.sort, s.empty?]
+}
+
+# Selector#wait can wait multiple ractors with receiving.
+assert_equal '30', %q{
+ RN = 30
+ rs = RN.times.map{
+ Ractor.new{ :v }
+ }
+ s = Ractor::Selector.new(*rs)
+
+ results = []
+ until s.empty?
+ results << s.wait
+
+ # Note that s.wait can raise an exception because other Ractors/Threads
+ # can take from the same ractors in the waiting set.
+ # In this case there is no other takers so `s.wait` doesn't raise an error.
+ end
+
+ results.size
+}
+
+# Selector#wait can support dynamic addition
+assert_equal '600', %q{
+ RN = 100
+ s = Ractor::Selector.new
+ rs = RN.times.map{
+ Ractor.new{
+ Ractor.main << Ractor.new{ Ractor.yield :v3; :v4 }
+ Ractor.main << Ractor.new{ Ractor.yield :v5; :v6 }
+ Ractor.yield :v1
+ :v2
+ }
+ }
+
+ rs.each{|r| s.add(r)}
+ h = {v1: 0, v2: 0, v3: 0, v4: 0, v5: 0, v6: 0}
+
+ loop do
+ case s.wait receive: true
+ in :receive, r
+ s.add r
+ in r, v
+ h[v] += 1
+ break if h.all?{|k, v| v == RN}
+ end
+ end
+
+ h.sum{|k, v| v}
+}
+
+# Selector should be GCed (free'ed) withtou trouble
+assert_equal 'ok', %q{
+ RN = 30
+ rs = RN.times.map{
+ Ractor.new{ :v }
+ }
+ s = Ractor::Selector.new(*rs)
+ :ok
+}
+
end # if !ENV['GITHUB_WORKFLOW']