thread_local_var_accessors 1.1.0 → 1.3.0
Sign up to get free protection for your applications and to get access to all the features.
- 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
|