concurrent-ruby 0.7.0.rc0-x64-mingw32

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 (95) hide show
  1. checksums.yaml +15 -0
  2. data/LICENSE.txt +21 -0
  3. data/README.md +166 -0
  4. data/ext/concurrent_ruby_ext/atomic_reference.c +78 -0
  5. data/ext/concurrent_ruby_ext/atomic_reference.h +12 -0
  6. data/ext/concurrent_ruby_ext/extconf.rb +59 -0
  7. data/ext/concurrent_ruby_ext/rb_concurrent.c +28 -0
  8. data/lib/2.0/concurrent_ruby_ext.so +0 -0
  9. data/lib/concurrent.rb +45 -0
  10. data/lib/concurrent/actress.rb +221 -0
  11. data/lib/concurrent/actress/ad_hoc.rb +20 -0
  12. data/lib/concurrent/actress/context.rb +98 -0
  13. data/lib/concurrent/actress/core.rb +228 -0
  14. data/lib/concurrent/actress/core_delegations.rb +42 -0
  15. data/lib/concurrent/actress/envelope.rb +41 -0
  16. data/lib/concurrent/actress/errors.rb +14 -0
  17. data/lib/concurrent/actress/reference.rb +64 -0
  18. data/lib/concurrent/actress/type_check.rb +48 -0
  19. data/lib/concurrent/agent.rb +232 -0
  20. data/lib/concurrent/async.rb +319 -0
  21. data/lib/concurrent/atomic.rb +46 -0
  22. data/lib/concurrent/atomic/atomic_boolean.rb +157 -0
  23. data/lib/concurrent/atomic/atomic_fixnum.rb +162 -0
  24. data/lib/concurrent/atomic/condition.rb +67 -0
  25. data/lib/concurrent/atomic/copy_on_notify_observer_set.rb +118 -0
  26. data/lib/concurrent/atomic/copy_on_write_observer_set.rb +117 -0
  27. data/lib/concurrent/atomic/count_down_latch.rb +116 -0
  28. data/lib/concurrent/atomic/cyclic_barrier.rb +106 -0
  29. data/lib/concurrent/atomic/event.rb +98 -0
  30. data/lib/concurrent/atomic/thread_local_var.rb +117 -0
  31. data/lib/concurrent/atomic_reference/concurrent_update_error.rb +7 -0
  32. data/lib/concurrent/atomic_reference/delegated_update.rb +28 -0
  33. data/lib/concurrent/atomic_reference/direct_update.rb +28 -0
  34. data/lib/concurrent/atomic_reference/jruby.rb +8 -0
  35. data/lib/concurrent/atomic_reference/mutex_atomic.rb +47 -0
  36. data/lib/concurrent/atomic_reference/numeric_cas_wrapper.rb +24 -0
  37. data/lib/concurrent/atomic_reference/rbx.rb +16 -0
  38. data/lib/concurrent/atomic_reference/ruby.rb +16 -0
  39. data/lib/concurrent/atomics.rb +10 -0
  40. data/lib/concurrent/channel/buffered_channel.rb +85 -0
  41. data/lib/concurrent/channel/channel.rb +41 -0
  42. data/lib/concurrent/channel/unbuffered_channel.rb +34 -0
  43. data/lib/concurrent/channel/waitable_list.rb +40 -0
  44. data/lib/concurrent/channels.rb +5 -0
  45. data/lib/concurrent/collection/blocking_ring_buffer.rb +71 -0
  46. data/lib/concurrent/collection/priority_queue.rb +305 -0
  47. data/lib/concurrent/collection/ring_buffer.rb +59 -0
  48. data/lib/concurrent/collections.rb +3 -0
  49. data/lib/concurrent/configuration.rb +158 -0
  50. data/lib/concurrent/dataflow.rb +91 -0
  51. data/lib/concurrent/delay.rb +112 -0
  52. data/lib/concurrent/dereferenceable.rb +101 -0
  53. data/lib/concurrent/errors.rb +30 -0
  54. data/lib/concurrent/exchanger.rb +34 -0
  55. data/lib/concurrent/executor/cached_thread_pool.rb +44 -0
  56. data/lib/concurrent/executor/executor.rb +229 -0
  57. data/lib/concurrent/executor/fixed_thread_pool.rb +33 -0
  58. data/lib/concurrent/executor/immediate_executor.rb +16 -0
  59. data/lib/concurrent/executor/java_cached_thread_pool.rb +31 -0
  60. data/lib/concurrent/executor/java_fixed_thread_pool.rb +33 -0
  61. data/lib/concurrent/executor/java_single_thread_executor.rb +21 -0
  62. data/lib/concurrent/executor/java_thread_pool_executor.rb +187 -0
  63. data/lib/concurrent/executor/per_thread_executor.rb +24 -0
  64. data/lib/concurrent/executor/ruby_cached_thread_pool.rb +29 -0
  65. data/lib/concurrent/executor/ruby_fixed_thread_pool.rb +32 -0
  66. data/lib/concurrent/executor/ruby_single_thread_executor.rb +73 -0
  67. data/lib/concurrent/executor/ruby_thread_pool_executor.rb +286 -0
  68. data/lib/concurrent/executor/ruby_thread_pool_worker.rb +72 -0
  69. data/lib/concurrent/executor/safe_task_executor.rb +35 -0
  70. data/lib/concurrent/executor/serialized_execution.rb +90 -0
  71. data/lib/concurrent/executor/single_thread_executor.rb +35 -0
  72. data/lib/concurrent/executor/thread_pool_executor.rb +68 -0
  73. data/lib/concurrent/executor/timer_set.rb +143 -0
  74. data/lib/concurrent/executors.rb +9 -0
  75. data/lib/concurrent/future.rb +124 -0
  76. data/lib/concurrent/ivar.rb +111 -0
  77. data/lib/concurrent/logging.rb +17 -0
  78. data/lib/concurrent/mvar.rb +200 -0
  79. data/lib/concurrent/obligation.rb +171 -0
  80. data/lib/concurrent/observable.rb +40 -0
  81. data/lib/concurrent/options_parser.rb +46 -0
  82. data/lib/concurrent/promise.rb +169 -0
  83. data/lib/concurrent/scheduled_task.rb +78 -0
  84. data/lib/concurrent/supervisor.rb +343 -0
  85. data/lib/concurrent/timer_task.rb +341 -0
  86. data/lib/concurrent/tvar.rb +252 -0
  87. data/lib/concurrent/utilities.rb +3 -0
  88. data/lib/concurrent/utility/processor_count.rb +150 -0
  89. data/lib/concurrent/utility/timeout.rb +35 -0
  90. data/lib/concurrent/utility/timer.rb +21 -0
  91. data/lib/concurrent/version.rb +3 -0
  92. data/lib/concurrent_ruby.rb +1 -0
  93. data/lib/concurrent_ruby_ext.so +0 -0
  94. data/lib/extension_helper.rb +9 -0
  95. metadata +141 -0
@@ -0,0 +1,7 @@
1
+ module Concurrent
2
+
3
+ class ConcurrentUpdateError < ThreadError
4
+ # frozen pre-allocated backtrace to speed ConcurrentUpdateError
5
+ CONC_UP_ERR_BACKTRACE = ['backtrace elided; set verbose to enable'].freeze
6
+ end
7
+ end
@@ -0,0 +1,28 @@
1
+ require 'concurrent/atomic_reference/concurrent_update_error'
2
+
3
+ module Concurrent
4
+
5
+ # Define update methods that delegate to @ref field
6
+ class Atomic
7
+ # Pass the current value to the given block, replacing it
8
+ # with the block's result. May retry if the value changes
9
+ # during the block's execution.
10
+ def update
11
+ true until @ref.compare_and_set(old_value = @ref.get, new_value = yield(old_value))
12
+ new_value
13
+ end
14
+
15
+ def try_update
16
+ old_value = @ref.get
17
+ new_value = yield old_value
18
+ unless @ref.compare_and_set(old_value, new_value)
19
+ if $VERBOSE
20
+ raise ConcurrentUpdateError, "Update failed"
21
+ else
22
+ raise ConcurrentUpdateError, "Update failed", ConcurrentUpdateError::CONC_UP_ERR_BACKTRACE
23
+ end
24
+ end
25
+ new_value
26
+ end
27
+ end
28
+ end
@@ -0,0 +1,28 @@
1
+ require 'concurrent/atomic_reference/concurrent_update_error'
2
+
3
+ module Concurrent
4
+
5
+ # Define update methods that use direct paths
6
+ module AtomicDirectUpdate
7
+ # Pass the current value to the given block, replacing it
8
+ # with the block's result. May retry if the value changes
9
+ # during the block's execution.
10
+ def update
11
+ true until compare_and_set(old_value = get, new_value = yield(old_value))
12
+ new_value
13
+ end
14
+
15
+ def try_update
16
+ old_value = get
17
+ new_value = yield old_value
18
+ unless compare_and_set(old_value, new_value)
19
+ if $VERBOSE
20
+ raise ConcurrentUpdateError, "Update failed"
21
+ else
22
+ raise ConcurrentUpdateError, "Update failed", ConcurrentUpdateError::CONC_UP_ERR_BACKTRACE
23
+ end
24
+ end
25
+ new_value
26
+ end
27
+ end
28
+ end
@@ -0,0 +1,8 @@
1
+ require 'concurrent_ruby_ext'
2
+ require 'concurrent/atomic_reference/direct_update'
3
+
4
+ module Concurrent
5
+ class JavaAtomic
6
+ include Concurrent::AtomicDirectUpdate
7
+ end
8
+ end
@@ -0,0 +1,47 @@
1
+ require 'thread'
2
+ require 'concurrent/atomic_reference/direct_update'
3
+ require 'concurrent/atomic_reference/numeric_cas_wrapper'
4
+
5
+ module Concurrent
6
+
7
+ # Portable/generic (but not very memory or scheduling-efficient) fallback
8
+ class MutexAtomic #:nodoc: all
9
+ include Concurrent::AtomicDirectUpdate
10
+ include Concurrent::AtomicNumericCompareAndSetWrapper
11
+
12
+ def initialize(value = nil)
13
+ @mutex = Mutex.new
14
+ @value = value
15
+ end
16
+
17
+ def get
18
+ @mutex.synchronize { @value }
19
+ end
20
+ alias value get
21
+
22
+ def set(new_value)
23
+ @mutex.synchronize { @value = new_value }
24
+ end
25
+ alias value= set
26
+
27
+ def get_and_set(new_value)
28
+ @mutex.synchronize do
29
+ old_value = @value
30
+ @value = new_value
31
+ old_value
32
+ end
33
+ end
34
+ alias swap get_and_set
35
+
36
+ def _compare_and_set(old_value, new_value)
37
+ return false unless @mutex.try_lock
38
+ begin
39
+ return false unless @value.equal? old_value
40
+ @value = new_value
41
+ ensure
42
+ @mutex.unlock
43
+ end
44
+ true
45
+ end
46
+ end
47
+ end
@@ -0,0 +1,24 @@
1
+ module Concurrent
2
+
3
+ module AtomicNumericCompareAndSetWrapper
4
+ #alias _compare_and_set compare_and_set
5
+
6
+ def compare_and_set(expected, new)
7
+ if expected.kind_of? Numeric
8
+ while true
9
+ old = get
10
+
11
+ return false unless old.kind_of? Numeric
12
+
13
+ return false unless old == expected
14
+
15
+ result = _compare_and_set(old, new)
16
+ return result if result
17
+ end
18
+ else
19
+ _compare_and_set(expected, new)
20
+ end
21
+ end
22
+ alias compare_and_swap compare_and_set
23
+ end
24
+ end
@@ -0,0 +1,16 @@
1
+ require 'concurrent/atomic_reference/direct_update'
2
+ require 'concurrent/atomic_reference/numeric_cas_wrapper'
3
+
4
+ module Concurrent
5
+
6
+ # extend Rubinius's version adding aliases and numeric logic
7
+ class RbxAtomic < Rubinius::AtomicReference
8
+ alias _compare_and_set compare_and_set
9
+ include Concurrent::AtomicDirectUpdate
10
+ include Concurrent::AtomicNumericCompareAndSetWrapper
11
+
12
+ alias value get
13
+ alias value= set
14
+ alias swap get_and_set
15
+ end
16
+ end
@@ -0,0 +1,16 @@
1
+ begin
2
+ require 'concurrent_ruby_ext'
3
+ rescue LoadError
4
+ # may be a Windows cross-compiled native gem
5
+ require "#{RUBY_VERSION[0..2]}/concurrent_ruby_ext"
6
+ end
7
+
8
+ require 'concurrent/atomic_reference/direct_update'
9
+ require 'concurrent/atomic_reference/numeric_cas_wrapper'
10
+
11
+ module Concurrent
12
+ class CAtomic
13
+ include Concurrent::AtomicDirectUpdate
14
+ include Concurrent::AtomicNumericCompareAndSetWrapper
15
+ end
16
+ end
@@ -0,0 +1,10 @@
1
+ require 'concurrent/atomic'
2
+ require 'concurrent/atomic/atomic_boolean'
3
+ require 'concurrent/atomic/atomic_fixnum'
4
+ require 'concurrent/atomic/condition'
5
+ require 'concurrent/atomic/copy_on_notify_observer_set'
6
+ require 'concurrent/atomic/copy_on_write_observer_set'
7
+ require 'concurrent/atomic/cyclic_barrier'
8
+ require 'concurrent/atomic/count_down_latch'
9
+ require 'concurrent/atomic/event'
10
+ require 'concurrent/atomic/thread_local_var'
@@ -0,0 +1,85 @@
1
+ require 'concurrent/atomic/condition'
2
+
3
+ require_relative 'waitable_list'
4
+
5
+ module Concurrent
6
+ class BufferedChannel
7
+
8
+ def initialize(size)
9
+ @mutex = Mutex.new
10
+ @condition = Condition.new
11
+ @buffer_condition = Condition.new
12
+
13
+ @probe_set = WaitableList.new
14
+ @buffer = RingBuffer.new(size)
15
+ end
16
+
17
+ def probe_set_size
18
+ @probe_set.size
19
+ end
20
+
21
+ def buffer_queue_size
22
+ @mutex.synchronize { @buffer.count }
23
+ end
24
+
25
+ def push(value)
26
+ until set_probe_or_push_into_buffer(value)
27
+ end
28
+ end
29
+
30
+ def pop
31
+ probe = Channel::Probe.new
32
+ select(probe)
33
+ probe.value
34
+ end
35
+
36
+ def select(probe)
37
+ @mutex.synchronize do
38
+
39
+ if @buffer.empty?
40
+ @probe_set.put(probe)
41
+ true
42
+ else
43
+ shift_buffer if probe.set_unless_assigned(peek_buffer, self)
44
+ end
45
+
46
+ end
47
+ end
48
+
49
+ def remove_probe(probe)
50
+ @probe_set.delete(probe)
51
+ end
52
+
53
+ private
54
+
55
+ def push_into_buffer(value)
56
+ @buffer_condition.wait(@mutex) while @buffer.full?
57
+ @buffer.offer value
58
+ @buffer_condition.broadcast
59
+ end
60
+
61
+ def peek_buffer
62
+ @buffer_condition.wait(@mutex) while @buffer.empty?
63
+ @buffer.peek
64
+ end
65
+
66
+ def shift_buffer
67
+ @buffer_condition.wait(@mutex) while @buffer.empty?
68
+ result = @buffer.poll
69
+ @buffer_condition.broadcast
70
+ result
71
+ end
72
+
73
+ def set_probe_or_push_into_buffer(value)
74
+ @mutex.synchronize do
75
+ if @probe_set.empty?
76
+ push_into_buffer(value)
77
+ true
78
+ else
79
+ @probe_set.take.set_unless_assigned(value, self)
80
+ end
81
+ end
82
+ end
83
+
84
+ end
85
+ end
@@ -0,0 +1,41 @@
1
+ require 'concurrent/ivar'
2
+
3
+ module Concurrent
4
+ module Channel
5
+
6
+ class Probe < Concurrent::IVar
7
+
8
+ def initialize(value = NO_VALUE, opts = {})
9
+ super(value, opts)
10
+ end
11
+
12
+ def set_unless_assigned(value, channel)
13
+ mutex.synchronize do
14
+ return false if [:fulfilled, :rejected].include? @state
15
+
16
+ set_state(true, [value, channel], nil)
17
+ event.set
18
+ true
19
+ end
20
+ end
21
+
22
+ alias_method :composite_value, :value
23
+
24
+ def value
25
+ composite_value.nil? ? nil : composite_value[0]
26
+ end
27
+
28
+ def channel
29
+ composite_value.nil? ? nil : composite_value[1]
30
+ end
31
+ end
32
+
33
+ def self.select(*channels)
34
+ probe = Probe.new
35
+ channels.each { |channel| channel.select(probe) }
36
+ result = probe.composite_value
37
+ channels.each { |channel| channel.remove_probe(probe) }
38
+ result
39
+ end
40
+ end
41
+ end
@@ -0,0 +1,34 @@
1
+ require_relative 'waitable_list'
2
+
3
+ module Concurrent
4
+ class UnbufferedChannel
5
+
6
+ def initialize
7
+ @probe_set = WaitableList.new
8
+ end
9
+
10
+ def probe_set_size
11
+ @probe_set.size
12
+ end
13
+
14
+ def push(value)
15
+ until @probe_set.take.set_unless_assigned(value, self)
16
+ end
17
+ end
18
+
19
+ def pop
20
+ probe = Channel::Probe.new
21
+ select(probe)
22
+ probe.value
23
+ end
24
+
25
+ def select(probe)
26
+ @probe_set.put(probe)
27
+ end
28
+
29
+ def remove_probe(probe)
30
+ @probe_set.delete(probe)
31
+ end
32
+
33
+ end
34
+ end
@@ -0,0 +1,40 @@
1
+ require 'concurrent/atomic/condition'
2
+
3
+ module Concurrent
4
+ class WaitableList
5
+
6
+ def initialize
7
+ @mutex = Mutex.new
8
+ @condition = Condition.new
9
+
10
+ @list = []
11
+ end
12
+
13
+ def size
14
+ @mutex.synchronize { @list.size }
15
+ end
16
+
17
+ def empty?
18
+ @mutex.synchronize { @list.empty? }
19
+ end
20
+
21
+ def put(value)
22
+ @mutex.synchronize do
23
+ @list << value
24
+ @condition.signal
25
+ end
26
+ end
27
+
28
+ def delete(value)
29
+ @mutex.synchronize { @list.delete(value) }
30
+ end
31
+
32
+ def take
33
+ @mutex.synchronize do
34
+ @condition.wait(@mutex) while @list.empty?
35
+ @list.shift
36
+ end
37
+ end
38
+
39
+ end
40
+ end
@@ -0,0 +1,5 @@
1
+ require 'concurrent/collections'
2
+
3
+ require 'concurrent/channel/channel'
4
+ require 'concurrent/channel/unbuffered_channel'
5
+ require 'concurrent/channel/buffered_channel'
@@ -0,0 +1,71 @@
1
+ require 'concurrent/atomic/condition'
2
+
3
+ module Concurrent
4
+ class BlockingRingBuffer
5
+
6
+ def initialize(capacity)
7
+ @buffer = RingBuffer.new(capacity)
8
+ @first = @last = 0
9
+ @count = 0
10
+ @mutex = Mutex.new
11
+ @condition = Condition.new
12
+ end
13
+
14
+ # @return [Integer] the capacity of the buffer
15
+ def capacity
16
+ @mutex.synchronize { @buffer.capacity }
17
+ end
18
+
19
+ # @return [Integer] the number of elements currently in the buffer
20
+ def count
21
+ @mutex.synchronize { @buffer.count }
22
+ end
23
+
24
+ # @return [Boolean] true if buffer is empty, false otherwise
25
+ def empty?
26
+ @mutex.synchronize { @buffer.empty? }
27
+ end
28
+
29
+ # @return [Boolean] true if buffer is full, false otherwise
30
+ def full?
31
+ @mutex.synchronize { @buffer.full? }
32
+ end
33
+
34
+ # @param [Object] value the value to be inserted
35
+ # @return [Boolean] true if value has been inserted, false otherwise
36
+ def put(value)
37
+ @mutex.synchronize do
38
+ wait_while_full
39
+ @buffer.offer(value)
40
+ @condition.signal
41
+ true
42
+ end
43
+ end
44
+
45
+ # @return [Object] the first available value and removes it from the buffer. If buffer is empty it blocks until an element is available
46
+ def take
47
+ @mutex.synchronize do
48
+ wait_while_empty
49
+ result = @buffer.poll
50
+ @condition.signal
51
+ result
52
+ end
53
+ end
54
+
55
+ # @return [Object] the first available value and without removing it from the buffer. If buffer is empty returns nil
56
+ def peek
57
+ @mutex.synchronize { @buffer.peek }
58
+ end
59
+
60
+ private
61
+
62
+ def wait_while_full
63
+ @condition.wait(@mutex) while @buffer.full?
64
+ end
65
+
66
+ def wait_while_empty
67
+ @condition.wait(@mutex) while @buffer.empty?
68
+ end
69
+
70
+ end
71
+ end