Issue #13893 has been updated by cremes (Chuck Remes).


I have an alternative suggestion. Since @shyouhei says that my original suggestion is too difficult a transition path, here is an alternative.

```
      # Convenience class to be used by Thread and Fiber. Those classes
      # have an odd way of dealing with thread-local and fiber-local variables.
      # This is a storage mechanism to replace the standard mechanism.
      #
      class Local
        extend Forwardable
        
        def_delegators :@storage, :[], :[]=, :key?, :keys

        def initialize
          @storage = {}
        end
      end
      
      # Done as a module so we can easily add it to a running Thread or Fiber via #extend.
      # e.g. add this to root Thread via Thread.main.extend(LocalMixin)
      #
      module LocalMixin
        def local
          @local ||= Local.new
        end
      end
```
This adds `Thread#local` and `Fiber#local` instance methods. We can then access them very easily:

```
Thread.current.local[:key] = 'thread local value'
Fiber.current.local[:key] = 'fiber local value'
```
This has several advantages:

* Cleans up the namespace by explicitly putting all "local" variables under the #local instance method accessor
* Does NOT break any existing code; the current thread and fiber local methods will continue to work
* We could potentially modify the `Local` class to use the Thread#thread_variable_set/get methods and the Thread#[]/[]= methods internally. This way users could access their local storage via either mechanism during the transition.

I can create a pull request with specs if anyone is interested in sponsoring this change.

----------------------------------------
Feature #13893: Add Fiber#[] and Fiber#[]= and restore Thread#[] and Thread#[]= to their original behavior
https://bugs.ruby-lang.org/issues/13893#change-68092

* Author: cremes (Chuck Remes)
* Status: Open
* Priority: Normal
* Assignee: 
* Target version: 
----------------------------------------
Ruby 3 API cleanup suggestion.

The Thread and Fiber classes have a very odd API for setting/getting thread local and fiber local variables. With Ruby 3 coming soon, this is a perfect opportunity to make this API more coherent and return to the Principal of Least Surprise. The concept of Fibers and Threads should be completely separated and we should no longer assume that a Fiber is attached to any particular Thread.

I suggest this:

```
class Fiber
  # Gets a fiber-local variable.
  def [](index)
    ...
  end

  # Sets a fiber-local variable.
  def []=(index, value)
    ...
  end

  # Returns true if the given +key+ exists as a fiber-local variable.
  def key?(key)
    ...
  end

  # Returns an array of fiber-local variable names as symbols.
  def keys
    ...
  end
end

class Thread
  # Gets a thread-local variable.
  def [](index)
    ...
  end

  # Sets a thread-local variable.
  def []=(index, value)
    ...
  end

  # Returns true if the given +key+ exists as a thread-local variable.
  def key?(key)
    ...
  end

  # Returns an array of thread-local variable names as symbols.
  def keys
    ...
  end
end
```

Also, remove ```Thread#thread_variable?```, `Thread#thread_variable_get`, `Thread#variable_set`, and `Thread#thread_variables` since that behavior is already covered by `Thread#key?`, `Thread#keys`, `Thread#[]`, and `Thread#[]=`. The APIs for both Thread and Fiber are more coherent and less surprising with these changes.



-- 
https://bugs.ruby-lang.org/

Unsubscribe: <mailto:ruby-core-request / ruby-lang.org?subject=unsubscribe>
<http://lists.ruby-lang.org/cgi-bin/mailman/options/ruby-core>