backports 3.18.0 → 3.20.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.
Files changed (42) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +47 -1
  3. data/Gemfile +3 -16
  4. data/README.md +31 -11
  5. data/backports.gemspec +1 -1
  6. data/lib/backports/2.0.0.rb +1 -1
  7. data/lib/backports/2.1.0.rb +1 -1
  8. data/lib/backports/2.2.0.rb +1 -1
  9. data/lib/backports/2.2.0/string/unicode_normalize.rb +3 -3
  10. data/lib/backports/2.3.0.rb +1 -1
  11. data/lib/backports/2.3.0/queue/close.rb +48 -0
  12. data/lib/backports/2.3.0/string.rb +3 -0
  13. data/lib/backports/2.4.0.rb +1 -1
  14. data/lib/backports/2.4.0/bignum.rb +3 -0
  15. data/lib/backports/2.4.0/bignum/dup.rb +5 -0
  16. data/lib/backports/2.5.0.rb +1 -1
  17. data/lib/backports/2.5.0/hash/transform_keys.rb +10 -3
  18. data/lib/backports/2.5.0/integer/sqrt.rb +1 -1
  19. data/lib/backports/2.5.0/string/undump.rb +2 -2
  20. data/lib/backports/2.5.rb +1 -1
  21. data/lib/backports/2.6.0.rb +2 -2
  22. data/lib/backports/2.6.0/enumerable/chain.rb +2 -0
  23. data/lib/backports/2.6.rb +1 -1
  24. data/lib/backports/2.7.0.rb +2 -2
  25. data/lib/backports/3.0.0.rb +3 -0
  26. data/lib/backports/3.0.0/env.rb +3 -0
  27. data/lib/backports/3.0.0/env/except.rb +10 -0
  28. data/lib/backports/3.0.0/hash.rb +3 -0
  29. data/lib/backports/3.0.0/hash/except.rb +10 -0
  30. data/lib/backports/3.0.0/hash/transform_keys.rb +48 -0
  31. data/lib/backports/3.0.0/ractor.rb +5 -0
  32. data/lib/backports/3.0.0/symbol.rb +3 -0
  33. data/lib/backports/3.0.0/symbol/name.rb +11 -0
  34. data/lib/backports/3.0.rb +1 -0
  35. data/lib/backports/ractor/cloner.rb +91 -0
  36. data/lib/backports/ractor/errors.rb +16 -0
  37. data/lib/backports/ractor/queues.rb +62 -0
  38. data/lib/backports/ractor/ractor.rb +261 -0
  39. data/lib/backports/ractor/sharing.rb +93 -0
  40. data/lib/backports/tools/filtered_queue.rb +202 -0
  41. data/lib/backports/version.rb +1 -1
  42. metadata +27 -7
@@ -0,0 +1,93 @@
1
+ class Ractor
2
+ class << self
3
+ # @api private
4
+ def ractor_isolate(val, move = false)
5
+ return val if move
6
+
7
+ Cloner.deep_clone(val)
8
+ end
9
+
10
+ private def ractor_check_shareability?(obj, freeze_all)
11
+ ractor_shareable_self?(obj, freeze_all) do
12
+ visited = {}
13
+
14
+ return false unless ractor_shareable_parts?(obj, freeze_all, visited)
15
+
16
+ ractor_mark_set_shareable(visited)
17
+
18
+ true
19
+ end
20
+ end
21
+
22
+ # yield if shareability can't be determined without looking at its parts
23
+ def ractor_shareable_self?(obj, freeze_all)
24
+ return true if @ractor_shareable.key?(obj)
25
+ return true if ractor_shareable_by_nature?(obj, freeze_all)
26
+ if obj.frozen? || (freeze_all && obj.freeze)
27
+ yield
28
+ else
29
+ false
30
+ end
31
+ end
32
+
33
+ private def ractor_shareable_parts?(obj, freeze_all, visited)
34
+ return true if visited.key?(obj)
35
+ visited[obj] = true
36
+
37
+ ractor_traverse(obj) do |part|
38
+ return false unless ractor_shareable_self?(part, freeze_all) do
39
+ ractor_shareable_parts?(part, freeze_all, visited)
40
+ end
41
+ end
42
+
43
+ true
44
+ end
45
+
46
+ def ractor_mark_set_shareable(visited)
47
+ visited.each do |key|
48
+ @ractor_shareable[key] = Ractor
49
+ end
50
+ end
51
+
52
+ private def ractor_traverse(obj, &block)
53
+ case obj
54
+ when ::Hash
55
+ Hash obj.default
56
+ yield obj.default_proc
57
+ obj.each do |key, value|
58
+ yield key
59
+ yield value
60
+ end
61
+ when ::Range
62
+ yield obj.begin
63
+ yield obj.end
64
+ when ::Array, ::Struct
65
+ obj.each(&block)
66
+ when ::Complex
67
+ yield obj.real
68
+ yield obj.imaginary
69
+ when ::Rational
70
+ yield obj.numerator
71
+ yield obj.denominator
72
+ end
73
+ obj.instance_variables.each do |var|
74
+ yield obj.instance_variable_get(var)
75
+ end
76
+ end
77
+
78
+ private def ractor_shareable_by_nature?(obj, freeze_all)
79
+ case obj
80
+ when ::Module, ::Ractor
81
+ true
82
+ when ::Regexp, ::Range, ::Numeric
83
+ !freeze_all # Assume that these are literals that would have been frozen in 3.0
84
+ # unless we're making them shareable, in which case we might as well
85
+ # freeze them for real.
86
+ when ::Symbol, false, true, nil # Were only frozen in Ruby 2.3+
87
+ true
88
+ else
89
+ false
90
+ end
91
+ end
92
+ end
93
+ end
@@ -0,0 +1,202 @@
1
+ module Backports
2
+ class FilteredQueue
3
+ require 'backports/2.3.0/queue/close'
4
+ CONSUME_ON_ESCAPE = true
5
+
6
+ class ClosedQueueError < ::ClosedQueueError
7
+ end
8
+ class TimeoutError < ::ThreadError
9
+ end
10
+
11
+ class Message
12
+ # Not using Struct as we want comparision by identity
13
+ attr_reader :value
14
+ attr_accessor :reserved
15
+
16
+ def initialize(value)
17
+ @value = value
18
+ @reserved = false
19
+ end
20
+ end
21
+ private_constant :Message
22
+
23
+ # Like ::Queue, but with
24
+ # - filtering
25
+ # - timeout
26
+ # - raises on closed queues
27
+
28
+ attr_reader :num_waiting
29
+
30
+ # Timeout processing based on https://spin.atomicobject.com/2017/06/28/queue-pop-with-timeout-fixed/
31
+ def initialize
32
+ @mutex = ::Mutex.new
33
+ @queue = []
34
+ @closed = false
35
+ @received = ::ConditionVariable.new
36
+ @num_waiting = 0
37
+ end
38
+
39
+ def close
40
+ @mutex.synchronize do
41
+ @closed = true
42
+ @received.broadcast
43
+ end
44
+ self
45
+ end
46
+
47
+ def closed?
48
+ @closed
49
+ end
50
+
51
+ def <<(x)
52
+ @mutex.synchronize do
53
+ ensure_open
54
+ @queue << Message.new(x)
55
+ @received.signal
56
+ end
57
+ self
58
+ end
59
+ alias_method :push, :<<
60
+
61
+ def clear
62
+ @mutex.synchronize do
63
+ @queue.clear
64
+ end
65
+ self
66
+ end
67
+
68
+ def pop(timeout: nil, &block)
69
+ msg = nil
70
+ exclude = [] if block # exclusion list of messages rejected by this call
71
+ timeout_time = timeout + Time.now.to_f if timeout
72
+ while true do
73
+ @mutex.synchronize do
74
+ reenter if reentrant?
75
+ msg = acquire!(timeout_time, exclude)
76
+ return consume!(msg).value unless block
77
+ end
78
+ return msg.value if filter?(msg, &block)
79
+ end
80
+ end
81
+
82
+ def empty?
83
+ avail = @mutex.synchronize do
84
+ available!
85
+ end
86
+
87
+ !avail
88
+ end
89
+
90
+ protected def timeout_value
91
+ raise self.class::TimeoutError, "timeout elapsed"
92
+ end
93
+
94
+ protected def closed_queue_value
95
+ ensure_open
96
+ end
97
+
98
+ # @return if outer message should be consumed or not
99
+ protected def reenter
100
+ true
101
+ end
102
+
103
+ ### private section
104
+ #
105
+ # bang methods require synchronization
106
+
107
+ # @returns:
108
+ # * true if message consumed (block result truthy or due to reentrant call)
109
+ # * false if rejected
110
+ private def filter?(msg)
111
+ consume = self.class::CONSUME_ON_ESCAPE
112
+ begin
113
+ reentered = consume_on_reentry(msg) do
114
+ consume = !!(yield msg.value)
115
+ end
116
+ reentered ? reenter : consume
117
+ ensure
118
+ commit(msg, consume) unless reentered
119
+ end
120
+ end
121
+
122
+ # @returns msg
123
+ private def consume!(msg)
124
+ @queue.delete(msg)
125
+ end
126
+
127
+ private def reject!(msg)
128
+ msg.reserved = false
129
+ @received.broadcast
130
+ end
131
+
132
+ private def commit(msg, consume)
133
+ @mutex.synchronize do
134
+ if consume
135
+ consume!(msg)
136
+ else
137
+ reject!(msg)
138
+ end
139
+ end
140
+ end
141
+
142
+ private def consume_on_reentry(msg)
143
+ q_map = current_filtered_queues
144
+ if (outer_msg = q_map[self])
145
+ commit(outer_msg, reenter)
146
+ end
147
+ q_map[self] = msg
148
+ begin
149
+ yield
150
+ ensure
151
+ reentered = !q_map.delete(self)
152
+ end
153
+ reentered
154
+ end
155
+
156
+ private def reentrant?
157
+ !!current_filtered_queues[self]
158
+ end
159
+
160
+ # @returns Hash { FilteredQueue => Message }
161
+ private def current_filtered_queues
162
+ t = Thread.current
163
+ t.thread_variable_get(:backports_currently_filtered_queues) or
164
+ t.thread_variable_set(:backports_currently_filtered_queues, {}.compare_by_identity)
165
+ end
166
+
167
+ # private methods assume @mutex synchonized
168
+ # adds to exclude list
169
+ private def acquire!(timeout_time, exclude = nil)
170
+ while true do
171
+ if (msg = available!(exclude))
172
+ msg.reserved = true
173
+ exclude << msg if exclude
174
+ return msg
175
+ end
176
+ return closed_queue_value if @closed
177
+ # wait for element or timeout
178
+ if timeout_time
179
+ remaining_time = timeout_time - ::Time.now.to_f
180
+ return timeout_value if remaining_time <= 0
181
+ end
182
+ begin
183
+ @num_waiting += 1
184
+ @received.wait(@mutex, remaining_time)
185
+ ensure
186
+ @num_waiting -= 1
187
+ end
188
+ end
189
+ end
190
+
191
+ private def available!(exclude = nil)
192
+ @queue.find do |msg|
193
+ next if exclude && exclude.include?(msg)
194
+ !msg.reserved
195
+ end
196
+ end
197
+
198
+ private def ensure_open
199
+ raise self.class::ClosedQueueError, 'queue closed' if @closed
200
+ end
201
+ end
202
+ end
@@ -1,3 +1,3 @@
1
1
  module Backports
2
- VERSION = "3.18.0" unless Backports.constants.include? :VERSION # the guard is against a redefinition warning that happens on Travis
2
+ VERSION = "3.20.1" unless Backports.constants.include? :VERSION # the guard is against a redefinition warning that happens on Travis
3
3
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: backports
3
3
  version: !ruby/object:Gem::Version
4
- version: 3.18.0
4
+ version: 3.20.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Marc-André Lafortune
8
- autorequire:
8
+ autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2020-06-22 00:00:00.000000000 Z
11
+ date: 2021-01-03 00:00:00.000000000 Z
12
12
  dependencies: []
13
13
  description: Essential backports that enable many of the nice features of Ruby for
14
14
  earlier versions.
@@ -425,12 +425,16 @@ files:
425
425
  - lib/backports/2.3.0/numeric.rb
426
426
  - lib/backports/2.3.0/numeric/negative.rb
427
427
  - lib/backports/2.3.0/numeric/positive.rb
428
+ - lib/backports/2.3.0/queue/close.rb
429
+ - lib/backports/2.3.0/string.rb
428
430
  - lib/backports/2.3.0/string/uminus.rb
429
431
  - lib/backports/2.3.0/string/uplus.rb
430
432
  - lib/backports/2.3.0/struct.rb
431
433
  - lib/backports/2.3.0/struct/dig.rb
432
434
  - lib/backports/2.3.rb
433
435
  - lib/backports/2.4.0.rb
436
+ - lib/backports/2.4.0/bignum.rb
437
+ - lib/backports/2.4.0/bignum/dup.rb
434
438
  - lib/backports/2.4.0/comparable.rb
435
439
  - lib/backports/2.4.0/comparable/clamp.rb
436
440
  - lib/backports/2.4.0/enumerable.rb
@@ -528,6 +532,16 @@ files:
528
532
  - lib/backports/2.7.0/time/ceil.rb
529
533
  - lib/backports/2.7.0/time/floor.rb
530
534
  - lib/backports/2.7.rb
535
+ - lib/backports/3.0.0.rb
536
+ - lib/backports/3.0.0/env.rb
537
+ - lib/backports/3.0.0/env/except.rb
538
+ - lib/backports/3.0.0/hash.rb
539
+ - lib/backports/3.0.0/hash/except.rb
540
+ - lib/backports/3.0.0/hash/transform_keys.rb
541
+ - lib/backports/3.0.0/ractor.rb
542
+ - lib/backports/3.0.0/symbol.rb
543
+ - lib/backports/3.0.0/symbol/name.rb
544
+ - lib/backports/3.0.rb
531
545
  - lib/backports/basic_object.rb
532
546
  - lib/backports/force/array_map.rb
533
547
  - lib/backports/force/enumerable_map.rb
@@ -535,6 +549,11 @@ files:
535
549
  - lib/backports/force/string_length.rb
536
550
  - lib/backports/force/string_size.rb
537
551
  - lib/backports/latest.rb
552
+ - lib/backports/ractor/cloner.rb
553
+ - lib/backports/ractor/errors.rb
554
+ - lib/backports/ractor/queues.rb
555
+ - lib/backports/ractor/ractor.rb
556
+ - lib/backports/ractor/sharing.rb
538
557
  - lib/backports/rails.rb
539
558
  - lib/backports/rails/array.rb
540
559
  - lib/backports/rails/enumerable.rb
@@ -553,6 +572,7 @@ files:
553
572
  - lib/backports/tools/arguments.rb
554
573
  - lib/backports/tools/deprecation.rb
555
574
  - lib/backports/tools/extreme_object.rb
575
+ - lib/backports/tools/filtered_queue.rb
556
576
  - lib/backports/tools/float_integer_conversion.rb
557
577
  - lib/backports/tools/io.rb
558
578
  - lib/backports/tools/make_block_optional.rb
@@ -566,10 +586,10 @@ homepage: http://github.com/marcandre/backports
566
586
  licenses:
567
587
  - MIT
568
588
  metadata:
569
- changelog_uri: https://github.com/marcandre/backports/blob/master/CHANGELOG.rdoc
589
+ changelog_uri: https://github.com/marcandre/backports/blob/master/CHANGELOG.md
570
590
  source_code_uri: https://github.com/marcandre/backports
571
591
  bug_tracker_uri: https://github.com/marcandre/backports/issues
572
- post_install_message:
592
+ post_install_message:
573
593
  rdoc_options: []
574
594
  require_paths:
575
595
  - lib
@@ -584,8 +604,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
584
604
  - !ruby/object:Gem::Version
585
605
  version: '0'
586
606
  requirements: []
587
- rubygems_version: 3.1.2
588
- signing_key:
607
+ rubygems_version: 3.1.4
608
+ signing_key:
589
609
  specification_version: 4
590
610
  summary: Backports of Ruby features for older Ruby.
591
611
  test_files: []