Skip to content

Commit

Permalink
Ractor.local_storage_init
Browse files Browse the repository at this point in the history
to initialize Ractor local storage slot atomically.
[Feature #20875]
  • Loading branch information
ko1 committed Nov 8, 2024
1 parent 8586838 commit b54792a
Show file tree
Hide file tree
Showing 4 changed files with 70 additions and 0 deletions.
15 changes: 15 additions & 0 deletions bootstraptest/test_ractor.rb
Original file line number Diff line number Diff line change
Expand Up @@ -1513,6 +1513,21 @@ class C
ans << Ractor.current[:key]
}

assert_equal '1', %q{
N = 1_000
Ractor.new{
a = []
1_000.times.map{|i|
Thread.new(i){|i|
Thread.pass if i < N
a << Ractor.local_storage_init(:i){ i }
a << Ractor.current[:i]
}
}.each(&:join)
a.uniq.size
}.take
}

###
### Synchronization tests
###
Expand Down
50 changes: 50 additions & 0 deletions ractor.c
Original file line number Diff line number Diff line change
Expand Up @@ -3869,4 +3869,54 @@ ractor_local_value_set(rb_execution_context_t *ec, VALUE self, VALUE sym, VALUE
return val;
}

struct ractor_local_value_init_data {
rb_execution_context_t *ec;
struct rb_id_table *tbl;
ID id;
VALUE sym;
};

static VALUE
ractor_local_value_init_i(VALUE ptr)
{
VALUE val;
struct ractor_local_value_init_data *data = (struct ractor_local_value_init_data *)ptr;

if (rb_id_table_lookup(data->tbl, data->id, &val)) {
// after synchronization, we found already registerred entry
}
else {
val = rb_yield(Qnil);
ractor_local_value_set(data->ec, Qnil, data->sym, val);
}
return val;
}

static VALUE
ractor_local_storage_init(rb_execution_context_t *ec, VALUE self, VALUE sym)
{
rb_ractor_t *cr = rb_ec_ractor_ptr(ec);
struct ractor_local_value_init_data data = {
.ec = ec,
.sym = sym,
.id = SYM2ID(rb_to_symbol(sym)),
.tbl = cr->idkey_local_storage,
};
VALUE val;

if (data.tbl == NULL) {
data.tbl = cr->idkey_local_storage = rb_id_table_create(2);
}
else if (rb_id_table_lookup(data.tbl, data.id, &val)) {
// already set
return val;
}

if (!cr->idkey_init_lock) {
cr->idkey_init_lock = rb_mutex_new();
}

return rb_mutex_synchronize(cr->idkey_init_lock, ractor_local_value_init_i, (VALUE)&data);
}

#include "ractor.rbinc"
4 changes: 4 additions & 0 deletions ractor.rb
Original file line number Diff line number Diff line change
Expand Up @@ -834,6 +834,10 @@ def self.make_shareable obj, copy: false
end
end

def self.local_storage_init(sym)
Primitive.ractor_local_storage_init(sym)
end

# get a value from ractor-local storage
def [](sym)
Primitive.ractor_local_value(sym)
Expand Down
1 change: 1 addition & 0 deletions ractor_core.h
Original file line number Diff line number Diff line change
Expand Up @@ -180,6 +180,7 @@ struct rb_ractor_struct {

st_table *local_storage;
struct rb_id_table *idkey_local_storage;
VALUE idkey_init_lock;

VALUE r_stdin;
VALUE r_stdout;
Expand Down

0 comments on commit b54792a

Please sign in to comment.