Skip to content

Commit

Permalink
add Ractor#[]/#[]= for ractor local storage
Browse files Browse the repository at this point in the history
This API is similar to plain old Thread#[]/Fiber#[] interface
with symbol key.
  • Loading branch information
ko1 committed Dec 21, 2020
1 parent 8f2031a commit 35471a9
Show file tree
Hide file tree
Showing 4 changed files with 71 additions and 0 deletions.
14 changes: 14 additions & 0 deletions bootstraptest/test_ractor.rb
Expand Up @@ -1245,6 +1245,20 @@ class C
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
###
Expand Down
46 changes: 46 additions & 0 deletions ractor.c
Expand Up @@ -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)
{
Expand All @@ -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
Expand All @@ -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
Expand Down Expand Up @@ -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"
10 changes: 10 additions & 0 deletions ractor.rb
Expand Up @@ -758,4 +758,14 @@ def self.make_shareable obj, copy: false
}
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
1 change: 1 addition & 0 deletions ractor_core.h
Expand Up @@ -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;
Expand Down

0 comments on commit 35471a9

Please sign in to comment.