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,46 @@
1
+ require 'concurrent/atomic_reference/concurrent_update_error'
2
+ require 'concurrent/atomic_reference/mutex_atomic'
3
+
4
+ begin
5
+ # force fallback impl with FORCE_ATOMIC_FALLBACK=1
6
+ if /[^0fF]/ =~ ENV['FORCE_ATOMIC_FALLBACK']
7
+ ruby_engine = 'mutex_atomic'
8
+ else
9
+ ruby_engine = defined?(RUBY_ENGINE)? RUBY_ENGINE : 'ruby'
10
+ end
11
+
12
+ require "concurrent/atomic_reference/#{ruby_engine}"
13
+ rescue LoadError
14
+ warn 'Compiled extensions not installed, pure Ruby Atomic will be used.'
15
+ end
16
+
17
+ if defined? Concurrent::JavaAtomic
18
+
19
+ class Concurrent::Atomic < Concurrent::JavaAtomic
20
+ end
21
+
22
+ elsif defined? Concurrent::CAtomic
23
+
24
+ class Concurrent::Atomic < Concurrent::CAtomic
25
+ end
26
+
27
+ elsif defined? Concurrent::RbxAtomic
28
+
29
+ class Concurrent::Atomic < Concurrent::RbxAtomic
30
+ end
31
+
32
+ else
33
+
34
+ class Concurrent::Atomic < Concurrent::MutexAtomic
35
+ end
36
+ end
37
+
38
+ class Atomic < Concurrent::Atomic
39
+
40
+ ConcurrentUpdateError = Class.new(Concurrent::ConcurrentUpdateError)
41
+
42
+ def initialize(*args)
43
+ warn "[DEPRECATED] Please use Concurrent::Atomic instead."
44
+ super
45
+ end
46
+ end
@@ -0,0 +1,157 @@
1
+ module Concurrent
2
+
3
+ # @!macro [attach] atomic_boolean
4
+ #
5
+ # A boolean value that can be updated atomically. Reads and writes to an atomic
6
+ # boolean and thread-safe and guaranteed to succeed. Reads and writes may block
7
+ # briefly but no explicit locking is required.
8
+ #
9
+ # @since 0.6.0
10
+ # @see http://docs.oracle.com/javase/7/docs/api/java/util/concurrent/atomic/AtomicBoolean.html java.util.concurrent.atomic.AtomicBoolean
11
+ class MutexAtomicBoolean
12
+
13
+ # @!macro [attach] atomic_boolean_method_initialize
14
+ #
15
+ # Creates a new `AtomicBoolean` with the given initial value.
16
+ #
17
+ # @param [Boolean] initial the initial value
18
+ def initialize(initial = false)
19
+ @value = !!initial
20
+ @mutex = Mutex.new
21
+ end
22
+
23
+ # @!macro [attach] atomic_boolean_method_value
24
+ #
25
+ # Retrieves the current `Boolean` value.
26
+ #
27
+ # @return [Boolean] the current value
28
+ def value
29
+ @mutex.lock
30
+ @value
31
+ ensure
32
+ @mutex.unlock
33
+ end
34
+
35
+ # @!macro [attach] atomic_boolean_method_value_eq
36
+ #
37
+ # Explicitly sets the value.
38
+ #
39
+ # @param [Boolean] value the new value to be set
40
+ #
41
+ # @return [Boolean] the current value
42
+ def value=(value)
43
+ @mutex.lock
44
+ @value = !!value
45
+ @value
46
+ ensure
47
+ @mutex.unlock
48
+ end
49
+
50
+ # @!macro [attach] atomic_boolean_method_is_true
51
+ #
52
+ # Is the current value `true`?
53
+ #
54
+ # @return [Boolean] true if the current value is `true`, else false
55
+ def true?
56
+ @mutex.lock
57
+ @value
58
+ ensure
59
+ @mutex.unlock
60
+ end
61
+
62
+ # @!macro [attach] atomic_boolean_method_is_false
63
+ #
64
+ # Is the current value `true`?false
65
+ #
66
+ # @return [Boolean] true if the current value is `false`, else false
67
+ def false?
68
+ @mutex.lock
69
+ !@value
70
+ ensure
71
+ @mutex.unlock
72
+ end
73
+
74
+ # @!macro [attach] atomic_boolean_method_make_true
75
+ #
76
+ # Explicitly sets the value to true.
77
+ #
78
+ # @return [Boolean] true is value has changed, otherwise false
79
+ def make_true
80
+ @mutex.lock
81
+ old = @value
82
+ @value = true
83
+ !old
84
+ ensure
85
+ @mutex.unlock
86
+ end
87
+
88
+ # @!macro [attach] atomic_boolean_method_make_false
89
+ #
90
+ # Explicitly sets the value to false.
91
+ #
92
+ # @return [Boolean] true is value has changed, otherwise false
93
+ def make_false
94
+ @mutex.lock
95
+ old = @value
96
+ @value = false
97
+ old
98
+ ensure
99
+ @mutex.unlock
100
+ end
101
+ end
102
+
103
+ if RUBY_PLATFORM == 'java'
104
+
105
+ # @!macro atomic_boolean
106
+ class JavaAtomicBoolean
107
+
108
+ # @!macro atomic_boolean_method_initialize
109
+ #
110
+ def initialize(initial = false)
111
+ @atomic = java.util.concurrent.atomic.AtomicBoolean.new(!!initial)
112
+ end
113
+
114
+ # @!macro atomic_boolean_method_value
115
+ #
116
+ def value
117
+ @atomic.get
118
+ end
119
+
120
+ # @!macro atomic_boolean_method_value_eq
121
+ #
122
+ def value=(value)
123
+ @atomic.set(!!value)
124
+ end
125
+
126
+ # @!macro [attach] atomic_boolean_method_is_true
127
+ def true?
128
+ @atomic.get
129
+ end
130
+
131
+ # @!macro [attach] atomic_boolean_method_is_false
132
+ def false?
133
+ !@atomic.get
134
+ end
135
+
136
+ # @!macro atomic_boolean_method_make_true
137
+ def make_true
138
+ @atomic.compareAndSet(false, true)
139
+ end
140
+
141
+ # @!macro atomic_boolean_method_make_false
142
+ def make_false
143
+ @atomic.compareAndSet(true, false)
144
+ end
145
+ end
146
+
147
+ # @!macro atomic_boolean
148
+ class AtomicBoolean < JavaAtomicBoolean
149
+ end
150
+
151
+ else
152
+
153
+ # @!macro atomic_boolean
154
+ class AtomicBoolean < MutexAtomicBoolean
155
+ end
156
+ end
157
+ end
@@ -0,0 +1,162 @@
1
+ module Concurrent
2
+
3
+ # @!macro [attach] atomic_fixnum
4
+ #
5
+ # A numeric value that can be updated atomically. Reads and writes to an atomic
6
+ # fixnum and thread-safe and guaranteed to succeed. Reads and writes may block
7
+ # briefly but no explicit locking is required.
8
+ #
9
+ # @since 0.5.0
10
+ # @see http://docs.oracle.com/javase/7/docs/api/java/util/concurrent/atomic/AtomicLong.html java.util.concurrent.atomic.AtomicLong
11
+ class MutexAtomicFixnum
12
+
13
+ # @!macro [attach] atomic_fixnum_method_initialize
14
+ #
15
+ # Creates a new `AtomicFixnum` with the given initial value.
16
+ #
17
+ # @param [Fixnum] init the initial value
18
+ # @raise [ArgumentError] if the initial value is not a `Fixnum`
19
+ def initialize(init = 0)
20
+ raise ArgumentError.new('initial value must be a Fixnum') unless init.is_a?(Fixnum)
21
+ @value = init
22
+ @mutex = Mutex.new
23
+ end
24
+
25
+ # @!macro [attach] atomic_fixnum_method_value
26
+ #
27
+ # Retrieves the current `Fixnum` value.
28
+ #
29
+ # @return [Fixnum] the current value
30
+ def value
31
+ @mutex.lock
32
+ @value
33
+ ensure
34
+ @mutex.unlock
35
+ end
36
+
37
+ # @!macro [attach] atomic_fixnum_method_value_eq
38
+ #
39
+ # Explicitly sets the value.
40
+ #
41
+ # @param [Fixnum] value the new value to be set
42
+ #
43
+ # @return [Fixnum] the current value
44
+ #
45
+ # @raise [ArgumentError] if the new value is not a `Fixnum`
46
+ def value=(value)
47
+ raise ArgumentError.new('value must be a Fixnum') unless value.is_a?(Fixnum)
48
+ @mutex.lock
49
+ @value = value
50
+ ensure
51
+ @mutex.unlock
52
+ end
53
+
54
+ # @!macro [attach] atomic_fixnum_method_increment
55
+ #
56
+ # Increases the current value by 1.
57
+ #
58
+ # @return [Fixnum] the current value after incrementation
59
+ def increment
60
+ @mutex.lock
61
+ @value += 1
62
+ ensure
63
+ @mutex.unlock
64
+ end
65
+
66
+ alias_method :up, :increment
67
+
68
+ # @!macro [attach] atomic_fixnum_method_decrement
69
+ #
70
+ # Decreases the current value by 1.
71
+ #
72
+ # @return [Fixnum] the current value after decrementation
73
+ def decrement
74
+ @mutex.lock
75
+ @value -= 1
76
+ ensure
77
+ @mutex.unlock
78
+ end
79
+
80
+ alias_method :down, :decrement
81
+
82
+ # @!macro [attach] atomic_fixnum_method_compare_and_set
83
+ #
84
+ # Atomically sets the value to the given updated value if the current
85
+ # value == the expected value.
86
+ #
87
+ # @param [Fixnum] expect the expected value
88
+ # @param [Fixnum] update the new value
89
+ #
90
+ # @return [Boolean] true if the value was updated else false
91
+ def compare_and_set(expect, update)
92
+ @mutex.lock
93
+ if @value == expect
94
+ @value = update
95
+ true
96
+ else
97
+ false
98
+ end
99
+ ensure
100
+ @mutex.unlock
101
+ end
102
+ end
103
+
104
+ if RUBY_PLATFORM == 'java'
105
+
106
+ # @!macro atomic_fixnum
107
+ class JavaAtomicFixnum
108
+
109
+ # @!macro atomic_fixnum_method_initialize
110
+ #
111
+ def initialize(init = 0)
112
+ raise ArgumentError.new('initial value must be a Fixnum') unless init.is_a?(Fixnum)
113
+ @atomic = java.util.concurrent.atomic.AtomicLong.new(init)
114
+ end
115
+
116
+ # @!macro atomic_fixnum_method_value
117
+ #
118
+ def value
119
+ @atomic.get
120
+ end
121
+
122
+ # @!macro atomic_fixnum_method_value_eq
123
+ #
124
+ def value=(value)
125
+ raise ArgumentError.new('value must be a Fixnum') unless value.is_a?(Fixnum)
126
+ @atomic.set(value)
127
+ end
128
+
129
+ # @!macro atomic_fixnum_method_increment
130
+ #
131
+ def increment
132
+ @atomic.increment_and_get
133
+ end
134
+
135
+ alias_method :up, :increment
136
+
137
+ # @!macro atomic_fixnum_method_decrement
138
+ #
139
+ def decrement
140
+ @atomic.decrement_and_get
141
+ end
142
+
143
+ alias_method :down, :decrement
144
+
145
+ # @!macro atomic_fixnum_method_compare_and_set
146
+ #
147
+ def compare_and_set(expect, update)
148
+ @atomic.compare_and_set(expect, update)
149
+ end
150
+ end
151
+
152
+ # @!macro atomic_fixnum
153
+ class AtomicFixnum < JavaAtomicFixnum
154
+ end
155
+
156
+ else
157
+
158
+ # @!macro atomic_fixnum
159
+ class AtomicFixnum < MutexAtomicFixnum
160
+ end
161
+ end
162
+ end
@@ -0,0 +1,67 @@
1
+ module Concurrent
2
+
3
+ # Condition is a better implementation of standard Ruby ConditionVariable.
4
+ # The biggest difference is the wait return value: Condition#wait returns
5
+ # Condition::Result which make possible to know if waiting thread has been woken up
6
+ # by an another thread (using #signal or #broadcast) or due to timeout.
7
+ #
8
+ # Every #wait must be guarded by a locked Mutex or a ThreadError will be risen.
9
+ # Although it's not mandatory, it's recommended to call also #signal and #broadcast within
10
+ # the same mutex
11
+ class Condition
12
+
13
+ class Result
14
+ def initialize(remaining_time)
15
+ @remaining_time = remaining_time
16
+ end
17
+
18
+ attr_reader :remaining_time
19
+
20
+ # @return [Boolean] true if current thread has been waken up by a #signal or a #broadcast call, otherwise false
21
+ def woken_up?
22
+ @remaining_time.nil? || @remaining_time > 0
23
+ end
24
+
25
+ # @return [Boolean] true if current thread has been waken up due to a timeout, otherwise false
26
+ def timed_out?
27
+ @remaining_time != nil && @remaining_time <= 0
28
+ end
29
+
30
+ alias_method :can_wait?, :woken_up?
31
+
32
+ end
33
+
34
+ def initialize
35
+ @condition = ConditionVariable.new
36
+ end
37
+
38
+ # @param [Mutex] mutex the locked mutex guarding the wait
39
+ # @param [Object] timeout nil means no timeout
40
+ # @return [Result]
41
+ def wait(mutex, timeout = nil)
42
+ start_time = Time.now.to_f
43
+ @condition.wait(mutex, timeout)
44
+
45
+ if timeout.nil?
46
+ Result.new(nil)
47
+ else
48
+ Result.new(start_time + timeout - Time.now.to_f)
49
+ end
50
+ end
51
+
52
+ # Wakes up a waiting thread
53
+ # @return [true]
54
+ def signal
55
+ @condition.signal
56
+ true
57
+ end
58
+
59
+ # Wakes up all waiting threads
60
+ # @return [true]
61
+ def broadcast
62
+ @condition.broadcast
63
+ true
64
+ end
65
+
66
+ end
67
+ end
@@ -0,0 +1,118 @@
1
+ module Concurrent
2
+
3
+ # A thread safe observer set implemented using copy-on-read approach:
4
+ # observers are added and removed from a thread safe collection; every time
5
+ # a notification is required the internal data structure is copied to
6
+ # prevent concurrency issues
7
+ class CopyOnNotifyObserverSet
8
+
9
+ def initialize
10
+ @mutex = Mutex.new
11
+ @observers = {}
12
+ end
13
+
14
+ # Adds an observer to this set
15
+ # If a block is passed, the observer will be created by this method and no other params should be passed
16
+ # @param [Object] observer the observer to add
17
+ # @param [Symbol] func the function to call on the observer during notification. Default is :update
18
+ # @return [Object] the added observer
19
+ def add_observer(observer=nil, func=:update, &block)
20
+ if observer.nil? && block.nil?
21
+ raise ArgumentError, 'should pass observer as a first argument or block'
22
+ elsif observer && block
23
+ raise ArgumentError.new('cannot provide both an observer and a block')
24
+ end
25
+
26
+ if block
27
+ observer = block
28
+ func = :call
29
+ end
30
+
31
+ begin
32
+ @mutex.lock
33
+ @observers[observer] = func
34
+ ensure
35
+ @mutex.unlock
36
+ end
37
+
38
+ observer
39
+ end
40
+
41
+ # @param [Object] observer the observer to remove
42
+ # @return [Object] the deleted observer
43
+ def delete_observer(observer)
44
+ @mutex.lock
45
+ @observers.delete(observer)
46
+ @mutex.unlock
47
+
48
+ observer
49
+ end
50
+
51
+ # Deletes all observers
52
+ # @return [CopyOnWriteObserverSet] self
53
+ def delete_observers
54
+ @mutex.lock
55
+ @observers.clear
56
+ @mutex.unlock
57
+
58
+ self
59
+ end
60
+
61
+ # @return [Integer] the observers count
62
+ def count_observers
63
+ @mutex.lock
64
+ result = @observers.count
65
+ @mutex.unlock
66
+
67
+ result
68
+ end
69
+
70
+ # Notifies all registered observers with optional args
71
+ # @param [Object] args arguments to be passed to each observer
72
+ # @return [CopyOnWriteObserverSet] self
73
+ def notify_observers(*args, &block)
74
+ observers = duplicate_observers
75
+ notify_to(observers, *args, &block)
76
+
77
+ self
78
+ end
79
+
80
+ # Notifies all registered observers with optional args and deletes them.
81
+ #
82
+ # @param [Object] args arguments to be passed to each observer
83
+ # @return [CopyOnWriteObserverSet] self
84
+ def notify_and_delete_observers(*args, &block)
85
+ observers = duplicate_and_clear_observers
86
+ notify_to(observers, *args, &block)
87
+
88
+ self
89
+ end
90
+
91
+ private
92
+
93
+ def duplicate_and_clear_observers
94
+ @mutex.lock
95
+ observers = @observers.dup
96
+ @observers.clear
97
+ @mutex.unlock
98
+
99
+ observers
100
+ end
101
+
102
+ def duplicate_observers
103
+ @mutex.lock
104
+ observers = @observers.dup
105
+ @mutex.unlock
106
+
107
+ observers
108
+ end
109
+
110
+ def notify_to(observers, *args)
111
+ raise ArgumentError.new('cannot give arguments and a block') if block_given? && !args.empty?
112
+ observers.each do |observer, function|
113
+ args = yield if block_given?
114
+ observer.send(function, *args)
115
+ end
116
+ end
117
+ end
118
+ end