summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--bootstraptest/test_ractor.rb14
-rw-r--r--ractor.c46
-rw-r--r--ractor.rb10
-rw-r--r--ractor_core.h1
4 files changed, 71 insertions, 0 deletions
diff --git a/bootstraptest/test_ractor.rb b/bootstraptest/test_ractor.rb
index a853e91416..06bd739931 100644
--- a/bootstraptest/test_ractor.rb
+++ b/bootstraptest/test_ractor.rb
@@ -1245,6 +1245,20 @@ assert_equal '[:ok, :ok]', %q{
end
}
+# Ractor-local storage
+assert_equal '[nil, "b", "a"]', %q{
+ ans = []
+ Ractor.current[:key] = 'a'
+ r = Ractor.new{
+ Ractor.yield self[:key]
+ self[:key] = 'b'
+ self[:key]
+ }
+ ans << r.take
+ ans << r.take
+ ans << Ractor.current[:key]
+}
+
###
### Synchronization tests
###
diff --git a/ractor.c b/ractor.c
index fab4646c08..5937ac65bb 100644
--- a/ractor.c
+++ b/ractor.c
@@ -2928,6 +2928,13 @@ ractor_local_storage_mark_i(st_data_t key, st_data_t val, st_data_t dmy)
return ST_CONTINUE;
}
+static enum rb_id_table_iterator_result
+idkey_local_storage_mark_i(ID id, VALUE val, void *dmy)
+{
+ rb_gc_mark(val);
+ return ID_TABLE_CONTINUE;
+}
+
static void
ractor_local_storage_mark(rb_ractor_t *r)
{
@@ -2943,6 +2950,10 @@ ractor_local_storage_mark(rb_ractor_t *r)
}
}
}
+
+ if (r->idkey_local_storage) {
+ rb_id_table_foreach(r->idkey_local_storage, idkey_local_storage_mark_i, NULL);
+ }
}
static int
@@ -2960,6 +2971,10 @@ ractor_local_storage_free(rb_ractor_t *r)
st_foreach(r->local_storage, ractor_local_storage_free_i, 0);
st_free_table(r->local_storage);
}
+
+ if (r->idkey_local_storage) {
+ rb_id_table_free(r->idkey_local_storage);
+ }
}
static void
@@ -3103,4 +3118,35 @@ rb_ractor_finish_marking(void)
}
}
+static VALUE
+ractor_local_value(rb_execution_context_t *ec, VALUE self, VALUE sym)
+{
+ rb_ractor_t *cr = rb_ec_ractor_ptr(ec);
+ ID id = rb_check_id(&sym);
+ struct rb_id_table *tbl = cr->idkey_local_storage;
+ VALUE val;
+
+ if (id && tbl && rb_id_table_lookup(tbl, id, &val)) {
+ rp(val);
+ return val;
+ }
+ else {
+ return Qnil;
+ }
+}
+
+static VALUE
+ractor_local_value_set(rb_execution_context_t *ec, VALUE self, VALUE sym, VALUE val)
+{
+ rb_ractor_t *cr = rb_ec_ractor_ptr(ec);
+ ID id = SYM2ID(rb_to_symbol(sym));
+ struct rb_id_table *tbl = cr->idkey_local_storage;
+
+ if (tbl == NULL) {
+ tbl = cr->idkey_local_storage = rb_id_table_create(2);
+ }
+ rb_id_table_insert(tbl, id, val);
+ return val;
+}
+
#include "ractor.rbinc"
diff --git a/ractor.rb b/ractor.rb
index c73c574bdc..d72e02b60d 100644
--- a/ractor.rb
+++ b/ractor.rb
@@ -758,4 +758,14 @@ class Ractor
}
end
end
+
+ # get a value from ractor-local storage
+ def [](sym)
+ Primitive.ractor_local_value(sym)
+ end
+
+ # set a value in ractor-local storage
+ def []=(sym, val)
+ Primitive.ractor_local_value_set(sym, val)
+ end
end
diff --git a/ractor_core.h b/ractor_core.h
index 1f1e7aacf0..4451e06be1 100644
--- a/ractor_core.h
+++ b/ractor_core.h
@@ -130,6 +130,7 @@ struct rb_ractor_struct {
// ractor local data
st_table *local_storage;
+ struct rb_id_table *idkey_local_storage;
VALUE r_stdin;
VALUE r_stdout;