backports 3.17.2 → 3.20.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (47) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +52 -1
  3. data/Gemfile +3 -16
  4. data/README.md +31 -11
  5. data/backports.gemspec +1 -1
  6. data/lib/backports/1.8.7.rb +5 -4
  7. data/lib/backports/1.9.1.rb +6 -1
  8. data/lib/backports/1.9.2.rb +6 -1
  9. data/lib/backports/1.9.3.rb +6 -1
  10. data/lib/backports/2.0.0.rb +7 -2
  11. data/lib/backports/2.1.0.rb +2 -2
  12. data/lib/backports/2.2.0.rb +2 -2
  13. data/lib/backports/2.2.0/string/unicode_normalize.rb +3 -3
  14. data/lib/backports/2.3.0.rb +2 -2
  15. data/lib/backports/2.3.0/queue/close.rb +48 -0
  16. data/lib/backports/2.3.0/string.rb +3 -0
  17. data/lib/backports/2.4.0.rb +2 -2
  18. data/lib/backports/2.4.0/bignum.rb +3 -0
  19. data/lib/backports/2.4.0/bignum/dup.rb +5 -0
  20. data/lib/backports/2.5.0.rb +2 -2
  21. data/lib/backports/2.5.0/hash/transform_keys.rb +10 -3
  22. data/lib/backports/2.5.0/integer/sqrt.rb +1 -1
  23. data/lib/backports/2.5.0/string/undump.rb +2 -2
  24. data/lib/backports/2.5.rb +1 -1
  25. data/lib/backports/2.6.0.rb +3 -3
  26. data/lib/backports/2.6.0/enumerable/chain.rb +2 -0
  27. data/lib/backports/2.6.rb +1 -1
  28. data/lib/backports/2.7.0.rb +3 -3
  29. data/lib/backports/3.0.0.rb +3 -0
  30. data/lib/backports/3.0.0/env.rb +3 -0
  31. data/lib/backports/3.0.0/env/except.rb +10 -0
  32. data/lib/backports/3.0.0/hash.rb +3 -0
  33. data/lib/backports/3.0.0/hash/except.rb +10 -0
  34. data/lib/backports/3.0.0/hash/transform_keys.rb +48 -0
  35. data/lib/backports/3.0.0/ractor.rb +5 -0
  36. data/lib/backports/3.0.0/symbol.rb +3 -0
  37. data/lib/backports/3.0.0/symbol/name.rb +11 -0
  38. data/lib/backports/3.0.rb +1 -0
  39. data/lib/backports/ractor/cloner.rb +91 -0
  40. data/lib/backports/ractor/errors.rb +16 -0
  41. data/lib/backports/ractor/queues.rb +62 -0
  42. data/lib/backports/ractor/ractor.rb +238 -0
  43. data/lib/backports/ractor/sharing.rb +93 -0
  44. data/lib/backports/tools/filtered_queue.rb +202 -0
  45. data/lib/backports/tools/require_relative_dir.rb +6 -1
  46. data/lib/backports/version.rb +1 -1
  47. 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
@@ -7,7 +7,12 @@ module Backports
7
7
  compact.
8
8
  sort.
9
9
  each do |f|
10
- require short_path + f
10
+ path = '../../' + short_path + f
11
+ if Kernel.private_method_defined?(:require_relative)
12
+ require_relative path
13
+ else
14
+ require File.expand_path(path)
15
+ end
11
16
  end
12
17
  end
13
18
  end
@@ -1,3 +1,3 @@
1
1
  module Backports
2
- VERSION = "3.17.2" unless Backports.constants.include? :VERSION # the guard is against a redefinition warning that happens on Travis
2
+ VERSION = "3.20.0" 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.17.2
4
+ version: 3.20.0
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-05-20 00:00:00.000000000 Z
11
+ date: 2020-12-30 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: []