зеркало из https://github.com/github/ruby.git
[ruby/io-console] Store console IO in Ractor-local storage
Ractor requires a shareable class has shareable constants only, but IO is not shareable unless frozen. https://github.com/ruby/io-console/commit/65e0ff895c
This commit is contained in:
Родитель
5dbb67a593
Коммит
4a1ea9b63a
|
@ -81,7 +81,7 @@ getattr(int fd, conmode *t)
|
|||
|
||||
#define CSI "\x1b\x5b"
|
||||
|
||||
static ID id_getc, id_console, id_close;
|
||||
static ID id_getc, id_close;
|
||||
static ID id_gets, id_flush, id_chomp_bang;
|
||||
|
||||
#if defined HAVE_RUBY_FIBER_SCHEDULER_H
|
||||
|
@ -1566,6 +1566,56 @@ rb_io_closed_p(VALUE io)
|
|||
}
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_RB_EXT_RACTOR_SAFE
|
||||
#include "ruby/ractor.h"
|
||||
static rb_ractor_local_key_t key_console_dev;
|
||||
|
||||
static bool
|
||||
console_dev_get(VALUE klass, VALUE *dev)
|
||||
{
|
||||
return rb_ractor_local_storage_value_lookup(key_console_dev, dev);
|
||||
}
|
||||
|
||||
static void
|
||||
console_dev_set(VALUE klass, VALUE value)
|
||||
{
|
||||
rb_ractor_local_storage_value_set(key_console_dev, value);
|
||||
}
|
||||
|
||||
static void
|
||||
console_dev_remove(VALUE klass)
|
||||
{
|
||||
console_dev_set(klass, Qnil);
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
static ID id_console;
|
||||
|
||||
static bool
|
||||
console_dev_get(VALUE klass, VALUE *dev)
|
||||
{
|
||||
if (rb_const_defined(klass, id_console)) {
|
||||
*dev = rb_const_get(klass, id_console);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
static void
|
||||
console_dev_set(VALUE klass, VALUE value)
|
||||
{
|
||||
rb_const_set(klass, id_console, value);
|
||||
}
|
||||
|
||||
static void
|
||||
console_dev_remove(VALUE klass)
|
||||
{
|
||||
rb_const_remove(klass, id_console);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
/*
|
||||
* call-seq:
|
||||
* IO.console -> #<File:/dev/tty>
|
||||
|
@ -1594,10 +1644,9 @@ console_dev(int argc, VALUE *argv, VALUE klass)
|
|||
// Force the class to be File.
|
||||
if (klass == rb_cIO) klass = rb_cFile;
|
||||
|
||||
if (rb_const_defined(klass, id_console)) {
|
||||
con = rb_const_get(klass, id_console);
|
||||
if (console_dev_get(klass, &con)) {
|
||||
if (!RB_TYPE_P(con, T_FILE) || RTEST(rb_io_closed_p(con))) {
|
||||
rb_const_remove(klass, id_console);
|
||||
console_dev_remove(klass);
|
||||
con = 0;
|
||||
}
|
||||
}
|
||||
|
@ -1606,7 +1655,7 @@ console_dev(int argc, VALUE *argv, VALUE klass)
|
|||
if (sym == ID2SYM(id_close) && argc == 1) {
|
||||
if (con) {
|
||||
rb_io_close(con);
|
||||
rb_const_remove(klass, id_console);
|
||||
console_dev_remove(klass);
|
||||
con = 0;
|
||||
}
|
||||
return Qnil;
|
||||
|
@ -1647,7 +1696,7 @@ console_dev(int argc, VALUE *argv, VALUE klass)
|
|||
#ifdef CONSOLE_DEVICE_FOR_WRITING
|
||||
rb_io_set_write_io(con, out);
|
||||
#endif
|
||||
rb_const_set(klass, id_console, con);
|
||||
console_dev_set(klass, con);
|
||||
}
|
||||
|
||||
if (sym) {
|
||||
|
@ -1769,11 +1818,15 @@ Init_console(void)
|
|||
#endif
|
||||
|
||||
#undef rb_intern
|
||||
#ifdef HAVE_RB_EXT_RACTOR_SAFE
|
||||
key_console_dev = rb_ractor_local_storage_value_newkey();
|
||||
#else
|
||||
id_console = rb_intern("console");
|
||||
#endif
|
||||
id_getc = rb_intern("getc");
|
||||
id_gets = rb_intern("gets");
|
||||
id_flush = rb_intern("flush");
|
||||
id_chomp_bang = rb_intern("chomp!");
|
||||
id_console = rb_intern("console");
|
||||
id_close = rb_intern("close");
|
||||
#define init_rawmode_opt_id(name) \
|
||||
rawmode_opt_ids[kwd_##name] = rb_intern(#name)
|
||||
|
|
|
@ -20,5 +20,15 @@ class TestIOConsoleInRactor < Test::Unit::TestCase
|
|||
end
|
||||
puts r.take
|
||||
end;
|
||||
|
||||
assert_in_out_err(%W[-r#{path}], "#{<<~"begin;"}\n#{<<~'end;'}", ["true"], [])
|
||||
begin;
|
||||
console = IO.console
|
||||
$VERBOSE = nil
|
||||
r = Ractor.new do
|
||||
IO.console
|
||||
end
|
||||
puts console.class == r.take.class
|
||||
end;
|
||||
end
|
||||
end if defined? Ractor
|
||||
|
|
Загрузка…
Ссылка в новой задаче