o-concurrent-ruby 1.1.11

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 (142) hide show
  1. checksums.yaml +7 -0
  2. data/CHANGELOG.md +542 -0
  3. data/Gemfile +37 -0
  4. data/LICENSE.txt +21 -0
  5. data/README.md +404 -0
  6. data/Rakefile +307 -0
  7. data/ext/concurrent-ruby/ConcurrentRubyService.java +17 -0
  8. data/ext/concurrent-ruby/com/concurrent_ruby/ext/AtomicReferenceLibrary.java +175 -0
  9. data/ext/concurrent-ruby/com/concurrent_ruby/ext/JRubyMapBackendLibrary.java +248 -0
  10. data/ext/concurrent-ruby/com/concurrent_ruby/ext/JavaAtomicBooleanLibrary.java +93 -0
  11. data/ext/concurrent-ruby/com/concurrent_ruby/ext/JavaAtomicFixnumLibrary.java +113 -0
  12. data/ext/concurrent-ruby/com/concurrent_ruby/ext/JavaSemaphoreLibrary.java +189 -0
  13. data/ext/concurrent-ruby/com/concurrent_ruby/ext/SynchronizationLibrary.java +307 -0
  14. data/ext/concurrent-ruby/com/concurrent_ruby/ext/jsr166e/ConcurrentHashMap.java +31 -0
  15. data/ext/concurrent-ruby/com/concurrent_ruby/ext/jsr166e/ConcurrentHashMapV8.java +3863 -0
  16. data/ext/concurrent-ruby/com/concurrent_ruby/ext/jsr166e/LongAdder.java +203 -0
  17. data/ext/concurrent-ruby/com/concurrent_ruby/ext/jsr166e/Striped64.java +342 -0
  18. data/ext/concurrent-ruby/com/concurrent_ruby/ext/jsr166e/nounsafe/ConcurrentHashMapV8.java +3800 -0
  19. data/ext/concurrent-ruby/com/concurrent_ruby/ext/jsr166e/nounsafe/LongAdder.java +204 -0
  20. data/ext/concurrent-ruby/com/concurrent_ruby/ext/jsr166e/nounsafe/Striped64.java +291 -0
  21. data/ext/concurrent-ruby/com/concurrent_ruby/ext/jsr166y/ThreadLocalRandom.java +199 -0
  22. data/lib/concurrent-ruby/concurrent/agent.rb +587 -0
  23. data/lib/concurrent-ruby/concurrent/array.rb +66 -0
  24. data/lib/concurrent-ruby/concurrent/async.rb +449 -0
  25. data/lib/concurrent-ruby/concurrent/atom.rb +222 -0
  26. data/lib/concurrent-ruby/concurrent/atomic/abstract_thread_local_var.rb +66 -0
  27. data/lib/concurrent-ruby/concurrent/atomic/atomic_boolean.rb +126 -0
  28. data/lib/concurrent-ruby/concurrent/atomic/atomic_fixnum.rb +143 -0
  29. data/lib/concurrent-ruby/concurrent/atomic/atomic_markable_reference.rb +164 -0
  30. data/lib/concurrent-ruby/concurrent/atomic/atomic_reference.rb +205 -0
  31. data/lib/concurrent-ruby/concurrent/atomic/count_down_latch.rb +100 -0
  32. data/lib/concurrent-ruby/concurrent/atomic/cyclic_barrier.rb +128 -0
  33. data/lib/concurrent-ruby/concurrent/atomic/event.rb +109 -0
  34. data/lib/concurrent-ruby/concurrent/atomic/java_count_down_latch.rb +42 -0
  35. data/lib/concurrent-ruby/concurrent/atomic/java_thread_local_var.rb +37 -0
  36. data/lib/concurrent-ruby/concurrent/atomic/mutex_atomic_boolean.rb +62 -0
  37. data/lib/concurrent-ruby/concurrent/atomic/mutex_atomic_fixnum.rb +75 -0
  38. data/lib/concurrent-ruby/concurrent/atomic/mutex_count_down_latch.rb +44 -0
  39. data/lib/concurrent-ruby/concurrent/atomic/mutex_semaphore.rb +131 -0
  40. data/lib/concurrent-ruby/concurrent/atomic/read_write_lock.rb +254 -0
  41. data/lib/concurrent-ruby/concurrent/atomic/reentrant_read_write_lock.rb +377 -0
  42. data/lib/concurrent-ruby/concurrent/atomic/ruby_thread_local_var.rb +181 -0
  43. data/lib/concurrent-ruby/concurrent/atomic/semaphore.rb +166 -0
  44. data/lib/concurrent-ruby/concurrent/atomic/thread_local_var.rb +104 -0
  45. data/lib/concurrent-ruby/concurrent/atomic_reference/mutex_atomic.rb +56 -0
  46. data/lib/concurrent-ruby/concurrent/atomic_reference/numeric_cas_wrapper.rb +28 -0
  47. data/lib/concurrent-ruby/concurrent/atomics.rb +10 -0
  48. data/lib/concurrent-ruby/concurrent/collection/copy_on_notify_observer_set.rb +107 -0
  49. data/lib/concurrent-ruby/concurrent/collection/copy_on_write_observer_set.rb +111 -0
  50. data/lib/concurrent-ruby/concurrent/collection/java_non_concurrent_priority_queue.rb +84 -0
  51. data/lib/concurrent-ruby/concurrent/collection/lock_free_stack.rb +158 -0
  52. data/lib/concurrent-ruby/concurrent/collection/map/atomic_reference_map_backend.rb +927 -0
  53. data/lib/concurrent-ruby/concurrent/collection/map/mri_map_backend.rb +66 -0
  54. data/lib/concurrent-ruby/concurrent/collection/map/non_concurrent_map_backend.rb +140 -0
  55. data/lib/concurrent-ruby/concurrent/collection/map/synchronized_map_backend.rb +82 -0
  56. data/lib/concurrent-ruby/concurrent/collection/map/truffleruby_map_backend.rb +14 -0
  57. data/lib/concurrent-ruby/concurrent/collection/non_concurrent_priority_queue.rb +143 -0
  58. data/lib/concurrent-ruby/concurrent/collection/ruby_non_concurrent_priority_queue.rb +160 -0
  59. data/lib/concurrent-ruby/concurrent/concern/deprecation.rb +34 -0
  60. data/lib/concurrent-ruby/concurrent/concern/dereferenceable.rb +73 -0
  61. data/lib/concurrent-ruby/concurrent/concern/logging.rb +32 -0
  62. data/lib/concurrent-ruby/concurrent/concern/obligation.rb +220 -0
  63. data/lib/concurrent-ruby/concurrent/concern/observable.rb +110 -0
  64. data/lib/concurrent-ruby/concurrent/configuration.rb +188 -0
  65. data/lib/concurrent-ruby/concurrent/constants.rb +8 -0
  66. data/lib/concurrent-ruby/concurrent/dataflow.rb +81 -0
  67. data/lib/concurrent-ruby/concurrent/delay.rb +199 -0
  68. data/lib/concurrent-ruby/concurrent/errors.rb +69 -0
  69. data/lib/concurrent-ruby/concurrent/exchanger.rb +352 -0
  70. data/lib/concurrent-ruby/concurrent/executor/abstract_executor_service.rb +131 -0
  71. data/lib/concurrent-ruby/concurrent/executor/cached_thread_pool.rb +62 -0
  72. data/lib/concurrent-ruby/concurrent/executor/executor_service.rb +185 -0
  73. data/lib/concurrent-ruby/concurrent/executor/fixed_thread_pool.rb +220 -0
  74. data/lib/concurrent-ruby/concurrent/executor/immediate_executor.rb +66 -0
  75. data/lib/concurrent-ruby/concurrent/executor/indirect_immediate_executor.rb +44 -0
  76. data/lib/concurrent-ruby/concurrent/executor/java_executor_service.rb +103 -0
  77. data/lib/concurrent-ruby/concurrent/executor/java_single_thread_executor.rb +30 -0
  78. data/lib/concurrent-ruby/concurrent/executor/java_thread_pool_executor.rb +140 -0
  79. data/lib/concurrent-ruby/concurrent/executor/ruby_executor_service.rb +82 -0
  80. data/lib/concurrent-ruby/concurrent/executor/ruby_single_thread_executor.rb +21 -0
  81. data/lib/concurrent-ruby/concurrent/executor/ruby_thread_pool_executor.rb +368 -0
  82. data/lib/concurrent-ruby/concurrent/executor/safe_task_executor.rb +35 -0
  83. data/lib/concurrent-ruby/concurrent/executor/serial_executor_service.rb +34 -0
  84. data/lib/concurrent-ruby/concurrent/executor/serialized_execution.rb +107 -0
  85. data/lib/concurrent-ruby/concurrent/executor/serialized_execution_delegator.rb +28 -0
  86. data/lib/concurrent-ruby/concurrent/executor/simple_executor_service.rb +100 -0
  87. data/lib/concurrent-ruby/concurrent/executor/single_thread_executor.rb +57 -0
  88. data/lib/concurrent-ruby/concurrent/executor/thread_pool_executor.rb +88 -0
  89. data/lib/concurrent-ruby/concurrent/executor/timer_set.rb +172 -0
  90. data/lib/concurrent-ruby/concurrent/executors.rb +20 -0
  91. data/lib/concurrent-ruby/concurrent/future.rb +141 -0
  92. data/lib/concurrent-ruby/concurrent/hash.rb +59 -0
  93. data/lib/concurrent-ruby/concurrent/immutable_struct.rb +101 -0
  94. data/lib/concurrent-ruby/concurrent/ivar.rb +207 -0
  95. data/lib/concurrent-ruby/concurrent/map.rb +346 -0
  96. data/lib/concurrent-ruby/concurrent/maybe.rb +229 -0
  97. data/lib/concurrent-ruby/concurrent/mutable_struct.rb +239 -0
  98. data/lib/concurrent-ruby/concurrent/mvar.rb +242 -0
  99. data/lib/concurrent-ruby/concurrent/options.rb +42 -0
  100. data/lib/concurrent-ruby/concurrent/promise.rb +580 -0
  101. data/lib/concurrent-ruby/concurrent/promises.rb +2167 -0
  102. data/lib/concurrent-ruby/concurrent/re_include.rb +58 -0
  103. data/lib/concurrent-ruby/concurrent/scheduled_task.rb +331 -0
  104. data/lib/concurrent-ruby/concurrent/set.rb +74 -0
  105. data/lib/concurrent-ruby/concurrent/settable_struct.rb +139 -0
  106. data/lib/concurrent-ruby/concurrent/synchronization/abstract_lockable_object.rb +98 -0
  107. data/lib/concurrent-ruby/concurrent/synchronization/abstract_object.rb +24 -0
  108. data/lib/concurrent-ruby/concurrent/synchronization/abstract_struct.rb +171 -0
  109. data/lib/concurrent-ruby/concurrent/synchronization/condition.rb +60 -0
  110. data/lib/concurrent-ruby/concurrent/synchronization/jruby_lockable_object.rb +13 -0
  111. data/lib/concurrent-ruby/concurrent/synchronization/jruby_object.rb +45 -0
  112. data/lib/concurrent-ruby/concurrent/synchronization/lock.rb +36 -0
  113. data/lib/concurrent-ruby/concurrent/synchronization/lockable_object.rb +72 -0
  114. data/lib/concurrent-ruby/concurrent/synchronization/mri_object.rb +44 -0
  115. data/lib/concurrent-ruby/concurrent/synchronization/mutex_lockable_object.rb +88 -0
  116. data/lib/concurrent-ruby/concurrent/synchronization/object.rb +183 -0
  117. data/lib/concurrent-ruby/concurrent/synchronization/rbx_lockable_object.rb +71 -0
  118. data/lib/concurrent-ruby/concurrent/synchronization/rbx_object.rb +49 -0
  119. data/lib/concurrent-ruby/concurrent/synchronization/truffleruby_object.rb +47 -0
  120. data/lib/concurrent-ruby/concurrent/synchronization/volatile.rb +36 -0
  121. data/lib/concurrent-ruby/concurrent/synchronization.rb +30 -0
  122. data/lib/concurrent-ruby/concurrent/thread_safe/synchronized_delegator.rb +50 -0
  123. data/lib/concurrent-ruby/concurrent/thread_safe/util/adder.rb +74 -0
  124. data/lib/concurrent-ruby/concurrent/thread_safe/util/cheap_lockable.rb +118 -0
  125. data/lib/concurrent-ruby/concurrent/thread_safe/util/data_structures.rb +88 -0
  126. data/lib/concurrent-ruby/concurrent/thread_safe/util/power_of_two_tuple.rb +38 -0
  127. data/lib/concurrent-ruby/concurrent/thread_safe/util/striped64.rb +246 -0
  128. data/lib/concurrent-ruby/concurrent/thread_safe/util/volatile.rb +75 -0
  129. data/lib/concurrent-ruby/concurrent/thread_safe/util/xor_shift_random.rb +50 -0
  130. data/lib/concurrent-ruby/concurrent/thread_safe/util.rb +16 -0
  131. data/lib/concurrent-ruby/concurrent/timer_task.rb +311 -0
  132. data/lib/concurrent-ruby/concurrent/tuple.rb +86 -0
  133. data/lib/concurrent-ruby/concurrent/tvar.rb +221 -0
  134. data/lib/concurrent-ruby/concurrent/utility/engine.rb +56 -0
  135. data/lib/concurrent-ruby/concurrent/utility/monotonic_time.rb +90 -0
  136. data/lib/concurrent-ruby/concurrent/utility/native_extension_loader.rb +79 -0
  137. data/lib/concurrent-ruby/concurrent/utility/native_integer.rb +53 -0
  138. data/lib/concurrent-ruby/concurrent/utility/processor_counter.rb +130 -0
  139. data/lib/concurrent-ruby/concurrent/version.rb +3 -0
  140. data/lib/concurrent-ruby/concurrent-ruby.rb +5 -0
  141. data/lib/concurrent-ruby/concurrent.rb +134 -0
  142. metadata +192 -0
@@ -0,0 +1,66 @@
1
+ require 'thread'
2
+ require 'concurrent/collection/map/non_concurrent_map_backend'
3
+
4
+ module Concurrent
5
+
6
+ # @!visibility private
7
+ module Collection
8
+
9
+ # @!visibility private
10
+ class MriMapBackend < NonConcurrentMapBackend
11
+
12
+ def initialize(options = nil)
13
+ super(options)
14
+ @write_lock = Mutex.new
15
+ end
16
+
17
+ def []=(key, value)
18
+ @write_lock.synchronize { super }
19
+ end
20
+
21
+ def compute_if_absent(key)
22
+ if NULL != (stored_value = @backend.fetch(key, NULL)) # fast non-blocking path for the most likely case
23
+ stored_value
24
+ else
25
+ @write_lock.synchronize { super }
26
+ end
27
+ end
28
+
29
+ def compute_if_present(key)
30
+ @write_lock.synchronize { super }
31
+ end
32
+
33
+ def compute(key)
34
+ @write_lock.synchronize { super }
35
+ end
36
+
37
+ def merge_pair(key, value)
38
+ @write_lock.synchronize { super }
39
+ end
40
+
41
+ def replace_pair(key, old_value, new_value)
42
+ @write_lock.synchronize { super }
43
+ end
44
+
45
+ def replace_if_exists(key, new_value)
46
+ @write_lock.synchronize { super }
47
+ end
48
+
49
+ def get_and_set(key, value)
50
+ @write_lock.synchronize { super }
51
+ end
52
+
53
+ def delete(key)
54
+ @write_lock.synchronize { super }
55
+ end
56
+
57
+ def delete_pair(key, value)
58
+ @write_lock.synchronize { super }
59
+ end
60
+
61
+ def clear
62
+ @write_lock.synchronize { super }
63
+ end
64
+ end
65
+ end
66
+ end
@@ -0,0 +1,140 @@
1
+ require 'concurrent/constants'
2
+
3
+ module Concurrent
4
+
5
+ # @!visibility private
6
+ module Collection
7
+
8
+ # @!visibility private
9
+ class NonConcurrentMapBackend
10
+
11
+ # WARNING: all public methods of the class must operate on the @backend
12
+ # directly without calling each other. This is important because of the
13
+ # SynchronizedMapBackend which uses a non-reentrant mutex for performance
14
+ # reasons.
15
+ def initialize(options = nil)
16
+ @backend = {}
17
+ end
18
+
19
+ def [](key)
20
+ @backend[key]
21
+ end
22
+
23
+ def []=(key, value)
24
+ @backend[key] = value
25
+ end
26
+
27
+ def compute_if_absent(key)
28
+ if NULL != (stored_value = @backend.fetch(key, NULL))
29
+ stored_value
30
+ else
31
+ @backend[key] = yield
32
+ end
33
+ end
34
+
35
+ def replace_pair(key, old_value, new_value)
36
+ if pair?(key, old_value)
37
+ @backend[key] = new_value
38
+ true
39
+ else
40
+ false
41
+ end
42
+ end
43
+
44
+ def replace_if_exists(key, new_value)
45
+ if NULL != (stored_value = @backend.fetch(key, NULL))
46
+ @backend[key] = new_value
47
+ stored_value
48
+ end
49
+ end
50
+
51
+ def compute_if_present(key)
52
+ if NULL != (stored_value = @backend.fetch(key, NULL))
53
+ store_computed_value(key, yield(stored_value))
54
+ end
55
+ end
56
+
57
+ def compute(key)
58
+ store_computed_value(key, yield(@backend[key]))
59
+ end
60
+
61
+ def merge_pair(key, value)
62
+ if NULL == (stored_value = @backend.fetch(key, NULL))
63
+ @backend[key] = value
64
+ else
65
+ store_computed_value(key, yield(stored_value))
66
+ end
67
+ end
68
+
69
+ def get_and_set(key, value)
70
+ stored_value = @backend[key]
71
+ @backend[key] = value
72
+ stored_value
73
+ end
74
+
75
+ def key?(key)
76
+ @backend.key?(key)
77
+ end
78
+
79
+ def delete(key)
80
+ @backend.delete(key)
81
+ end
82
+
83
+ def delete_pair(key, value)
84
+ if pair?(key, value)
85
+ @backend.delete(key)
86
+ true
87
+ else
88
+ false
89
+ end
90
+ end
91
+
92
+ def clear
93
+ @backend.clear
94
+ self
95
+ end
96
+
97
+ def each_pair
98
+ dupped_backend.each_pair do |k, v|
99
+ yield k, v
100
+ end
101
+ self
102
+ end
103
+
104
+ def size
105
+ @backend.size
106
+ end
107
+
108
+ def get_or_default(key, default_value)
109
+ @backend.fetch(key, default_value)
110
+ end
111
+
112
+ alias_method :_get, :[]
113
+ alias_method :_set, :[]=
114
+ private :_get, :_set
115
+ private
116
+ def initialize_copy(other)
117
+ super
118
+ @backend = {}
119
+ self
120
+ end
121
+
122
+ def dupped_backend
123
+ @backend.dup
124
+ end
125
+
126
+ def pair?(key, expected_value)
127
+ NULL != (stored_value = @backend.fetch(key, NULL)) && expected_value.equal?(stored_value)
128
+ end
129
+
130
+ def store_computed_value(key, new_value)
131
+ if new_value.nil?
132
+ @backend.delete(key)
133
+ nil
134
+ else
135
+ @backend[key] = new_value
136
+ end
137
+ end
138
+ end
139
+ end
140
+ end
@@ -0,0 +1,82 @@
1
+ require 'concurrent/collection/map/non_concurrent_map_backend'
2
+
3
+ module Concurrent
4
+
5
+ # @!visibility private
6
+ module Collection
7
+
8
+ # @!visibility private
9
+ class SynchronizedMapBackend < NonConcurrentMapBackend
10
+
11
+ require 'mutex_m'
12
+ include Mutex_m
13
+ # WARNING: Mutex_m is a non-reentrant lock, so the synchronized methods are
14
+ # not allowed to call each other.
15
+
16
+ def [](key)
17
+ synchronize { super }
18
+ end
19
+
20
+ def []=(key, value)
21
+ synchronize { super }
22
+ end
23
+
24
+ def compute_if_absent(key)
25
+ synchronize { super }
26
+ end
27
+
28
+ def compute_if_present(key)
29
+ synchronize { super }
30
+ end
31
+
32
+ def compute(key)
33
+ synchronize { super }
34
+ end
35
+
36
+ def merge_pair(key, value)
37
+ synchronize { super }
38
+ end
39
+
40
+ def replace_pair(key, old_value, new_value)
41
+ synchronize { super }
42
+ end
43
+
44
+ def replace_if_exists(key, new_value)
45
+ synchronize { super }
46
+ end
47
+
48
+ def get_and_set(key, value)
49
+ synchronize { super }
50
+ end
51
+
52
+ def key?(key)
53
+ synchronize { super }
54
+ end
55
+
56
+ def delete(key)
57
+ synchronize { super }
58
+ end
59
+
60
+ def delete_pair(key, value)
61
+ synchronize { super }
62
+ end
63
+
64
+ def clear
65
+ synchronize { super }
66
+ end
67
+
68
+ def size
69
+ synchronize { super }
70
+ end
71
+
72
+ def get_or_default(key, default_value)
73
+ synchronize { super }
74
+ end
75
+
76
+ private
77
+ def dupped_backend
78
+ synchronize { super }
79
+ end
80
+ end
81
+ end
82
+ end
@@ -0,0 +1,14 @@
1
+ module Concurrent
2
+
3
+ # @!visibility private
4
+ module Collection
5
+
6
+ # @!visibility private
7
+ class TruffleRubyMapBackend < TruffleRuby::ConcurrentMap
8
+ def initialize(options = nil)
9
+ options ||= {}
10
+ super(initial_capacity: options[:initial_capacity], load_factor: options[:load_factor])
11
+ end
12
+ end
13
+ end
14
+ end
@@ -0,0 +1,143 @@
1
+ require 'concurrent/utility/engine'
2
+ require 'concurrent/collection/java_non_concurrent_priority_queue'
3
+ require 'concurrent/collection/ruby_non_concurrent_priority_queue'
4
+
5
+ module Concurrent
6
+ module Collection
7
+
8
+ # @!visibility private
9
+ # @!macro internal_implementation_note
10
+ NonConcurrentPriorityQueueImplementation = case
11
+ when Concurrent.on_jruby?
12
+ JavaNonConcurrentPriorityQueue
13
+ else
14
+ RubyNonConcurrentPriorityQueue
15
+ end
16
+ private_constant :NonConcurrentPriorityQueueImplementation
17
+
18
+ # @!macro priority_queue
19
+ #
20
+ # A queue collection in which the elements are sorted based on their
21
+ # comparison (spaceship) operator `<=>`. Items are added to the queue
22
+ # at a position relative to their priority. On removal the element
23
+ # with the "highest" priority is removed. By default the sort order is
24
+ # from highest to lowest, but a lowest-to-highest sort order can be
25
+ # set on construction.
26
+ #
27
+ # The API is based on the `Queue` class from the Ruby standard library.
28
+ #
29
+ # The pure Ruby implementation, `RubyNonConcurrentPriorityQueue` uses a heap algorithm
30
+ # stored in an array. The algorithm is based on the work of Robert Sedgewick
31
+ # and Kevin Wayne.
32
+ #
33
+ # The JRuby native implementation is a thin wrapper around the standard
34
+ # library `java.util.NonConcurrentPriorityQueue`.
35
+ #
36
+ # When running under JRuby the class `NonConcurrentPriorityQueue` extends `JavaNonConcurrentPriorityQueue`.
37
+ # When running under all other interpreters it extends `RubyNonConcurrentPriorityQueue`.
38
+ #
39
+ # @note This implementation is *not* thread safe.
40
+ #
41
+ # @see http://en.wikipedia.org/wiki/Priority_queue
42
+ # @see http://ruby-doc.org/stdlib-2.0.0/libdoc/thread/rdoc/Queue.html
43
+ #
44
+ # @see http://algs4.cs.princeton.edu/24pq/index.php#2.6
45
+ # @see http://algs4.cs.princeton.edu/24pq/MaxPQ.java.html
46
+ #
47
+ # @see http://docs.oracle.com/javase/7/docs/api/java/util/PriorityQueue.html
48
+ #
49
+ # @!visibility private
50
+ class NonConcurrentPriorityQueue < NonConcurrentPriorityQueueImplementation
51
+
52
+ alias_method :has_priority?, :include?
53
+
54
+ alias_method :size, :length
55
+
56
+ alias_method :deq, :pop
57
+ alias_method :shift, :pop
58
+
59
+ alias_method :<<, :push
60
+ alias_method :enq, :push
61
+
62
+ # @!method initialize(opts = {})
63
+ # @!macro priority_queue_method_initialize
64
+ #
65
+ # Create a new priority queue with no items.
66
+ #
67
+ # @param [Hash] opts the options for creating the queue
68
+ # @option opts [Symbol] :order (:max) dictates the order in which items are
69
+ # stored: from highest to lowest when `:max` or `:high`; from lowest to
70
+ # highest when `:min` or `:low`
71
+
72
+ # @!method clear
73
+ # @!macro priority_queue_method_clear
74
+ #
75
+ # Removes all of the elements from this priority queue.
76
+
77
+ # @!method delete(item)
78
+ # @!macro priority_queue_method_delete
79
+ #
80
+ # Deletes all items from `self` that are equal to `item`.
81
+ #
82
+ # @param [Object] item the item to be removed from the queue
83
+ # @return [Object] true if the item is found else false
84
+
85
+ # @!method empty?
86
+ # @!macro priority_queue_method_empty
87
+ #
88
+ # Returns `true` if `self` contains no elements.
89
+ #
90
+ # @return [Boolean] true if there are no items in the queue else false
91
+
92
+ # @!method include?(item)
93
+ # @!macro priority_queue_method_include
94
+ #
95
+ # Returns `true` if the given item is present in `self` (that is, if any
96
+ # element == `item`), otherwise returns false.
97
+ #
98
+ # @param [Object] item the item to search for
99
+ #
100
+ # @return [Boolean] true if the item is found else false
101
+
102
+ # @!method length
103
+ # @!macro priority_queue_method_length
104
+ #
105
+ # The current length of the queue.
106
+ #
107
+ # @return [Fixnum] the number of items in the queue
108
+
109
+ # @!method peek
110
+ # @!macro priority_queue_method_peek
111
+ #
112
+ # Retrieves, but does not remove, the head of this queue, or returns `nil`
113
+ # if this queue is empty.
114
+ #
115
+ # @return [Object] the head of the queue or `nil` when empty
116
+
117
+ # @!method pop
118
+ # @!macro priority_queue_method_pop
119
+ #
120
+ # Retrieves and removes the head of this queue, or returns `nil` if this
121
+ # queue is empty.
122
+ #
123
+ # @return [Object] the head of the queue or `nil` when empty
124
+
125
+ # @!method push(item)
126
+ # @!macro priority_queue_method_push
127
+ #
128
+ # Inserts the specified element into this priority queue.
129
+ #
130
+ # @param [Object] item the item to insert onto the queue
131
+
132
+ # @!method self.from_list(list, opts = {})
133
+ # @!macro priority_queue_method_from_list
134
+ #
135
+ # Create a new priority queue from the given list.
136
+ #
137
+ # @param [Enumerable] list the list to build the queue from
138
+ # @param [Hash] opts the options for creating the queue
139
+ #
140
+ # @return [NonConcurrentPriorityQueue] the newly created and populated queue
141
+ end
142
+ end
143
+ end
@@ -0,0 +1,160 @@
1
+ module Concurrent
2
+ module Collection
3
+
4
+ # @!macro priority_queue
5
+ #
6
+ # @!visibility private
7
+ # @!macro internal_implementation_note
8
+ class RubyNonConcurrentPriorityQueue
9
+
10
+ # @!macro priority_queue_method_initialize
11
+ def initialize(opts = {})
12
+ order = opts.fetch(:order, :max)
13
+ @comparator = [:min, :low].include?(order) ? -1 : 1
14
+ clear
15
+ end
16
+
17
+ # @!macro priority_queue_method_clear
18
+ def clear
19
+ @queue = [nil]
20
+ @length = 0
21
+ true
22
+ end
23
+
24
+ # @!macro priority_queue_method_delete
25
+ def delete(item)
26
+ return false if empty?
27
+ original_length = @length
28
+ k = 1
29
+ while k <= @length
30
+ if @queue[k] == item
31
+ swap(k, @length)
32
+ @length -= 1
33
+ sink(k) || swim(k)
34
+ @queue.pop
35
+ else
36
+ k += 1
37
+ end
38
+ end
39
+ @length != original_length
40
+ end
41
+
42
+ # @!macro priority_queue_method_empty
43
+ def empty?
44
+ size == 0
45
+ end
46
+
47
+ # @!macro priority_queue_method_include
48
+ def include?(item)
49
+ @queue.include?(item)
50
+ end
51
+ alias_method :has_priority?, :include?
52
+
53
+ # @!macro priority_queue_method_length
54
+ def length
55
+ @length
56
+ end
57
+ alias_method :size, :length
58
+
59
+ # @!macro priority_queue_method_peek
60
+ def peek
61
+ empty? ? nil : @queue[1]
62
+ end
63
+
64
+ # @!macro priority_queue_method_pop
65
+ def pop
66
+ return nil if empty?
67
+ max = @queue[1]
68
+ swap(1, @length)
69
+ @length -= 1
70
+ sink(1)
71
+ @queue.pop
72
+ max
73
+ end
74
+ alias_method :deq, :pop
75
+ alias_method :shift, :pop
76
+
77
+ # @!macro priority_queue_method_push
78
+ def push(item)
79
+ raise ArgumentError.new('cannot enqueue nil') if item.nil?
80
+ @length += 1
81
+ @queue << item
82
+ swim(@length)
83
+ true
84
+ end
85
+ alias_method :<<, :push
86
+ alias_method :enq, :push
87
+
88
+ # @!macro priority_queue_method_from_list
89
+ def self.from_list(list, opts = {})
90
+ queue = new(opts)
91
+ list.each{|item| queue << item }
92
+ queue
93
+ end
94
+
95
+ private
96
+
97
+ # Exchange the values at the given indexes within the internal array.
98
+ #
99
+ # @param [Integer] x the first index to swap
100
+ # @param [Integer] y the second index to swap
101
+ #
102
+ # @!visibility private
103
+ def swap(x, y)
104
+ temp = @queue[x]
105
+ @queue[x] = @queue[y]
106
+ @queue[y] = temp
107
+ end
108
+
109
+ # Are the items at the given indexes ordered based on the priority
110
+ # order specified at construction?
111
+ #
112
+ # @param [Integer] x the first index from which to retrieve a comparable value
113
+ # @param [Integer] y the second index from which to retrieve a comparable value
114
+ #
115
+ # @return [Boolean] true if the two elements are in the correct priority order
116
+ # else false
117
+ #
118
+ # @!visibility private
119
+ def ordered?(x, y)
120
+ (@queue[x] <=> @queue[y]) == @comparator
121
+ end
122
+
123
+ # Percolate down to maintain heap invariant.
124
+ #
125
+ # @param [Integer] k the index at which to start the percolation
126
+ #
127
+ # @!visibility private
128
+ def sink(k)
129
+ success = false
130
+
131
+ while (j = (2 * k)) <= @length do
132
+ j += 1 if j < @length && ! ordered?(j, j+1)
133
+ break if ordered?(k, j)
134
+ swap(k, j)
135
+ success = true
136
+ k = j
137
+ end
138
+
139
+ success
140
+ end
141
+
142
+ # Percolate up to maintain heap invariant.
143
+ #
144
+ # @param [Integer] k the index at which to start the percolation
145
+ #
146
+ # @!visibility private
147
+ def swim(k)
148
+ success = false
149
+
150
+ while k > 1 && ! ordered?(k/2, k) do
151
+ swap(k, k/2)
152
+ k = k/2
153
+ success = true
154
+ end
155
+
156
+ success
157
+ end
158
+ end
159
+ end
160
+ end
@@ -0,0 +1,34 @@
1
+ require 'concurrent/concern/logging'
2
+
3
+ module Concurrent
4
+ module Concern
5
+
6
+ # @!visibility private
7
+ # @!macro internal_implementation_note
8
+ module Deprecation
9
+ # TODO require additional parameter: a version. Display when it'll be removed based on that. Error if not removed.
10
+ include Concern::Logging
11
+
12
+ def deprecated(message, strip = 2)
13
+ caller_line = caller(strip).first if strip > 0
14
+ klass = if Module === self
15
+ self
16
+ else
17
+ self.class
18
+ end
19
+ message = if strip > 0
20
+ format("[DEPRECATED] %s\ncalled on: %s", message, caller_line)
21
+ else
22
+ format('[DEPRECATED] %s', message)
23
+ end
24
+ log WARN, klass.to_s, message
25
+ end
26
+
27
+ def deprecated_method(old_name, new_name)
28
+ deprecated "`#{old_name}` is deprecated and it'll removed in next release, use `#{new_name}` instead", 3
29
+ end
30
+
31
+ extend self
32
+ end
33
+ end
34
+ end