Threads, Fibers and local variables
Did you know that if you store something in thread-local storage, it won't be available in child fibers?
01 Thread.current[] is fiber-local
Although the name Thread.current[] gives us a clue that it stores our data in a thread, it actually stores it in fiber-local variables.
So, if you do something like this:
Thread.current[:foo] = 1 Fiber.new do p Thread.current[:foo] end.resume # => nil
It will print nil.
02 Truly thread-local storage
If you really want to store something that is truly thread-local, you must use Thread.current.thread_variable_get and Thread.current.thread_variable_set.
03 Two separate storage APIs
To make things even more interesting, Thread.current[] and Fiber[] are not the same storage.
If you set a value using Thread.current[], it won't be available through Fiber[], and vice versa.
04 Fiber Storage inheritance
One more caveat about fibers: Fiber Storage supports inheritance of data from the parent fiber. This makes it different from Thread.current[], whose fiber-local variables are always brand new in a newly created fiber.
However, Fiber Storage inheritance is shallow. If you do something like this:
Fiber[:foo] = { a: 1, b: 2 }
Ruby copies the Fiber Storage itself, but the hash stored under :foo is not duplicated. Instead, both the parent and child fibers hold a reference to the same hash.
Mutating the hash in either the parent or the child fiber will be visible to the other.