concurrent-ruby 0.2.1 → 0.2.2

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 (58) hide show
  1. checksums.yaml +7 -0
  2. data/LICENSE +21 -21
  3. data/README.md +276 -275
  4. data/lib/concurrent.rb +28 -28
  5. data/lib/concurrent/agent.rb +114 -114
  6. data/lib/concurrent/cached_thread_pool.rb +131 -131
  7. data/lib/concurrent/defer.rb +65 -65
  8. data/lib/concurrent/event.rb +60 -60
  9. data/lib/concurrent/event_machine_defer_proxy.rb +23 -23
  10. data/lib/concurrent/executor.rb +96 -96
  11. data/lib/concurrent/fixed_thread_pool.rb +99 -99
  12. data/lib/concurrent/functions.rb +120 -120
  13. data/lib/concurrent/future.rb +42 -42
  14. data/lib/concurrent/global_thread_pool.rb +24 -16
  15. data/lib/concurrent/goroutine.rb +29 -29
  16. data/lib/concurrent/null_thread_pool.rb +22 -22
  17. data/lib/concurrent/obligation.rb +67 -67
  18. data/lib/concurrent/promise.rb +174 -174
  19. data/lib/concurrent/reactor.rb +166 -166
  20. data/lib/concurrent/reactor/drb_async_demux.rb +83 -83
  21. data/lib/concurrent/reactor/tcp_sync_demux.rb +131 -131
  22. data/lib/concurrent/supervisor.rb +105 -105
  23. data/lib/concurrent/thread_pool.rb +76 -76
  24. data/lib/concurrent/utilities.rb +32 -32
  25. data/lib/concurrent/version.rb +3 -3
  26. data/lib/concurrent_ruby.rb +1 -1
  27. data/md/agent.md +123 -123
  28. data/md/defer.md +174 -174
  29. data/md/event.md +32 -32
  30. data/md/executor.md +187 -187
  31. data/md/future.md +83 -83
  32. data/md/goroutine.md +52 -52
  33. data/md/obligation.md +32 -32
  34. data/md/promise.md +227 -227
  35. data/md/thread_pool.md +224 -224
  36. data/spec/concurrent/agent_spec.rb +390 -386
  37. data/spec/concurrent/cached_thread_pool_spec.rb +125 -125
  38. data/spec/concurrent/defer_spec.rb +199 -195
  39. data/spec/concurrent/event_machine_defer_proxy_spec.rb +256 -256
  40. data/spec/concurrent/event_spec.rb +134 -134
  41. data/spec/concurrent/executor_spec.rb +200 -200
  42. data/spec/concurrent/fixed_thread_pool_spec.rb +83 -83
  43. data/spec/concurrent/functions_spec.rb +217 -217
  44. data/spec/concurrent/future_spec.rb +112 -108
  45. data/spec/concurrent/global_thread_pool_spec.rb +11 -38
  46. data/spec/concurrent/goroutine_spec.rb +67 -67
  47. data/spec/concurrent/null_thread_pool_spec.rb +57 -57
  48. data/spec/concurrent/obligation_shared.rb +132 -132
  49. data/spec/concurrent/promise_spec.rb +316 -312
  50. data/spec/concurrent/reactor/drb_async_demux_spec.rb +196 -196
  51. data/spec/concurrent/reactor/tcp_sync_demux_spec.rb +410 -410
  52. data/spec/concurrent/reactor_spec.rb +364 -364
  53. data/spec/concurrent/supervisor_spec.rb +269 -269
  54. data/spec/concurrent/thread_pool_shared.rb +204 -204
  55. data/spec/concurrent/uses_global_thread_pool_shared.rb +64 -0
  56. data/spec/concurrent/utilities_spec.rb +74 -74
  57. data/spec/spec_helper.rb +32 -32
  58. metadata +17 -19
@@ -1,99 +1,99 @@
1
- require 'thread'
2
-
3
- require 'concurrent/thread_pool'
4
- require 'concurrent/event'
5
-
6
- module Concurrent
7
-
8
- def self.new_fixed_thread_pool(size)
9
- return FixedThreadPool.new(size)
10
- end
11
-
12
- class FixedThreadPool < ThreadPool
13
- behavior(:thread_pool)
14
-
15
- MIN_POOL_SIZE = 1
16
- MAX_POOL_SIZE = 1024
17
-
18
- def initialize(size)
19
- super()
20
- if size < MIN_POOL_SIZE || size > MAX_POOL_SIZE
21
- raise ArgumentError.new("size must be between #{MIN_POOL_SIZE} and #{MAX_POOL_SIZE}")
22
- end
23
-
24
- @pool = size.times.collect{ create_worker_thread }
25
- collect_garbage
26
- end
27
-
28
- def kill
29
- mutex.synchronize do
30
- @status = :killed
31
- @pool.each{|t| Thread.kill(t) }
32
- end
33
- end
34
-
35
- def size
36
- if running?
37
- return @pool.length
38
- else
39
- return 0
40
- end
41
- end
42
-
43
- def post(*args, &block)
44
- raise ArgumentError.new('no block given') unless block_given?
45
- if running?
46
- @queue << [args, block]
47
- return true
48
- else
49
- return false
50
- end
51
- end
52
-
53
- # @private
54
- def status # :nodoc:
55
- mutex.synchronize do
56
- @pool.collect{|t| t.status }
57
- end
58
- end
59
-
60
- private
61
-
62
- # @private
63
- def create_worker_thread # :nodoc:
64
- thread = Thread.new do
65
- loop do
66
- task = @queue.pop
67
- if task == :stop
68
- break
69
- else
70
- task.last.call(*task.first)
71
- end
72
- end
73
- @pool.delete(Thread.current)
74
- if @pool.empty?
75
- @termination.set
76
- @status = :shutdown unless killed?
77
- end
78
- end
79
-
80
- thread.abort_on_exception = false
81
- return thread
82
- end
83
-
84
- # @private
85
- def collect_garbage # :nodoc:
86
- @collector = Thread.new do
87
- sleep(1)
88
- mutex.synchronize do
89
- @pool.size.times do |i|
90
- if @pool[i].status.nil?
91
- @pool[i] = create_worker_thread
92
- end
93
- end
94
- end
95
- end
96
- @collector.abort_on_exception = false
97
- end
98
- end
99
- end
1
+ require 'thread'
2
+
3
+ require 'concurrent/thread_pool'
4
+ require 'concurrent/event'
5
+
6
+ module Concurrent
7
+
8
+ def self.new_fixed_thread_pool(size)
9
+ return FixedThreadPool.new(size)
10
+ end
11
+
12
+ class FixedThreadPool < ThreadPool
13
+ behavior(:thread_pool)
14
+
15
+ MIN_POOL_SIZE = 1
16
+ MAX_POOL_SIZE = 1024
17
+
18
+ def initialize(size)
19
+ super()
20
+ if size < MIN_POOL_SIZE || size > MAX_POOL_SIZE
21
+ raise ArgumentError.new("size must be between #{MIN_POOL_SIZE} and #{MAX_POOL_SIZE}")
22
+ end
23
+
24
+ @pool = size.times.collect{ create_worker_thread }
25
+ collect_garbage
26
+ end
27
+
28
+ def kill
29
+ mutex.synchronize do
30
+ @status = :killed
31
+ @pool.each{|t| Thread.kill(t) }
32
+ end
33
+ end
34
+
35
+ def size
36
+ if running?
37
+ return @pool.length
38
+ else
39
+ return 0
40
+ end
41
+ end
42
+
43
+ def post(*args, &block)
44
+ raise ArgumentError.new('no block given') unless block_given?
45
+ if running?
46
+ @queue << [args, block]
47
+ return true
48
+ else
49
+ return false
50
+ end
51
+ end
52
+
53
+ # @private
54
+ def status # :nodoc:
55
+ mutex.synchronize do
56
+ @pool.collect{|t| t.status }
57
+ end
58
+ end
59
+
60
+ private
61
+
62
+ # @private
63
+ def create_worker_thread # :nodoc:
64
+ thread = Thread.new do
65
+ loop do
66
+ task = @queue.pop
67
+ if task == :stop
68
+ break
69
+ else
70
+ task.last.call(*task.first)
71
+ end
72
+ end
73
+ @pool.delete(Thread.current)
74
+ if @pool.empty?
75
+ @termination.set
76
+ @status = :shutdown unless killed?
77
+ end
78
+ end
79
+
80
+ thread.abort_on_exception = false
81
+ return thread
82
+ end
83
+
84
+ # @private
85
+ def collect_garbage # :nodoc:
86
+ @collector = Thread.new do
87
+ sleep(1)
88
+ mutex.synchronize do
89
+ @pool.size.times do |i|
90
+ if @pool[i].status.nil?
91
+ @pool[i] = create_worker_thread
92
+ end
93
+ end
94
+ end
95
+ end
96
+ @collector.abort_on_exception = false
97
+ end
98
+ end
99
+ end
@@ -1,120 +1,120 @@
1
- require 'concurrent/agent'
2
- require 'concurrent/defer'
3
- require 'concurrent/future'
4
- require 'concurrent/promise'
5
-
6
- module Kernel
7
-
8
- ## agent
9
-
10
- def agent(initial, timeout = Concurrent::Agent::TIMEOUT)
11
- return Concurrent::Agent.new(initial, timeout)
12
- end
13
- module_function :agent
14
-
15
- def post(object, &block)
16
- if object.respond_to?(:post)
17
- return object.post(&block)
18
- else
19
- raise ArgumentError.new('object does not support #post')
20
- end
21
- end
22
- module_function :post
23
-
24
- ## defer
25
-
26
- def defer(*args, &block)
27
- return Concurrent::Defer.new(*args, &block)
28
- end
29
- module_function :defer
30
-
31
- ## executor
32
-
33
- def executor(*args, &block)
34
- return Concurrent::Executor.run(*args, &block)
35
- end
36
- module_function :executor
37
-
38
- ## future
39
-
40
- def future(*args, &block)
41
- return Concurrent::Future.new(*args, &block)
42
- end
43
- module_function :future
44
-
45
- ## obligation
46
-
47
- def deref(object, timeout = nil)
48
- if object.respond_to?(:deref)
49
- return object.deref(timeout)
50
- elsif object.respond_to?(:value)
51
- return object.value(timeout)
52
- else
53
- raise ArgumentError.new('object does not support #deref')
54
- end
55
- end
56
- module_function :deref
57
-
58
- def pending?(object)
59
- if object.respond_to?(:pending?)
60
- return object.pending?
61
- else
62
- raise ArgumentError.new('object does not support #pending?')
63
- end
64
- end
65
- module_function :pending?
66
-
67
- def fulfilled?(object)
68
- if object.respond_to?(:fulfilled?)
69
- return object.fulfilled?
70
- elsif object.respond_to?(:realized?)
71
- return object.realized?
72
- else
73
- raise ArgumentError.new('object does not support #fulfilled?')
74
- end
75
- end
76
- module_function :fulfilled?
77
-
78
- def realized?(object)
79
- if object.respond_to?(:realized?)
80
- return object.realized?
81
- elsif object.respond_to?(:fulfilled?)
82
- return object.fulfilled?
83
- else
84
- raise ArgumentError.new('object does not support #realized?')
85
- end
86
- end
87
- module_function :realized?
88
-
89
- def rejected?(object)
90
- if object.respond_to?(:rejected?)
91
- return object.rejected?
92
- else
93
- raise ArgumentError.new('object does not support #rejected?')
94
- end
95
- end
96
- module_function :rejected?
97
-
98
- ## promise
99
-
100
- # Creates a new promise object. "A promise represents the eventual
101
- # value returned from the single completion of an operation."
102
- # Promises can be chained in a tree structure where each promise
103
- # has zero or more children. Promises are resolved asynchronously
104
- # in the order they are added to the tree. Parents are guaranteed
105
- # to be resolved before their children. The result of each promise
106
- # is passes to each of its children when the child resolves. When
107
- # a promise is rejected all its children will be summarily rejected.
108
- # A promise added to a rejected promise will immediately be rejected.
109
- # A promise that is neither resolved or rejected is pending.
110
- #
111
- # @param args [Array] zero or more arguments for the block
112
- # @param block [Proc] the block to call when attempting fulfillment
113
- #
114
- # @see Promise
115
- # @see http://wiki.commonjs.org/wiki/Promises/A
116
- def promise(*args, &block)
117
- return Concurrent::Promise.new(*args, &block)
118
- end
119
- module_function :promise
120
- end
1
+ require 'concurrent/agent'
2
+ require 'concurrent/defer'
3
+ require 'concurrent/future'
4
+ require 'concurrent/promise'
5
+
6
+ module Kernel
7
+
8
+ ## agent
9
+
10
+ def agent(initial, timeout = Concurrent::Agent::TIMEOUT)
11
+ return Concurrent::Agent.new(initial, timeout)
12
+ end
13
+ module_function :agent
14
+
15
+ def post(object, &block)
16
+ if object.respond_to?(:post)
17
+ return object.post(&block)
18
+ else
19
+ raise ArgumentError.new('object does not support #post')
20
+ end
21
+ end
22
+ module_function :post
23
+
24
+ ## defer
25
+
26
+ def defer(*args, &block)
27
+ return Concurrent::Defer.new(*args, &block)
28
+ end
29
+ module_function :defer
30
+
31
+ ## executor
32
+
33
+ def executor(*args, &block)
34
+ return Concurrent::Executor.run(*args, &block)
35
+ end
36
+ module_function :executor
37
+
38
+ ## future
39
+
40
+ def future(*args, &block)
41
+ return Concurrent::Future.new(*args, &block)
42
+ end
43
+ module_function :future
44
+
45
+ ## obligation
46
+
47
+ def deref(object, timeout = nil)
48
+ if object.respond_to?(:deref)
49
+ return object.deref(timeout)
50
+ elsif object.respond_to?(:value)
51
+ return object.value(timeout)
52
+ else
53
+ raise ArgumentError.new('object does not support #deref')
54
+ end
55
+ end
56
+ module_function :deref
57
+
58
+ def pending?(object)
59
+ if object.respond_to?(:pending?)
60
+ return object.pending?
61
+ else
62
+ raise ArgumentError.new('object does not support #pending?')
63
+ end
64
+ end
65
+ module_function :pending?
66
+
67
+ def fulfilled?(object)
68
+ if object.respond_to?(:fulfilled?)
69
+ return object.fulfilled?
70
+ elsif object.respond_to?(:realized?)
71
+ return object.realized?
72
+ else
73
+ raise ArgumentError.new('object does not support #fulfilled?')
74
+ end
75
+ end
76
+ module_function :fulfilled?
77
+
78
+ def realized?(object)
79
+ if object.respond_to?(:realized?)
80
+ return object.realized?
81
+ elsif object.respond_to?(:fulfilled?)
82
+ return object.fulfilled?
83
+ else
84
+ raise ArgumentError.new('object does not support #realized?')
85
+ end
86
+ end
87
+ module_function :realized?
88
+
89
+ def rejected?(object)
90
+ if object.respond_to?(:rejected?)
91
+ return object.rejected?
92
+ else
93
+ raise ArgumentError.new('object does not support #rejected?')
94
+ end
95
+ end
96
+ module_function :rejected?
97
+
98
+ ## promise
99
+
100
+ # Creates a new promise object. "A promise represents the eventual
101
+ # value returned from the single completion of an operation."
102
+ # Promises can be chained in a tree structure where each promise
103
+ # has zero or more children. Promises are resolved asynchronously
104
+ # in the order they are added to the tree. Parents are guaranteed
105
+ # to be resolved before their children. The result of each promise
106
+ # is passes to each of its children when the child resolves. When
107
+ # a promise is rejected all its children will be summarily rejected.
108
+ # A promise added to a rejected promise will immediately be rejected.
109
+ # A promise that is neither resolved or rejected is pending.
110
+ #
111
+ # @param args [Array] zero or more arguments for the block
112
+ # @param block [Proc] the block to call when attempting fulfillment
113
+ #
114
+ # @see Promise
115
+ # @see http://wiki.commonjs.org/wiki/Promises/A
116
+ def promise(*args, &block)
117
+ return Concurrent::Promise.new(*args, &block)
118
+ end
119
+ module_function :promise
120
+ end
@@ -1,42 +1,42 @@
1
- require 'thread'
2
-
3
- require 'concurrent/global_thread_pool'
4
- require 'concurrent/obligation'
5
- require 'concurrent/utilities'
6
-
7
- module Concurrent
8
-
9
- class Future
10
- include Obligation
11
- include UsesGlobalThreadPool
12
-
13
- behavior(:future)
14
-
15
- def initialize(*args, &block)
16
- unless block_given?
17
- @state = :fulfilled
18
- else
19
- @value = nil
20
- @state = :pending
21
- Future.thread_pool.post(*args) do
22
- work(*args, &block)
23
- end
24
- end
25
- end
26
-
27
- private
28
-
29
- # @private
30
- def work(*args) # :nodoc:
31
- mutex.synchronize do
32
- begin
33
- @value = yield(*args)
34
- @state = :fulfilled
35
- rescue Exception => ex
36
- @state = :rejected
37
- @reason = ex
38
- end
39
- end
40
- end
41
- end
42
- end
1
+ require 'thread'
2
+
3
+ require 'concurrent/global_thread_pool'
4
+ require 'concurrent/obligation'
5
+ require 'concurrent/utilities'
6
+
7
+ module Concurrent
8
+
9
+ class Future
10
+ include Obligation
11
+ include UsesGlobalThreadPool
12
+
13
+ behavior(:future)
14
+
15
+ def initialize(*args, &block)
16
+ unless block_given?
17
+ @state = :fulfilled
18
+ else
19
+ @value = nil
20
+ @state = :pending
21
+ Future.thread_pool.post(*args) do
22
+ work(*args, &block)
23
+ end
24
+ end
25
+ end
26
+
27
+ private
28
+
29
+ # @private
30
+ def work(*args) # :nodoc:
31
+ mutex.synchronize do
32
+ begin
33
+ @value = yield(*args)
34
+ @state = :fulfilled
35
+ rescue Exception => ex
36
+ @state = :rejected
37
+ @reason = ex
38
+ end
39
+ end
40
+ end
41
+ end
42
+ end