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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 939ace98d853409e91249ccd6a34a1acfa707f77293984c9143e4acee3e011a1
4
- data.tar.gz: bd876354d8cae177ee222d6fbe7110f417013485d568ce3bd031aa068c752883
3
+ metadata.gz: 4537e0db3960367d75a6ab4d731026c6a425e315816bf0523d078b563b90a09a
4
+ data.tar.gz: d270efc557c3b04f41ae9adf7850157d98c793a7d57cd025e8c88a40d2aaa154
5
5
  SHA512:
6
- metadata.gz: 6a3c026cd82bf5676d412ae88a799645afa5e5f3c9a85b552489656a8c1a9340435dfbd8ab1e00c0400d28f4792c009bb7f19d100f7a6792d77be71fe7ba3a04
7
- data.tar.gz: 72001afd55e3c86e9da161f8d596fb148dd33a009a33ca72cc126425a59f6e8238adab52f2360de4e14b29c037f44aa2c728e01456b8dc0c3f22253d242e5fc6
6
+ metadata.gz: b1ad3ff8ce74641cdb6956fe084d8bd69e2712b002805302c2ca3550d82591e2874e94322dbf3ba4123f70f8185318fb05c6ef51e8527ce6145361f72347fb64
7
+ data.tar.gz: 16ad94b606dfc4249bf344fcd859c1db7929bd026680fc8ef885e6768097c20cfbbc4753543c4989fea1095ce2876fbd525b5ba9090570fd117d79936446838b
data/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- thread_local_var_accessors (1.1.0)
4
+ thread_local_var_accessors (1.3.0)
5
5
  concurrent-ruby
6
6
 
7
7
  GEM
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 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
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 the `ThreadLocalVarAccessors` class.
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
- These methods manage the default values for thread-local variables:
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
- tlv_new NAME, DEFAULT
57
- tlv_new NAME { DEFAULT }
58
- tlv_init NAME, DEFAULT
59
- tlv_init NAME { DEFAULT }
60
- tlv_default NAME
61
- tlv_set_default NAME, VALUE
62
- tlv_set_default NAME { VALUE }
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`: it sets the
95
- default value (or block) of a given TLVar, without affecting any possible
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) # ensure that @timeout is initialized to an TLV
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, eg: `+=`, or `||=`.
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 class, with:
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 and setter methods:
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 an optional, associated block.
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 object must have both a reader and writer method. In other words, it needs to have been created as an `tlv_accessor`.
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 the underlying instance methods:
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 doing these basic accesses of the corresponding instance variables:
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 initialization
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, run `rake spec` to run the tests. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
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 be defined.
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 the `develop` branch by a repo admin.
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 be tested with all of the `rspec` tests _(except the integration tests)_.
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 is invoked which causes the newest build of the gem to be pushed to rubygems.org.
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
 
@@ -1,3 +1,3 @@
1
1
  module ThreadLocalVarAccessors
2
- VERSION = '1.1.0'
2
+ VERSION = '1.3.0'
3
3
  end
@@ -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
- instance_variable_get(name.to_ivar)&.value
233
+ tlv_get_var(name)&.value
234
234
  end
235
235
 
236
- # sets the thread-local value of the TLV instance variable, creating
237
- # it if necessary. This method is equivalent to:
238
- # @name ||= ThreadLocalVar.new
239
- # @name.value = block_given? ? yield : value
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 = instance_variable_get(name.to_ivar) || tlv_new(name)
242
- tlv_set_var(var, value, &block)
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 = instance_variable_get(name.to_ivar)) && !var&.value.nil?
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
- tlv_set_var(tlv_new(name), value, &block)
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(name.to_ivar, Concurrent::ThreadLocalVar.new(default, &block))
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
- instance_variable_get(name.to_ivar)&.send(:default)
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.1.0
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-05-27 00:00:00.000000000 Z
11
+ date: 2023-06-10 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler