File: local.rb

package info (click to toggle)
ruby-fiber-local 1.1.0-1
  • links: PTS, VCS
  • area: main
  • in suites: sid
  • size: 132 kB
  • sloc: ruby: 125; makefile: 4
file content (56 lines) | stat: -rw-r--r-- 1,684 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
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