Skip to content

Commit

Permalink
Assigning nil to fiber storage deletes the association.
Browse files Browse the repository at this point in the history
- Reduce memory allocations when looking up `Fiber#storage`.
  • Loading branch information
ioquatix committed Feb 25, 2023
1 parent 132934b commit 3d46d6b
Show file tree
Hide file tree
Showing 2 changed files with 37 additions and 13 deletions.
31 changes: 24 additions & 7 deletions cont.c
Expand Up @@ -2059,16 +2059,22 @@ fiber_storage_set(struct rb_fiber_struct *fiber, VALUE storage)
}

static inline VALUE
fiber_storage_get(rb_fiber_t *fiber)
fiber_storage_get(rb_fiber_t *fiber, int allocate)
{
VALUE storage = fiber->cont.saved_ec.storage;
if (storage == Qnil) {
if (storage == Qnil && allocate) {
storage = rb_hash_new();
fiber_storage_set(fiber, storage);
}
return storage;
}

static inline int
fiber_storage_p(rb_fiber_t *fiber)
{
return fiber->cont.saved_ec.storage != Qnil;
}

static void
storage_access_must_be_from_same_fiber(VALUE self)
{
Expand All @@ -2089,7 +2095,14 @@ static VALUE
rb_fiber_storage_get(VALUE self)
{
storage_access_must_be_from_same_fiber(self);
return rb_obj_dup(fiber_storage_get(fiber_ptr(self)));

VALUE storage = fiber_storage_get(fiber_ptr(self), FALSE);

if (storage == Qnil) {
return Qnil;
} else {
return rb_obj_dup(storage);
}
}

static int
Expand Down Expand Up @@ -2170,8 +2183,7 @@ rb_fiber_storage_aref(VALUE class, VALUE key)
ID id = rb_check_id(&key);
if (!id) return Qnil;

VALUE storage = fiber_storage_get(fiber_current());

VALUE storage = fiber_storage_get(fiber_current(), FALSE);
if (storage == Qnil) return Qnil;

return rb_hash_aref(storage, key);
Expand All @@ -2193,9 +2205,14 @@ rb_fiber_storage_aset(VALUE class, VALUE key, VALUE value)
ID id = rb_check_id(&key);
if (!id) return Qnil;

VALUE storage = fiber_storage_get(fiber_current());
VALUE storage = fiber_storage_get(fiber_current(), value != Qnil);
if (storage == Qnil) return Qnil;

return rb_hash_aset(storage, key, value);
if (value == Qnil) {
return rb_hash_delete(storage, key);
} else {
return rb_hash_aset(storage, key, value);
}
}

static VALUE
Expand Down
19 changes: 13 additions & 6 deletions spec/ruby/core/fiber/storage_spec.rb
Expand Up @@ -11,7 +11,7 @@
end

it "creates a fiber with lazily initialized storage" do
Fiber.new(storage: nil) { Fiber.current.storage }.resume.should == {}
Fiber.new(storage: nil) { Fiber[:x] = 10; Fiber.current.storage }.resume.should == {x: 10}
end

it "creates a fiber by inheriting the storage of the parent fiber" do
Expand All @@ -30,18 +30,19 @@
describe "Fiber#storage=" do
ruby_version_is "3.2" do
it "can clear the storage of the fiber" do
fiber = Fiber.new(storage: {life: 42}) {
fiber = Fiber.new(storage: {life: 42}) do
Fiber.current.storage = nil
Fiber[:x] = 10
Fiber.current.storage
}
fiber.resume.should == {}
end
fiber.resume.should == {x: 10}
end

it "can set the storage of the fiber" do
fiber = Fiber.new(storage: {life: 42}) {
fiber = Fiber.new(storage: {life: 42}) do
Fiber.current.storage = {life: 43}
Fiber.current.storage
}
end
fiber.resume.should == {life: 43}
end

Expand Down Expand Up @@ -89,6 +90,12 @@
Fiber.new { Fiber[:life] = 43; Fiber[:life] }.resume.should == 43
end
end

ruby_version_is "3.3" do
it "deletes the fiber storage key when assigning nil" do
Fiber.new(storage: {life: 42}) { Fiber[:life] = nil; Fiber.current.storage }.resume.should == {}
end
end
end

describe "Thread.new" do
Expand Down

0 comments on commit 3d46d6b

Please sign in to comment.