This commit is contained in:
@@ -0,0 +1,56 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
# Released under the MIT License.
|
||||
# Copyright, 2020-2024, by Samuel Williams.
|
||||
|
||||
require_relative "local/version"
|
||||
require 'fiber/storage'
|
||||
|
||||
class Fiber
|
||||
module Local
|
||||
def self.extended(klass)
|
||||
attribute_name = klass.name.gsub('::', '_').gsub(/\W/, '').downcase.to_sym
|
||||
|
||||
# This is used for the general interface and fiber storage key:
|
||||
klass.instance_variable_set(:@fiber_local_attribute_name, attribute_name)
|
||||
klass.singleton_class.attr :fiber_local_attribute_name
|
||||
|
||||
# This is used for reading and writing directly to the thread instance variables:
|
||||
klass.instance_variable_set(:@fiber_local_variable_name, :"@#{attribute_name}")
|
||||
|
||||
Thread.attr_accessor(attribute_name)
|
||||
end
|
||||
|
||||
# Instantiate a new thread-local object.
|
||||
# By default, invokes {new} to generate the instance.
|
||||
# @returns [Object]
|
||||
def local
|
||||
self.new
|
||||
end
|
||||
|
||||
# Get the current thread-local instance. Create it if required.
|
||||
# @returns [Object] The thread-local instance.
|
||||
def instance
|
||||
# This is considered a local "override" in the dynamic scope of the fiber:
|
||||
if instance = Fiber[@fiber_local_attribute_name]
|
||||
return instance
|
||||
end
|
||||
|
||||
# This is generally the fast path:
|
||||
thread = Thread.current
|
||||
unless instance = thread.instance_variable_get(@fiber_local_variable_name)
|
||||
if instance = self.local
|
||||
thread.instance_variable_set(@fiber_local_variable_name, instance)
|
||||
end
|
||||
end
|
||||
|
||||
return instance
|
||||
end
|
||||
|
||||
# Assigns to the fiber-local instance.
|
||||
# @parameter instance [Object] The object that will become the thread-local instance.
|
||||
def instance= instance
|
||||
Fiber[@fiber_local_attribute_name] = instance
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -0,0 +1,10 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
# Released under the MIT License.
|
||||
# Copyright, 2020, by Samuel Williams.
|
||||
|
||||
class Fiber
|
||||
module Local
|
||||
VERSION = "1.1.0"
|
||||
end
|
||||
end
|
||||
@@ -0,0 +1,21 @@
|
||||
# MIT License
|
||||
|
||||
Copyright, 2020-2024, by Samuel Williams.
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
@@ -0,0 +1,82 @@
|
||||
# Fiber::Local
|
||||
|
||||
A module to simplify fiber-local state.
|
||||
|
||||
[](https://github.com/socketry/fiber-local/actions?workflow=Test)
|
||||
|
||||
## Features
|
||||
|
||||
- Easily access fiber-local state from a fiber.
|
||||
- Default to shared thread-local state.
|
||||
|
||||
## Installation
|
||||
|
||||
``` bash
|
||||
$ bundle add fiber-local
|
||||
```
|
||||
|
||||
## Usage
|
||||
|
||||
In your own class, e.g. `Logger`:
|
||||
|
||||
``` ruby
|
||||
class Logger
|
||||
extend Fiber::Local
|
||||
|
||||
def initialize
|
||||
@buffer = []
|
||||
end
|
||||
|
||||
def log(*arguments)
|
||||
@buffer << arguments
|
||||
end
|
||||
end
|
||||
```
|
||||
|
||||
Now, instead of instantiating your cache `LOGGER = Logger.new`, use `Logger.instance`. It will return a thread-local instance.
|
||||
|
||||
``` ruby
|
||||
Thread.new do
|
||||
Logger.instance
|
||||
# => #<Logger:0x000055a14ec6be80>
|
||||
end
|
||||
|
||||
Thread.new do
|
||||
Logger.instance
|
||||
# => #<Logger:0x000055a14ec597d0>
|
||||
end
|
||||
```
|
||||
|
||||
In cases where you have job per fiber or request per fiber, you might want to collect all log output for a specific fiber, you can do the following:
|
||||
|
||||
``` ruby
|
||||
Logger.instance
|
||||
# => #<Logger:0x000055a14ec6be80>
|
||||
|
||||
Fiber.new do
|
||||
Logger.instance = Logger.new
|
||||
# => #<Logger:0x000055a14ec597d0>
|
||||
end
|
||||
```
|
||||
|
||||
## Contributing
|
||||
|
||||
We welcome contributions to this project.
|
||||
|
||||
1. Fork it.
|
||||
2. Create your feature branch (`git checkout -b my-new-feature`).
|
||||
3. Commit your changes (`git commit -am 'Add some feature'`).
|
||||
4. Push to the branch (`git push origin my-new-feature`).
|
||||
5. Create new Pull Request.
|
||||
|
||||
### Developer Certificate of Origin
|
||||
|
||||
This project uses the [Developer Certificate of Origin](https://developercertificate.org/). All contributors to this project must agree to this document to have their contributions accepted.
|
||||
|
||||
### Contributor Covenant
|
||||
|
||||
This project is governed by the [Contributor Covenant](https://www.contributor-covenant.org/). All contributors and participants agree to abide by its terms.
|
||||
|
||||
## See Also
|
||||
|
||||
- [thread-local](https://github.com/socketry/thread-local) — Strictly thread-local variables.
|
||||
Reference in New Issue
Block a user