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 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