thread_local_var_accessors 0.1.1

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: 1b6e9d88de11a15e80e03d531bbb506da4b962e057ee1e88f0eb56f79c0eca74
4
+ data.tar.gz: 919b3b1100b7d8683317869cda3dbd87672ba6e30a0a86c565fffd0cefadcc99
5
+ SHA512:
6
+ metadata.gz: 2c1c294e53542491de381e69ff49b9b68942f6d5dc06ef8256f954dbec8af9c23396a4fd995d10701017b790c51880c6928c451c4e521c0b7cef80233af50aba
7
+ data.tar.gz: 740127f6247210b11f2ad478005eb459780afa6f50e451416b74a6ac35081d1ab818151b85bab786dd60031f71ee67cc01fc7b45423c454976f66834e000d0e0
data/Gemfile ADDED
@@ -0,0 +1,3 @@
1
+ source 'https://rubygems.org'
2
+
3
+ gemspec
data/Gemfile.lock ADDED
@@ -0,0 +1,90 @@
1
+ PATH
2
+ remote: .
3
+ specs:
4
+ thread_local_var_accessors (0.1.1)
5
+ concurrent-ruby
6
+
7
+ GEM
8
+ remote: https://rubygems.org/
9
+ specs:
10
+ ast (2.4.2)
11
+ builder (3.2.4)
12
+ concurrent-ruby (1.2.2)
13
+ diff-lcs (1.5.0)
14
+ docile (1.4.0)
15
+ fuubar (2.5.1)
16
+ rspec-core (~> 3.0)
17
+ ruby-progressbar (~> 1.4)
18
+ json (2.6.3)
19
+ parallel (1.22.1)
20
+ parser (3.2.1.1)
21
+ ast (~> 2.4.1)
22
+ rainbow (3.1.1)
23
+ rake (13.0.6)
24
+ redcarpet (3.6.0)
25
+ regexp_parser (2.7.0)
26
+ rexml (3.2.5)
27
+ rspec (3.12.0)
28
+ rspec-core (~> 3.12.0)
29
+ rspec-expectations (~> 3.12.0)
30
+ rspec-mocks (~> 3.12.0)
31
+ rspec-core (3.12.1)
32
+ rspec-support (~> 3.12.0)
33
+ rspec-expectations (3.12.2)
34
+ diff-lcs (>= 1.2.0, < 2.0)
35
+ rspec-support (~> 3.12.0)
36
+ rspec-mocks (3.12.4)
37
+ diff-lcs (>= 1.2.0, < 2.0)
38
+ rspec-support (~> 3.12.0)
39
+ rspec-support (3.12.0)
40
+ rspec_junit (4.0.4)
41
+ builder (>= 3.2.2)
42
+ rspec (>= 3.3.0)
43
+ rspec_junit_formatter (0.6.0)
44
+ rspec-core (>= 2, < 4, != 2.12.0)
45
+ rubocop (1.48.1)
46
+ json (~> 2.3)
47
+ parallel (~> 1.10)
48
+ parser (>= 3.2.0.0)
49
+ rainbow (>= 2.2.2, < 4.0)
50
+ regexp_parser (>= 1.8, < 3.0)
51
+ rexml (>= 3.2.5, < 4.0)
52
+ rubocop-ast (>= 1.26.0, < 2.0)
53
+ ruby-progressbar (~> 1.7)
54
+ unicode-display_width (>= 2.4.0, < 3.0)
55
+ rubocop-ast (1.28.0)
56
+ parser (>= 3.2.1.0)
57
+ ruby-progressbar (1.13.0)
58
+ simplecov (0.22.0)
59
+ docile (~> 1.1)
60
+ simplecov-html (~> 0.11)
61
+ simplecov_json_formatter (~> 0.1)
62
+ simplecov-html (0.12.3)
63
+ simplecov_json_formatter (0.1.4)
64
+ spring (4.1.1)
65
+ terminal-notifier-guard (1.7.0)
66
+ unicode-display_width (2.4.2)
67
+ webrick (1.7.0)
68
+ yard (0.9.28)
69
+ webrick (~> 1.7.0)
70
+
71
+ PLATFORMS
72
+ x86_64-darwin-21
73
+
74
+ DEPENDENCIES
75
+ bundler
76
+ fuubar
77
+ rake
78
+ redcarpet
79
+ rspec
80
+ rspec_junit
81
+ rspec_junit_formatter
82
+ rubocop
83
+ simplecov
84
+ spring
85
+ terminal-notifier-guard
86
+ thread_local_var_accessors!
87
+ yard
88
+
89
+ BUNDLED WITH
90
+ 2.4.6
data/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2023 Alan Stebbens
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
data/LICENSE.md ADDED
@@ -0,0 +1,21 @@
1
+ # MIT LICENSE
2
+
3
+ Copyright (c) 2023 Alan Stebbens <aks@stebbens.org>
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in
13
+ all copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21
+ THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,211 @@
1
+ # thread_local_var_accessors
2
+
3
+ Ruby gem to make `ThreadLocalVars` easy to use, with either "accessor" methods,
4
+ or instance methods.
5
+
6
+ Build Status: [![CircleCI](https://dl.circleci.com/status-badge/img/gh/aks/thread_local_var_accessors/tree/main.svg?style=svg)](https://dl.circleci.com/status-badge/redirect/gh/aks/thread_local_var_accessors/tree/main)
7
+
8
+ ## Description
9
+
10
+ This module has methods making it easy to use the `Concurrent::ThreadLocalVar`
11
+ as instance variables. This makes instance variables using this code as
12
+ actually thread-local, without also leaking memory over time.
13
+
14
+ See [Why Concurrent::ThreadLocalVar](https://github.com/ruby-concurrency/concurrent-ruby/blob/master/lib/concurrent-ruby/concurrent/atomic/thread_local_var.rb#L10-L17) to understand why we use TLVs instead of `Thread.current.thread_variable_(set|get)`
15
+
16
+ ### Class Methods
17
+
18
+ Just as Rails provides _attribute_ accessor methods, eg: `attr_accessor`,
19
+ `attr_reader`, and `attr_writer`, this module provides the following
20
+ class methods for declaring getter and setter methods based on instance
21
+ variables that use `ThreadLocalVar` (TLV) objects.
22
+
23
+ tlv_reader :var1, :var2, ...
24
+ tlv_writer :var3, :var4, ...
25
+ tlv_accessor :var5, :var6, ...
26
+
27
+ - `tlv_reader` creates an instance method with the name `name`, that references
28
+ the instance variable names '@name', which is expected to be either nil,
29
+ or already have a `Concurrent::ThreadLocalVar` instance.
30
+
31
+ - `tlv_writer` creates an instance method with the name `name=`, which accepts a single
32
+ argument that is the new value. This method checks for an existing value
33
+ on the instance variable named `@name`, which should be a
34
+ `Concurrent::ThreadLocalVar` instance. If `@name` value is nil, then a new
35
+ `Concurrent::ThreadLocalVar` instance is assigned to it. In either case, the
36
+ instance variable's TLV object is assigned the new value, which is returned.
37
+
38
+ - `tlv_accessor` - creates both a `tlv_reader` and a `tlv_writer`.
39
+
40
+ For reference, see [ThreadLocalVars](https://ruby-concurrency.github.io/concurrent-ruby/master/Concurrent/ThreadLocalVar.html).
41
+
42
+ ### Instance Methods
43
+
44
+ With the accessor methods, obtaining values and setting values
45
+ becomes very simple:
46
+
47
+ tlv_accessor :timeout
48
+ ...
49
+ timeout # fetches the current TLV value, unique to each thread
50
+ ...
51
+ self.timeout = 0.5 # stores the TLV value just for this thread
52
+
53
+ Alternative ways to initialize:
54
+
55
+ tlv_set(:timeout, 0)
56
+
57
+ tlv_set(:timeout) # ensure that @timeout is initialized to an [TLV](TLV)
58
+ @timeout.value = 0
59
+
60
+ The following methods are used within the above reader, writer, accessor
61
+ methods:
62
+
63
+ tlv_get(name) - fetches the value of TLV `name`
64
+ tlv_set(name, value) - stores the value into the TLV `name`
65
+
66
+ There is a block form to `tls_set`:
67
+
68
+ tlv_set(name) { |old_val| new_val }
69
+
70
+ In addition, there is also a `tlv_set_once` method that can be used to set
71
+ a TLV value only if has not currently be set already.
72
+
73
+ tlv_set_once(name, value)
74
+
75
+ tlv_set_once(name) { |old_val| new_value }
76
+
77
+ For `tlv_accessor` instance variables, it's possible to use the assign operators, eg: `+=`, or `||=`.
78
+ For example:
79
+
80
+ tlv_accessor :timeout, :count
81
+
82
+ self.timeout ||= DEFAULT_TIMEOUT
83
+
84
+ self.count += 1
85
+
86
+ ### TLV Name Arguments
87
+
88
+ The `name` argument to `tlv_get` and `tlv_set` is the same as given on
89
+ the accessor, reader, and writer methods: either a string or symbol name,
90
+ automatically converted as needed to instance-variable syntax (eg: :@name),
91
+ and setter-method name syntax (eg :name=).
92
+
93
+
94
+ ## Installation
95
+
96
+ gem install thread_local_var_accessors
97
+
98
+ Within another app, within its `Gemfile` or `*.gemspec` file:
99
+
100
+ gem 'thread_local_var_accessors'
101
+
102
+ Then:
103
+
104
+ bundle install
105
+
106
+ ## Usage
107
+
108
+ Use the class methods to declare instance getter and setter methods:
109
+
110
+ tlv_reader :name1
111
+ tlv_writer :name2
112
+ tlv_accessor :name3, :name4
113
+
114
+ The above invocations:
115
+ - create reader methods for `name1`, `name3`, and `name4`.
116
+ - create writer methods for `name2`, `name3`, and `name4`.
117
+
118
+ The writer methods accept a value as the second argument, or from the result of an associated block.
119
+
120
+ Note: to use the read-and-operate operators, eg: `+=`, `-=`, `||=`, etc., the object must have both a reader and writer method. In other words, it needs to have been created as an `tlv_accessor`.
121
+
122
+ When adapting legacy code to become thread-safe, it's sometimes necessary to use the underlying instance methods:
123
+
124
+ tlv_get(name)
125
+ tlv_set(name, value)
126
+ tlv_set_once(name, value)
127
+
128
+ Alternative block forms:
129
+
130
+ tlv_set(name) { |oldval| newval }
131
+ tlv_set_once(name) { |oldval| newval }
132
+
133
+
134
+ In all cases, the `name` can be a string or symbol, with or without a leading `@`.
135
+
136
+ ### Example Usage
137
+
138
+ ```ruby
139
+ require 'thread_local_var_accessors'
140
+
141
+ class MyClass
142
+ include ThreadLocalVarAccessors
143
+
144
+ tlv_accessor :timeout, :max_time, :count, :limit
145
+ tlv_reader :sleep_time
146
+ tlv_writer :locked
147
+
148
+ def initialize(**args)
149
+ self.limit = args[:limit]
150
+ self.timeout = args[:timeout]
151
+ self.max_time = args[:max_time]
152
+ self.sleep_time = args[:sleep_time]
153
+ end
154
+
155
+ def run
156
+ while count < limit && delay_time < timeout
157
+ ...
158
+ self.max_time ||= DEFAULT_MAX_TIME
159
+ ...
160
+ sleep sleep_time
161
+ ...
162
+ self.locked = true
163
+ end
164
+ end
165
+ end
166
+ ```
167
+
168
+ There may be times where you may want to use the `tlv_`-prefix methods and not use the accessors.
169
+
170
+ The following are a set of equivalencies.
171
+
172
+ ```ruby
173
+ tlv_accessor :timeout
174
+ ```
175
+
176
+ produces both the reader and writer methods, using the `tlv_get` and `tlv_set` methods.
177
+
178
+ ```ruby
179
+ def timeout
180
+ tlv_get(:timeout)
181
+ end
182
+
183
+ def timeout=(val)
184
+ tlv_set(:timeout, val)
185
+ end
186
+ ```
187
+
188
+ The advantage of the block method, especially for `tlv_set_once`, is that the
189
+ VALUE is only evaluated when the instance variable value is being set, and, the block will receive the old value as a parameter.
190
+
191
+ ## Development
192
+
193
+ After checking out the repo, run `bin/setup` to install dependencies. Then, run `rake spec` to run the tests. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
194
+
195
+ For both development and testing, the environment variables described above must be defined.
196
+
197
+ ## Testing
198
+
199
+ ## Continuous Integration and Deployments
200
+
201
+ This repo is configured to the [gitflow](https://datasift.github.io/gitflow/IntroducingGitFlow.html) pattern, with the `develop` branch being the _default_ branch on PRs.
202
+
203
+ The `main` branch gets updated with a PR or with a manual merge-and-push from the `develop` branch by a repo admin.
204
+
205
+ When any branch is pushed, the continuous integration with causes the branch to be tested with all of the `rspec` tests _(except the integration tests)_.
206
+
207
+ When the `main` branch is updated and after its tests pass, the `deploy` action is invoked which causes the newest build of the gem to be pushed to rubygems.org.
208
+
209
+ ## Original Author:
210
+
211
+ Alan K. Stebbens <aks@stebbens.org>
data/Rakefile ADDED
@@ -0,0 +1,38 @@
1
+ # Rakefile for thread_local_var_accessors
2
+ require "bundler/gem_tasks"
3
+ require "rspec/core/rake_task"
4
+ require 'yard'
5
+
6
+ # Local CI testing
7
+
8
+ namespace :ci do
9
+ desc "Check CIRCLECI config"
10
+ task :check do
11
+ sh "circleci config validate", verbose: true
12
+ end
13
+
14
+ desc "Run CIRCLECI config locally"
15
+ task :local do
16
+ sh "circleci local execute", verbose: true
17
+ end
18
+ end
19
+
20
+ # add spec unit tests
21
+
22
+ RSpec::Core::RakeTask.new(:spec)
23
+
24
+ namespace :spec do
25
+ desc "run Simplecov"
26
+ task :coverage do
27
+ sh 'CODE_COVERAGE=1 bundle exec rake spec'
28
+ end
29
+ end
30
+
31
+ # add yard task
32
+
33
+ YARD::Rake::YardocTask.new do |t|
34
+ t.files = ['README.md', 'lib/**/*.rb']
35
+ t.stats_options = ['--list-undoc']
36
+ end
37
+
38
+ task default: :spec
@@ -0,0 +1,3 @@
1
+ module ThreadLocalVarAccessors
2
+ VERSION = '0.1.1'
3
+ end
@@ -0,0 +1,188 @@
1
+ # frozen_string_literal: true
2
+
3
+ # This module has methods making it easy to use the Concurrent::ThreadLocalVar
4
+ # as instance variables. This makes instance variables using this code as
5
+ # actually thread-local, without also leaking memory over time.
6
+ #
7
+ # See [Why Concurrent::ThreadLocalVar](https://github.com/ruby-concurrency/concurrent-ruby/blob/master/lib/concurrent-ruby/concurrent/atomic/thread_local_var.rb#L10-L17)
8
+ # to understand why we use TLVs instead of `Thread.current.thread_variable_(set|get)`
9
+ #
10
+ # The following class methods declare `Concurrent::ThreadLocalVar` reader,
11
+ # writer, and accessors with these class methods:
12
+ #
13
+ # tlv_reader :var1, :var2, ...
14
+ # tlv_writer :var3, :var4, ...
15
+ # tlv_accessor :var5, :var6, ...
16
+ #
17
+ # - `tlv_reader` creates a method with the name `name`, that references
18
+ # the instance variable names '@name', which is expected to be either nil,
19
+ # or already have a `Concurrent::ThreadLocalVar` instance.
20
+ #
21
+ # - `tlv_writer` creates a method with the name `name=`, which accepts a single
22
+ # argument that is the new value. This method checks for an existing value
23
+ # on the instance variable named "@name", which should be a
24
+ # `Concurrent::ThreadLocalVar` instance. If `@name` value is nil, then a new
25
+ # `Concurrent::ThreadLocalVar` instance is assigned to it. In either case, the
26
+ # instance variable's TLV object is assigned the new value, which is returned.
27
+ #
28
+ # - `tlv_accessor` - creates both a `tlv_reader` and a `tlv_writer`.
29
+ #
30
+ # Just as with `attr_accessor` methods, obtaining values and setting values
31
+ # becomes very simple:
32
+ #
33
+ # tlv_accessor :timeout
34
+ # ...
35
+ # timeout # fetches the current TLV value, unique to each thread
36
+ # ...
37
+ # self.timeout = 0.5 # stores the TLV value just for this thread
38
+ #
39
+ # Alternative ways to initialize:
40
+ #
41
+ # ltv_set(:timeout, 0)
42
+ #
43
+ # ltv_set(:timeout) # ensure that @timeout is initialized to an LTV
44
+ # @timeout.value = 0
45
+ #
46
+ # The following methods are used within the above reader, writer, accessor
47
+ # methods:
48
+ #
49
+ # tlv_get(name) - fetches the value of TLV `name`
50
+ # tlv_set(name, value) - stores the value into the TLV `name`
51
+ #
52
+ # There is a block form to `tls_set`:
53
+ #
54
+ # tlv_set(name) { |old_val| new_val }
55
+ #
56
+ # The `name` argument to `tlv_get` and `tlv_set` is the same as given on
57
+ # the accessor, reader, writer methods: either a string or symbol name,
58
+ # automatically converted as needed to instance-variable syntax (eg: :@name),
59
+ # and setter-method name syntax (eg :name=).
60
+ #
61
+ # Example:
62
+ #
63
+ # tlv_accessor :timeout
64
+ #
65
+ # Creates reader and writer methods called "timeout", and "timeout=",
66
+ # respectively. Both of these methods interrogate the instance variable
67
+ # "@timeout", which is initialized (by `tlv_set`) to contain a
68
+ # `Concurrent::ThreadLocalVar.new` value.
69
+ #
70
+ # The writer methods support using attached blocks to receive the current
71
+ # value, if any, and should return the value to be stored.
72
+ #
73
+ # The `timeout` reader method would look like this:
74
+ #
75
+ # def timeout
76
+ # instance_variable_get(:@timeout)&.value
77
+ # end
78
+ #
79
+ # The 'timeout=' writer method would look like this:
80
+ #
81
+ # def timeout=(value)
82
+ # var = instance_variable_get(:@timeout) ||
83
+ # instance_variable_get(:@timeout, Concurrent::ThreadLocalVar.new)
84
+ # var.value = block_given? ? yield(var.value) : value
85
+ # end
86
+ #
87
+ # Each thread referencing the instance variable, will get the same TLV object,
88
+ # but when the `.value` method is invoked, each thread will receive the initial
89
+ # value, or whatever local value may have been assigned subsequently.
90
+ #
91
+ # To obtain the value of such an TLV instance variable, do:
92
+ #
93
+ # @timeout.value
94
+ #
95
+ # To assign a new value to an TLV instance:
96
+ #
97
+ # @timeout.value = new_value
98
+
99
+ require 'concurrent-ruby'
100
+
101
+ # methods for making usage of ThreadLocalVars easy
102
+ module ThreadLocalVarAccessors
103
+ # @!visibility private
104
+ module MyRefinements
105
+ # allow to_sym to be called on either a String or a Symbol
106
+ refine Symbol do
107
+ # idempotent method: :symbol.to_sym => :symbol
108
+ def to_sym
109
+ self
110
+ end
111
+
112
+ # @return [Symbol] an instance variable; eg: :name => :@name.
113
+ # idempotent: returns instance variable names unchanged
114
+ def to_ivar
115
+ to_s.to_ivar
116
+ end
117
+ end
118
+
119
+ refine String do
120
+ # @return [Symbol] an instance variable; eg: "name" => :@name.
121
+ # idempotent: returns instance variable names unchanged
122
+ def to_ivar
123
+ (start_with?('@') ? self : "@#{self}").to_sym
124
+ end
125
+ end
126
+ end
127
+ using MyRefinements
128
+
129
+ module ClassMethods
130
+ def tlv_reader(*names)
131
+ names.each do |name|
132
+ define_method(name.to_sym) { tlv_get(name) }
133
+ end
134
+ end
135
+
136
+ # like attr_writer, but supports using block-values, which receive the
137
+ # current value, returning the new value
138
+ def tlv_writer(*names)
139
+ names.each do |name|
140
+ define_method("#{name}=".to_sym) do |new_value, &block|
141
+ tlv_set(name, new_value, &block)
142
+ end
143
+ end
144
+ end
145
+
146
+ def tlv_accessor(*names)
147
+ tlv_reader(*names)
148
+ tlv_writer(*names)
149
+ end
150
+ end
151
+
152
+ # instance methods
153
+ def tlv_get(name)
154
+ instance_variable_get(name.to_ivar)&.value
155
+ end
156
+
157
+ def tlv_set(name, value = nil, &block)
158
+ var = instance_variable_get(name.to_ivar) || tlv_new(name)
159
+ tlv_set_var(var, value, &block)
160
+ end
161
+
162
+ def tlv_set_once(name, value = nil, &block)
163
+ if (var = instance_variable_get(name.to_ivar)) && !var.value.nil?
164
+ var.value
165
+ elsif var # var is set, but its value is nil
166
+ tlv_set_var(var, value, &block)
167
+ else # var is not set
168
+ tlv_set_var(tlv_new(name), value, &block)
169
+ end
170
+ end
171
+
172
+ # @param [String|Symbol] name the TLV name
173
+ # @return [ThreadLocalVar] a new TLV set in the instance variable
174
+ def tlv_new(name)
175
+ instance_variable_set(name.to_ivar, Concurrent::ThreadLocalVar.new)
176
+ end
177
+
178
+ # @!visibility private
179
+ def self.included(base)
180
+ base.extend(ClassMethods)
181
+ end
182
+
183
+ private
184
+
185
+ def tlv_set_var(var, value)
186
+ var.value = block_given? ? yield(var.value) : value
187
+ end
188
+ end
@@ -0,0 +1,34 @@
1
+ # encoding: utf-8
2
+
3
+ $:.unshift File.expand_path('../lib', __FILE__)
4
+ require 'thread_local_var_accessors/version'
5
+
6
+ Gem::Specification.new do |s|
7
+ s.name = 'thread_local_var_accessors'
8
+ s.version = ThreadLocalVarAccessors::VERSION
9
+ s.authors = ['Alan Stebbens']
10
+ s.email = ['aks@stebbens.org']
11
+ s.homepage = 'https://github.com/aks/thread_local_var_accessors'
12
+ s.licenses = ['MIT']
13
+ s.summary = 'Ruby gem to make ThreadLocalVars easy to use'
14
+ s.description = 'Provides methods to declare and use ThreadLocalVar instance variables'
15
+
16
+ s.files = Dir.glob('{bin/*,lib/**/*,[A-Z]*}')
17
+ s.platform = Gem::Platform::RUBY
18
+ s.require_paths = ['lib']
19
+
20
+ s.add_development_dependency 'bundler'
21
+ s.add_development_dependency 'fuubar'
22
+ s.add_development_dependency 'rake'
23
+ s.add_development_dependency 'redcarpet'
24
+ s.add_development_dependency 'rspec'
25
+ s.add_development_dependency 'rspec_junit'
26
+ s.add_development_dependency 'rspec_junit_formatter'
27
+ s.add_development_dependency 'rubocop'
28
+ s.add_development_dependency 'simplecov'
29
+ s.add_development_dependency 'spring'
30
+ s.add_development_dependency 'terminal-notifier-guard' if /Darwin/.match?(`uname -a`.strip)
31
+ s.add_development_dependency 'yard'
32
+
33
+ s.add_runtime_dependency 'concurrent-ruby'
34
+ end
metadata ADDED
@@ -0,0 +1,234 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: thread_local_var_accessors
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.1
5
+ platform: ruby
6
+ authors:
7
+ - Alan Stebbens
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2023-03-28 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: bundler
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ">="
18
+ - !ruby/object:Gem::Version
19
+ version: '0'
20
+ type: :development
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - ">="
25
+ - !ruby/object:Gem::Version
26
+ version: '0'
27
+ - !ruby/object:Gem::Dependency
28
+ name: fuubar
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ">="
32
+ - !ruby/object:Gem::Version
33
+ version: '0'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - ">="
39
+ - !ruby/object:Gem::Version
40
+ version: '0'
41
+ - !ruby/object:Gem::Dependency
42
+ name: rake
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - ">="
46
+ - !ruby/object:Gem::Version
47
+ version: '0'
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - ">="
53
+ - !ruby/object:Gem::Version
54
+ version: '0'
55
+ - !ruby/object:Gem::Dependency
56
+ name: redcarpet
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - ">="
60
+ - !ruby/object:Gem::Version
61
+ version: '0'
62
+ type: :development
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - ">="
67
+ - !ruby/object:Gem::Version
68
+ version: '0'
69
+ - !ruby/object:Gem::Dependency
70
+ name: rspec
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - ">="
74
+ - !ruby/object:Gem::Version
75
+ version: '0'
76
+ type: :development
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - ">="
81
+ - !ruby/object:Gem::Version
82
+ version: '0'
83
+ - !ruby/object:Gem::Dependency
84
+ name: rspec_junit
85
+ requirement: !ruby/object:Gem::Requirement
86
+ requirements:
87
+ - - ">="
88
+ - !ruby/object:Gem::Version
89
+ version: '0'
90
+ type: :development
91
+ prerelease: false
92
+ version_requirements: !ruby/object:Gem::Requirement
93
+ requirements:
94
+ - - ">="
95
+ - !ruby/object:Gem::Version
96
+ version: '0'
97
+ - !ruby/object:Gem::Dependency
98
+ name: rspec_junit_formatter
99
+ requirement: !ruby/object:Gem::Requirement
100
+ requirements:
101
+ - - ">="
102
+ - !ruby/object:Gem::Version
103
+ version: '0'
104
+ type: :development
105
+ prerelease: false
106
+ version_requirements: !ruby/object:Gem::Requirement
107
+ requirements:
108
+ - - ">="
109
+ - !ruby/object:Gem::Version
110
+ version: '0'
111
+ - !ruby/object:Gem::Dependency
112
+ name: rubocop
113
+ requirement: !ruby/object:Gem::Requirement
114
+ requirements:
115
+ - - ">="
116
+ - !ruby/object:Gem::Version
117
+ version: '0'
118
+ type: :development
119
+ prerelease: false
120
+ version_requirements: !ruby/object:Gem::Requirement
121
+ requirements:
122
+ - - ">="
123
+ - !ruby/object:Gem::Version
124
+ version: '0'
125
+ - !ruby/object:Gem::Dependency
126
+ name: simplecov
127
+ requirement: !ruby/object:Gem::Requirement
128
+ requirements:
129
+ - - ">="
130
+ - !ruby/object:Gem::Version
131
+ version: '0'
132
+ type: :development
133
+ prerelease: false
134
+ version_requirements: !ruby/object:Gem::Requirement
135
+ requirements:
136
+ - - ">="
137
+ - !ruby/object:Gem::Version
138
+ version: '0'
139
+ - !ruby/object:Gem::Dependency
140
+ name: spring
141
+ requirement: !ruby/object:Gem::Requirement
142
+ requirements:
143
+ - - ">="
144
+ - !ruby/object:Gem::Version
145
+ version: '0'
146
+ type: :development
147
+ prerelease: false
148
+ version_requirements: !ruby/object:Gem::Requirement
149
+ requirements:
150
+ - - ">="
151
+ - !ruby/object:Gem::Version
152
+ version: '0'
153
+ - !ruby/object:Gem::Dependency
154
+ name: terminal-notifier-guard
155
+ requirement: !ruby/object:Gem::Requirement
156
+ requirements:
157
+ - - ">="
158
+ - !ruby/object:Gem::Version
159
+ version: '0'
160
+ type: :development
161
+ prerelease: false
162
+ version_requirements: !ruby/object:Gem::Requirement
163
+ requirements:
164
+ - - ">="
165
+ - !ruby/object:Gem::Version
166
+ version: '0'
167
+ - !ruby/object:Gem::Dependency
168
+ name: yard
169
+ requirement: !ruby/object:Gem::Requirement
170
+ requirements:
171
+ - - ">="
172
+ - !ruby/object:Gem::Version
173
+ version: '0'
174
+ type: :development
175
+ prerelease: false
176
+ version_requirements: !ruby/object:Gem::Requirement
177
+ requirements:
178
+ - - ">="
179
+ - !ruby/object:Gem::Version
180
+ version: '0'
181
+ - !ruby/object:Gem::Dependency
182
+ name: concurrent-ruby
183
+ requirement: !ruby/object:Gem::Requirement
184
+ requirements:
185
+ - - ">="
186
+ - !ruby/object:Gem::Version
187
+ version: '0'
188
+ type: :runtime
189
+ prerelease: false
190
+ version_requirements: !ruby/object:Gem::Requirement
191
+ requirements:
192
+ - - ">="
193
+ - !ruby/object:Gem::Version
194
+ version: '0'
195
+ description: Provides methods to declare and use ThreadLocalVar instance variables
196
+ email:
197
+ - aks@stebbens.org
198
+ executables: []
199
+ extensions: []
200
+ extra_rdoc_files: []
201
+ files:
202
+ - Gemfile
203
+ - Gemfile.lock
204
+ - LICENSE
205
+ - LICENSE.md
206
+ - README.md
207
+ - Rakefile
208
+ - lib/thread_local_var_accessors.rb
209
+ - lib/thread_local_var_accessors/version.rb
210
+ - thread_local_var_accessors.gemspec
211
+ homepage: https://github.com/aks/thread_local_var_accessors
212
+ licenses:
213
+ - MIT
214
+ metadata: {}
215
+ post_install_message:
216
+ rdoc_options: []
217
+ require_paths:
218
+ - lib
219
+ required_ruby_version: !ruby/object:Gem::Requirement
220
+ requirements:
221
+ - - ">="
222
+ - !ruby/object:Gem::Version
223
+ version: '0'
224
+ required_rubygems_version: !ruby/object:Gem::Requirement
225
+ requirements:
226
+ - - ">="
227
+ - !ruby/object:Gem::Version
228
+ version: '0'
229
+ requirements: []
230
+ rubygems_version: 3.1.6
231
+ signing_key:
232
+ specification_version: 4
233
+ summary: Ruby gem to make ThreadLocalVars easy to use
234
+ test_files: []