From: "byroot (Jean Boussier)" Date: 2022-11-08T21:04:13+00:00 Subject: [ruby-core:110660] [Ruby master Feature#19078] Introduce `Fiber#storage` for inheritable fiber-scoped variables. Issue #19078 has been updated by byroot (Jean Boussier). > Compare-by-identity also means using String with this new APIs would be a bug Agreed, that's what weirds me out a bit. It's quite a big downside. The upside if for objects that want to store instance state in fiber/thread local data (e.g. the `ThreadSafeLevel` example), but ultimately this is workable with the current "hack" `@key = :"#{self.class.name}_#{object_id}"`. > That means there is no need for the large complexity of copy-on-write Hash (and cost on maintenance) I think they can potentially be a performance improvement, but not to thread storage specifically. So I'd like to see them implemented, but IMO it's entirely orthogonal to this issue. > 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. I'm on the fence on this one. Usually the code spawning a thread, and the code using thread/fiber storage and needing it to be inherited are entirely decoupled. So you'd need to go convince all your dependencies that spawn threads (e.g. puma, sidekiq, etc) to add that one line of code. So I'd prefer if it was always implicitly copied. Also from my point of view `Thread.new` creates both a new thread and a new fiber, so implicitly it's akin to `Fiber.new` and should inherit. > Fiber#{storage,storage=} should only be allowed to be called on the current Fiber, and raise an exception if that's not the case. I get what you want that for truffle, but I fear this may be an hindrance to debugging and introspection. I would like to be able to run `Thread.list.map(&:storage)` to inspect the state of my process. `storage=` from another fiber is definitely a big no-no, but is there really no way `Fiber#storage` can be synchronized on Truffle, even if that means it's slower? ---------------------------------------- Feature #19078: Introduce `Fiber#storage` for inheritable fiber-scoped variables. https://bugs.ruby-lang.org/issues/19078#change-100004 * 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: