From: "Eregon (Benoit Daloze)" Date: 2022-11-08T15:48:54+00:00 Subject: [ruby-core:110658] [Ruby master Feature#19078] Introduce `Fiber#storage` for inheritable fiber-scoped variables. Issue #19078 has been updated by Eregon (Benoit Daloze). This design looks good to me. For the keys I would prefer Symbol only, just like for fiber/thread-locals. Consistency is good there. Compare-by-identity seems acceptable too. One concern is compare-by-identity is more expensive and complicated on TruffleRuby for primitives like `int/long` which can represent the same value. Compare-by-identity also means using String with this new APIs would be a bug, which seems unfortunate, also because fiber/thread-locals accept strings. I want to represent inheritable fiber-scoped variables interally as Ruby objects using Shapes in TruffleRuby. I think CRuby should do the same. That means there is no need for the large complexity of copy-on-write Hash (and cost on maintenance), and the actual copying is faster, it's just copying an array of values and done. COW is also weird perf-wise as it penalizes the first write significantly (the first write is O(n)). Access is also faster, a Shape check + a read/write vs hash lookups which have many more indirections and work to do. Also I feel the whole API is easier to understand (e.g. mutating the Hash has no effect) if we detach the external representation (Hash) from the internal one (object with shape). Regarding threads I think we shouldn't inherit automatically in new threads, and rather do it explicitly (via `Fiber.current.storage=`) in the rare cases it's needed. `Fiber#{storage,storage=}` should only be allowed to be called on the current Fiber, and raise an exception if that's not the case. ---------------------------------------- Feature #19078: Introduce `Fiber#storage` for inheritable fiber-scoped variables. https://bugs.ruby-lang.org/issues/19078#change-100001 * Author: ioquatix (Samuel Williams) * Status: Open * Priority: Normal * Assignee: ioquatix (Samuel Williams) ---------------------------------------- Pull Request: https://github.com/ruby/ruby/pull/6612 This is an evolution of the previous ideas: - https://bugs.ruby-lang.org/issues/19058 - https://bugs.ruby-lang.org/issues/19062 This PR introduces fiber scoped variables, and is a solution for problems like . The main interface is: ```ruby Fiber[key] = value Fiber[key] # => value ``` The variables are scoped (local to) a fiber and inherited into child fibers and threads. ```ruby Fiber[:request_id] = SecureRandom.hex(16) Fiber.new do p Fiber[:request_id] # prints the above request id end ``` The fiber scoped variables are stored and can be accessed: ```ruby Fiber.current.storage # => returns a Hash (copy) of the internal storage. Fiber.current.storage= # => assigns a Hash (copy) to the internal storage. ``` Fiber itself has one new keyword argument: ``` Fiber.new(..., storage: hash, false, undef, nil) ``` This can control how the fiber variables are setup in a child context. To minimise the performance overhead of some of the implementation choices, we are also simultaneously implementing . ## Examples ### Request loop ```ruby Thread.new do while request = queue.pop Fiber.new(storage: {id: SecureRandom.hex(16)}) do handle_request.call(request) end end end ``` OR ```ruby Thread.new do while request = queue.pop Fiber.current.storage = {id: SecureRandom.hex(16)} handle_request.call(request) end end ``` -- https://bugs.ruby-lang.org/ Unsubscribe: