thread_local_var_accessors 1.1.0 → 1.3.0
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 +4 -4
- data/Gemfile.lock +1 -1
- data/README.md +63 -38
- data/lib/thread_local_var_accessors/version.rb +1 -1
- data/lib/thread_local_var_accessors.rb +46 -16
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 4537e0db3960367d75a6ab4d731026c6a425e315816bf0523d078b563b90a09a
|
4
|
+
data.tar.gz: d270efc557c3b04f41ae9adf7850157d98c793a7d57cd025e8c88a40d2aaa154
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: b1ad3ff8ce74641cdb6956fe084d8bd69e2712b002805302c2ca3550d82591e2874e94322dbf3ba4123f70f8185318fb05c6ef51e8527ce6145361f72347fb64
|
7
|
+
data.tar.gz: 16ad94b606dfc4249bf344fcd859c1db7929bd026680fc8ef885e6768097c20cfbbc4753543c4989fea1095ce2876fbd525b5ba9090570fd117d79936446838b
|
data/Gemfile.lock
CHANGED
data/README.md
CHANGED
@@ -28,10 +28,10 @@ variables that use `ThreadLocalVar` (TLV) objects.
|
|
28
28
|
the instance variable names '@name', which is expected to be either nil,
|
29
29
|
or already have a `Concurrent::ThreadLocalVar` instance.
|
30
30
|
|
31
|
-
- `tlv_writer` creates an instance method with the name `name=`, which accepts a
|
32
|
-
argument that is the new value.
|
33
|
-
on the instance variable named `@name`, which should be a
|
34
|
-
`Concurrent::ThreadLocalVar` instance.
|
31
|
+
- `tlv_writer` creates an instance method with the name `name=`, which accepts a
|
32
|
+
single argument that is the new value. This method checks for an existing
|
33
|
+
value on the instance variable named `@name`, which should be a
|
34
|
+
`Concurrent::ThreadLocalVar` instance. If `@name` value is nil, then a new
|
35
35
|
`Concurrent::ThreadLocalVar` instance is assigned to it. In either case, the
|
36
36
|
instance variable's TLV object is assigned the new value, which is returned.
|
37
37
|
|
@@ -41,25 +41,32 @@ For reference, see [ThreadLocalVars](https://ruby-concurrency.github.io/concurre
|
|
41
41
|
|
42
42
|
### Instance Methods
|
43
43
|
|
44
|
-
The following are a brief list of the instance variable in
|
44
|
+
The following are a brief list of the instance variable in
|
45
|
+
the `ThreadLocalVarAccessors` class.
|
45
46
|
|
46
47
|
These methods interrogate or set thread-local variable values:
|
47
48
|
|
48
|
-
tlv_get NAME
|
49
|
-
tlv_set NAME, VALUE
|
50
|
-
tlv_set NAME { VALUE }
|
51
|
-
tlv_set_once NAME, VALUE
|
52
|
-
tlv_set_once NAME { VALUE }
|
49
|
+
tlv_get NAME # => TLV value
|
50
|
+
tlv_set NAME, VALUE # => TLV value
|
51
|
+
tlv_set NAME { VALUE } # => TLV value
|
52
|
+
tlv_set_once NAME, VALUE # => current TLV value, or new VALUE
|
53
|
+
tlv_set_once NAME { VALUE } # => current TLV value, or new VALUE
|
53
54
|
|
54
|
-
|
55
|
+
There is a method to fetch the TLV object for a given instance variable name,
|
56
|
+
but only if it is actually a TLV. If the instance variable is unassigned, or
|
57
|
+
contains a non-TLV, then `nil` is returned.
|
55
58
|
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
59
|
+
tlv_get_var NAME # => TLV object or nil
|
60
|
+
|
61
|
+
The methods below manage the default values for thread-local variables:
|
62
|
+
|
63
|
+
tlv_new NAME, DEFAULT # => new TLV
|
64
|
+
tlv_new NAME { DEFAULT } # => new TLV
|
65
|
+
tlv_init NAME, DEFAULT # => DEFAULT
|
66
|
+
tlv_init NAME { DEFAULT } # => DEFAULT
|
67
|
+
tlv_default NAME # => TLV default value for NAME
|
68
|
+
tlv_set_default NAME, VALUE # => VALUE
|
69
|
+
tlv_set_default NAME { VALUE } # => VALUE
|
63
70
|
|
64
71
|
### Instance Variable Details
|
65
72
|
|
@@ -86,20 +93,21 @@ any particular value (other than nil) to be inherited, then using `tlv_set`
|
|
86
93
|
is the right way to go.
|
87
94
|
|
88
95
|
|
89
|
-
The TLV default value is used across *all* threads
|
96
|
+
The TLV default value is used across *all* threads, when there is no value
|
97
|
+
specifically assigned for a given thread.
|
90
98
|
|
91
99
|
tlv_init(:timeout, default)
|
92
100
|
tlv_init(:timeout) { default }
|
93
101
|
|
94
|
-
The `tlv_init` method is essentially the same as `tlv_set_default
|
95
|
-
default value (or block) of a given TLVar, without
|
96
|
-
thread-local variables already assigned.
|
102
|
+
The `tlv_init` method is essentially the same as `tlv_set_default` followed
|
103
|
+
by `tlv_get`: it sets the default value (or block) of a given TLVar, without
|
104
|
+
affecting any possible thread-local variables already assigned.
|
97
105
|
|
98
106
|
Alternative ways to initialize:
|
99
107
|
|
100
|
-
tlv_set(:timeout, 0)
|
108
|
+
tlv_set(:timeout, 0) # => 0
|
101
109
|
|
102
|
-
tlv_set(:timeout)
|
110
|
+
tlv_set(:timeout) # @timeout = Concurrent::ThreadLocalVar.new
|
103
111
|
@timeout.value = 0
|
104
112
|
|
105
113
|
### More Details
|
@@ -121,8 +129,8 @@ a TLV value only if has not currently be set already.
|
|
121
129
|
|
122
130
|
tlv_set_once(name) { |old_val| new_value }
|
123
131
|
|
124
|
-
For `tlv_accessor` instance variables, it's possible to use the assign operators,
|
125
|
-
For example:
|
132
|
+
For `tlv_accessor` instance variables, it's possible to use the assign operators,
|
133
|
+
eg: `+=`, or `||=`. For example:
|
126
134
|
|
127
135
|
tlv_accessor :timeout, :count
|
128
136
|
|
@@ -152,14 +160,16 @@ Then:
|
|
152
160
|
|
153
161
|
## Usage
|
154
162
|
|
155
|
-
To use the class methods, they must be included into the current module or
|
163
|
+
To use the class methods, they must be included into the current module or
|
164
|
+
class, with:
|
156
165
|
|
157
166
|
class MyNewClass
|
158
167
|
include ThreadLocalVarAccessors
|
159
168
|
...
|
160
169
|
end
|
161
170
|
|
162
|
-
With the include above, you can use the class methods to declare instance getter
|
171
|
+
With the include above, you can use the class methods to declare instance getter
|
172
|
+
and setter methods:
|
163
173
|
|
164
174
|
class MyNewClass
|
165
175
|
include ThreadLocalVarAccessors
|
@@ -175,11 +185,15 @@ The above invocations:
|
|
175
185
|
- create reader methods for `name1`, `name3`, and `name4`.
|
176
186
|
- create writer methods for `name2`, `name3`, and `name4`.
|
177
187
|
|
178
|
-
The writer methods accept a value as the second argument, or from the result of
|
188
|
+
The writer methods accept a value as the second argument, or from the result of
|
189
|
+
an optional, associated block.
|
179
190
|
|
180
|
-
Note: to use the read-and-operate operators, eg: `+=`, `-=`, `||=`, etc., the
|
191
|
+
Note: to use the read-and-operate operators, eg: `+=`, `-=`, `||=`, etc., the
|
192
|
+
object must have both a reader and writer method. In other words, it needs to
|
193
|
+
have been created as an `tlv_accessor`.
|
181
194
|
|
182
|
-
When adapting legacy code to become thread-safe, it's sometimes necessary to use
|
195
|
+
When adapting legacy code to become thread-safe, it's sometimes necessary to use
|
196
|
+
the underlying instance methods:
|
183
197
|
|
184
198
|
tlv_get(name)
|
185
199
|
tlv_set(name, value)
|
@@ -192,7 +206,8 @@ Alternative block forms:
|
|
192
206
|
|
193
207
|
In all cases, the `name` can be a string or symbol, with or without a leading `@`.
|
194
208
|
|
195
|
-
Ultimately, these methods are all
|
209
|
+
Ultimately, these methods are all performing basic accesses of the corresponding
|
210
|
+
instance variables:
|
196
211
|
|
197
212
|
@name1 ||= ThreadLocalVar.new
|
198
213
|
@name1.value = per_thread_value
|
@@ -222,7 +237,10 @@ class MyClass
|
|
222
237
|
self.sleep_time = args[:sleep_time]
|
223
238
|
end
|
224
239
|
|
225
|
-
# if the ivars might possibly be inherited in new threads after
|
240
|
+
# if the ivars might possibly be inherited in new threads after
|
241
|
+
# initialization, then the defaults should be set for each thread to
|
242
|
+
# inherit.
|
243
|
+
|
226
244
|
def alt_initialize(**args)
|
227
245
|
# for each ivar, set the default value, which is inherited across all threads
|
228
246
|
tlv_init :limit, args[:limit]
|
@@ -246,9 +264,12 @@ end
|
|
246
264
|
|
247
265
|
## Development
|
248
266
|
|
249
|
-
After checking out the repo, run `bin/setup` to install dependencies. Then,
|
267
|
+
After checking out the repo, run `bin/setup` to install dependencies. Then,
|
268
|
+
run `rake spec` to run the tests. You can also run `bin/console` for an
|
269
|
+
interactive prompt that will allow you to experiment.
|
250
270
|
|
251
|
-
For both development and testing, the environment variables described above must
|
271
|
+
For both development and testing, the environment variables described above must
|
272
|
+
be defined.
|
252
273
|
|
253
274
|
## Testing
|
254
275
|
|
@@ -256,11 +277,15 @@ For both development and testing, the environment variables described above must
|
|
256
277
|
|
257
278
|
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.
|
258
279
|
|
259
|
-
The `main` branch gets updated with a PR or with a manual merge-and-push from
|
280
|
+
The `main` branch gets updated with a PR or with a manual merge-and-push from
|
281
|
+
the `develop` branch by a repo admin.
|
260
282
|
|
261
|
-
When any branch is pushed, the continuous integration with causes the branch to
|
283
|
+
When any branch is pushed, the continuous integration with causes the branch to
|
284
|
+
be tested with all of the `rspec` tests _(except the integration tests)_.
|
262
285
|
|
263
|
-
When the `main` branch is updated and after its tests pass, the `deploy` action
|
286
|
+
When the `main` branch is updated and after its tests pass, the `deploy` action
|
287
|
+
is invoked which causes the newest build of the gem to be pushed to
|
288
|
+
rubygems.org.
|
264
289
|
|
265
290
|
## Original Author:
|
266
291
|
|
@@ -230,16 +230,34 @@ module ThreadLocalVarAccessors
|
|
230
230
|
# instance methods
|
231
231
|
# Returns the value of the TLV instance variable, if any.
|
232
232
|
def tlv_get(name)
|
233
|
-
|
233
|
+
tlv_get_var(name)&.value
|
234
234
|
end
|
235
235
|
|
236
|
-
#
|
237
|
-
|
238
|
-
|
239
|
-
|
236
|
+
# @return [ThreadLocalVar] the TLV, if any, of the named instance variable.
|
237
|
+
def tlv_get_var(name)
|
238
|
+
var = instance_variable_get(name.to_ivar)
|
239
|
+
var if var.is_a?(Concurrent::ThreadLocalVar)
|
240
|
+
end
|
241
|
+
|
242
|
+
# If the instance variable is already a TLV, then set it's value to the
|
243
|
+
# given value, or the value returned by the block, if any. If the
|
244
|
+
# instance variable is not a TLV, then create a new TLV, initializing
|
245
|
+
# it's default value with the given value, or the value returned by the block,
|
246
|
+
# if any, then, returning it's local value -- which returns the default value.
|
247
|
+
#
|
248
|
+
# This method is equivalent to:
|
249
|
+
# if @name.is_a?(ThreadLocalVar)
|
250
|
+
# @name.value = block_given? ? yield : value
|
251
|
+
# else
|
252
|
+
# @name = ThreadLocalVar(value, &block)
|
253
|
+
# end
|
254
|
+
# @return [Object] the value of the TLV instance variable
|
240
255
|
def tlv_set(name, value = nil, &block)
|
241
|
-
var =
|
242
|
-
|
256
|
+
if (var = tlv_get_var(name))
|
257
|
+
tlv_set_var(var, value, &block)
|
258
|
+
else
|
259
|
+
tlv_new(name, value, &block).value
|
260
|
+
end
|
243
261
|
end
|
244
262
|
|
245
263
|
# Sets the thread-local value of the TLV instance variable, but only
|
@@ -247,12 +265,12 @@ module ThreadLocalVarAccessors
|
|
247
265
|
# @name ||= ThreadLocalVar.new
|
248
266
|
# @name.value ||= block_given? yield : value
|
249
267
|
def tlv_set_once(name, value = nil, &block)
|
250
|
-
if (var =
|
268
|
+
if (var = tlv_get_var(name))&.value
|
251
269
|
var.value
|
252
270
|
elsif var # var is set, but its value is nil
|
253
271
|
tlv_set_var(var, value, &block)
|
254
|
-
else # var is not set
|
255
|
-
|
272
|
+
else # var is not set, initialize it
|
273
|
+
tlv_new(name, value, &block).value
|
256
274
|
end
|
257
275
|
end
|
258
276
|
|
@@ -260,27 +278,38 @@ module ThreadLocalVarAccessors
|
|
260
278
|
# Equivalent to:
|
261
279
|
# @name = ThreadLocalVar.new(block_given? ? yield : default)
|
262
280
|
def tlv_new(name, default=nil, &block)
|
263
|
-
instance_variable_set(
|
281
|
+
instance_variable_set(
|
282
|
+
name.to_ivar,
|
283
|
+
Concurrent::ThreadLocalVar.new(default, &block)
|
284
|
+
)
|
264
285
|
end
|
265
286
|
|
266
287
|
# Creates a new TLVar with a default, or assigns the default value to an
|
267
288
|
# existing TLVar, without affecting any existing thread-local values.
|
289
|
+
# Returns the value of the new TLVar.
|
268
290
|
# Equivalent to:
|
269
291
|
# @name ||= ThreadLocalVar.new
|
270
292
|
# @name.instance_variable_set(:@default, block_given? ? yield : default)
|
293
|
+
# @name.value
|
271
294
|
def tlv_init(name, default=nil, &block)
|
272
295
|
tlv_set_default(name, default, &block)
|
296
|
+
tlv_get(name)
|
273
297
|
end
|
274
298
|
|
275
|
-
# Fetches the default value for the TLVar
|
276
|
-
# Equivalent to:
|
277
|
-
# @name&.send(:default)
|
299
|
+
# Fetches the default value for the TLVar at the ivar
|
278
300
|
def tlv_default(name)
|
279
|
-
|
301
|
+
tlv_get_default(tlv_get_var(name))
|
302
|
+
end
|
303
|
+
|
304
|
+
# gets the default value from a TLV
|
305
|
+
# this masks the private ThreadLocalVar#default method
|
306
|
+
def tlv_get_default(tlv)
|
307
|
+
tlv&.send(:default)
|
280
308
|
end
|
281
309
|
|
282
310
|
# Sets the default value or block for the TLV _(which is applied across all threads)_.
|
283
311
|
# Creates a new TLV if the instance variable is not initialized.
|
312
|
+
# @return [Object] the effective default value of the TLV instance variable
|
284
313
|
def tlv_set_default(name, default=nil, &block)1
|
285
314
|
tlv = instance_variable_get(name.to_ivar)
|
286
315
|
if tlv
|
@@ -295,8 +324,9 @@ module ThreadLocalVarAccessors
|
|
295
324
|
end
|
296
325
|
tlv
|
297
326
|
else
|
298
|
-
tlv_new(name, default, &block)
|
327
|
+
tlv = tlv_new(name, default, &block)
|
299
328
|
end
|
329
|
+
tlv_get_default(tlv)
|
300
330
|
end
|
301
331
|
|
302
332
|
# @!visibility private
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: thread_local_var_accessors
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.
|
4
|
+
version: 1.3.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Alan Stebbens
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2023-
|
11
|
+
date: 2023-06-10 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|