[前][次][番号順一覧][スレッド一覧]

ruby-changes:67252

From: Sutou <ko1@a...>
Date: Thu, 26 Aug 2021 13:30:15 +0900 (JST)
Subject: [ruby-changes:67252] a2ad0cb7b4 (master): Make Hash#each family usable in Ractor

https://git.ruby-lang.org/ruby.git/commit/?id=a2ad0cb7b4

From a2ad0cb7b44a0cb87bd552b312a70bc46016a95f Mon Sep 17 00:00:00 2001
From: Sutou Kouhei <kou@c...>
Date: Tue, 24 Aug 2021 11:22:00 +0900
Subject: Make Hash#each family usable in Ractor

We don't need to increment/decrement iteration level for frozen Hash
because frozen Hash can't be modified. We can assume that nobody
changes the target Hash while calling #each family.

How to reproduce:

    a = {}
    100.times do |i|
      a[i] = true
    end
    Ractor.make_shareable(a)

    4.times.collect do
      Ractor.new(a) do |b|
        100.times do
          b.each_value do
          end
        end
      end
    end.each(&:take)

Example output:

    internal:ractor>:267: warning: Ractor is experimental, and the behavior may change in future versions of Ruby! Also there are many implementation issues.
    #<Thread:0x00007fcfb087bb30 run> terminated with exception (report_on_exception is true):
    #<Thread:0x00007fcfb087b8d8 run> terminated with exception (report_on_exception is true):
    #<Thread:0x00007fcfb088d678 run> terminated with exception (report_on_exception is true):
    #<Thread:0x00007fcfb087bd88 run> terminated with exception (report_on_exception is true):
    /tmp/h.rb:10:in `each_value'/tmp/h.rb:10:in `each_value': : /tmp/h.rb:10:in `each_value'no implicit conversion from nil to integer/tmp/h.rb:10:in `each_value'no implicit conversion from nil to integer (: :  (TypeErrorTypeError)no implicit conversion from nil to integer)no implicit conversion from nil to integer (

     (TypeErrorTypeError	from /tmp/h.rb:10:in `block (3 levels) in <main>'
    	from /tmp/h.rb:10:in `block (3 levels) in <main>'
    ))	from /tmp/h.rb:9:in `times'

    	from /tmp/h.rb:9:in `times'

    	from /tmp/h.rb:9:in `block (2 levels) in <main>'
    	from /tmp/h.rb:10:in `block (3 levels) in <main>'
    	from /tmp/h.rb:10:in `block (3 levels) in <main>'
    	from /tmp/h.rb:9:in `block (2 levels) in <main>'
    	from /tmp/h.rb:9:in `times'
    	from /tmp/h.rb:9:in `times'
    	from /tmp/h.rb:9:in `block (2 levels) in <main>'
    	from /tmp/h.rb:9:in `block (2 levels) in <main>'
    <internal:ractor>:694:in `take': thrown by remote Ractor. (Ractor::RemoteError)
    	from /tmp/h.rb:14:in `each'
    	from /tmp/h.rb:14:in `<main>'
    /tmp/h.rb:10:in `each_value': no implicit conversion from nil to integer (TypeError)
    	from /tmp/h.rb:10:in `block (3 levels) in <main>'
    	from /tmp/h.rb:9:in `times'
    	from /tmp/h.rb:9:in `block (2 levels) in <main>'
---
 hash.c | 9 +++++++--
 1 file changed, 7 insertions(+), 2 deletions(-)

diff --git a/hash.c b/hash.c
index 6fa85e8..6675b81 100644
--- a/hash.c
+++ b/hash.c
@@ -1503,11 +1503,16 @@ rb_hash_foreach(VALUE hash, rb_foreach_func *func, VALUE farg) https://github.com/ruby/ruby/blob/trunk/hash.c#L1503
 
     if (RHASH_TABLE_EMPTY_P(hash))
         return;
-    hash_iter_lev_inc(hash);
     arg.hash = hash;
     arg.func = (rb_foreach_func *)func;
     arg.arg  = farg;
-    rb_ensure(hash_foreach_call, (VALUE)&arg, hash_foreach_ensure, hash);
+    if (RB_OBJ_FROZEN(hash)) {
+        hash_foreach_call((VALUE)&arg);
+    }
+    else {
+        hash_iter_lev_inc(hash);
+        rb_ensure(hash_foreach_call, (VALUE)&arg, hash_foreach_ensure, hash);
+    }
     hash_verify(hash);
 }
 
-- 
cgit v1.1


--
ML: ruby-changes@q...
Info: http://www.atdot.net/~ko1/quickml/

[前][次][番号順一覧][スレッド一覧]