thread_local_var_accessors 0.1.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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: []