ruby-core@ruby-lang.org archive (unofficial mirror)
 help / color / mirror / Atom feed
* [ruby-core:99958] [Ruby master Bug#17159] extend `define_method` for Ractor
@ 2020-09-07  1:49 ko1
  2020-09-07  2:39 ` [ruby-core:99959] " matz
                   ` (6 more replies)
  0 siblings, 7 replies; 8+ messages in thread
From: ko1 @ 2020-09-07  1:49 UTC (permalink / raw)
  To: ruby-core

Issue #17159 has been reported by ko1 (Koichi Sasada).

----------------------------------------
Bug #17159: extend `define_method` for Ractor
https://bugs.ruby-lang.org/issues/17159

* Author: ko1 (Koichi Sasada)
* Status: Open
* Priority: Normal
* Backport: 2.5: UNKNOWN, 2.6: UNKNOWN, 2.7: UNKNOWN
----------------------------------------
Ractor prohibits to use non-isolated Procs.

Non-isolated example is here:

```
s = "foo"
pr = Proc.new{ p s }
```

This Proc pr can not be shared with multi-ractors because outer variable `s` can contain an unshareable object. Also outer binding is mutable object so it can lead race condition.

Because of these reasons, `define_method` are also problem on multi-Ractor program.
(current implementation allows it just because check is not implemented, and it leads BUG).


I think there are several patterns `define_method` are used.

(1) want to choose variable method names

```ruby
name = ...
define_method(name){ nil }
```

(2) want to embed variables to the code

```ruby
10.times{|i|
  define_method("foo{i}"){ i }
}
```

(3) want to use global state by local variables

```ruby
cnt = 0
define_method("inc"){ cnt += 1 }
```

(4) others I can't imagine

----

(1) is easy. `define_method(name, &Proc{nil}.isoplate)` will be allowed on multi-ractors.

(3) is not allowed because it introduces data races/race conditions. For example, we need to use shared hash.

```ruby
STATE = SharedHash.new(cnt: 0)
define_method("inc"){ STATE.transaction{ STATE[:cnt] += 1 }}
```

I think there are many (2) patterns and it should be saved.
To help (2) pattern, the easiest way is to use eval.

```ruby
10.times{|i|
  eval("def foo#{i} #{i}; end")
}

```

However, eval has several issues (it has huge freedom to explode the program, editor's syntax highlighting and so on).

Another approach is embed the current value to the code, like that:


```ruby
i = 0
define_method("foo", ractorise: true){ i }
#=> equivalent to:
#   define_method("foo"){ 0 }
# so that if outer scope's i changed, not affected.
i = 1
foo #=> 0

s = ""
define_method("bar", ractorise: true){ s }
#=> equivalent to:
#   define_method("bar"){ "" }
# so that if outer scope's s or s's value, it doesn't affect
s << "x"
bar #=> ""
```

However, it is very difference between current Proc semantics.
Another idea is to specify embedding value like that.

```ruby
i = 0
define_method("foo", i: i){ i }
#=> equivalent to:
#   define_method("foo"){ 0 }
# so that if outer scope's i changed, not affected.
i = 1
foo #=> 0

s = ""
define_method("bar", s: s){ s }
#=> equivalent to:
#   define_method("bar"){ "" }
# so that if outer scope's s or s's value, it doesn't affect
s << "x"
bar #=> ""
```

`i: i` and `s: s` are redundant. however, if there are no outer variable `i` or `s`, the `i` and `s` in blocks are compiled to `send(:i)` or `send(:s)`. But I agree these method invocation should be replaced is another idea.


Thoughts?

Thanks,
Koichi



-- 
https://bugs.ruby-lang.org/

^ permalink raw reply	[flat|nested] 8+ messages in thread

end of thread, other threads:[~2020-10-29 16:06 UTC | newest]

Thread overview: 8+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2020-09-07  1:49 [ruby-core:99958] [Ruby master Bug#17159] extend `define_method` for Ractor ko1
2020-09-07  2:39 ` [ruby-core:99959] " matz
2020-09-07  4:36 ` [ruby-core:99960] " ko1
2020-09-13 10:01 ` [ruby-core:100002] " eregontp
2020-09-13 10:07 ` [ruby-core:100003] " eregontp
2020-09-14  1:29 ` [ruby-core:100004] " shyouhei
2020-10-25 20:08 ` [ruby-core:100538] " marcandre-ruby-core
2020-10-29 16:06 ` [ruby-core:100646] " ko1

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).