concurrent-ruby 0.1.1.pre.5 → 0.1.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (45) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +1 -48
  3. data/lib/concurrent.rb +0 -6
  4. data/lib/concurrent/agent.rb +40 -19
  5. data/lib/concurrent/cached_thread_pool.rb +11 -10
  6. data/lib/concurrent/defer.rb +12 -8
  7. data/lib/concurrent/fixed_thread_pool.rb +6 -12
  8. data/lib/concurrent/future.rb +20 -8
  9. data/lib/concurrent/global_thread_pool.rb +0 -13
  10. data/lib/concurrent/goroutine.rb +1 -5
  11. data/lib/concurrent/obligation.rb +64 -10
  12. data/lib/concurrent/promise.rb +60 -38
  13. data/lib/concurrent/thread_pool.rb +5 -16
  14. data/lib/concurrent/utilities.rb +0 -8
  15. data/lib/concurrent/version.rb +1 -1
  16. data/md/defer.md +4 -4
  17. data/md/promise.md +0 -2
  18. data/md/thread_pool.md +0 -27
  19. data/spec/concurrent/agent_spec.rb +27 -8
  20. data/spec/concurrent/cached_thread_pool_spec.rb +1 -14
  21. data/spec/concurrent/defer_spec.rb +21 -17
  22. data/spec/concurrent/event_machine_defer_proxy_spec.rb +149 -159
  23. data/spec/concurrent/fixed_thread_pool_spec.rb +3 -2
  24. data/spec/concurrent/future_spec.rb +10 -3
  25. data/spec/concurrent/goroutine_spec.rb +0 -15
  26. data/spec/concurrent/obligation_shared.rb +2 -16
  27. data/spec/concurrent/promise_spec.rb +13 -15
  28. data/spec/concurrent/thread_pool_shared.rb +5 -5
  29. data/spec/concurrent/utilities_spec.rb +1 -30
  30. data/spec/spec_helper.rb +0 -25
  31. metadata +7 -28
  32. data/lib/concurrent/executor.rb +0 -95
  33. data/lib/concurrent/functions.rb +0 -120
  34. data/lib/concurrent/null_thread_pool.rb +0 -22
  35. data/lib/concurrent/reactor.rb +0 -161
  36. data/lib/concurrent/reactor/drb_async_demux.rb +0 -74
  37. data/lib/concurrent/reactor/tcp_sync_demux.rb +0 -98
  38. data/md/executor.md +0 -176
  39. data/spec/concurrent/executor_spec.rb +0 -200
  40. data/spec/concurrent/functions_spec.rb +0 -217
  41. data/spec/concurrent/global_thread_pool_spec.rb +0 -38
  42. data/spec/concurrent/null_thread_pool_spec.rb +0 -54
  43. data/spec/concurrent/reactor/drb_async_demux_spec.rb +0 -12
  44. data/spec/concurrent/reactor/tcp_sync_demux_spec.rb +0 -12
  45. data/spec/concurrent/reactor_spec.rb +0 -351
@@ -1,120 +0,0 @@
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,22 +0,0 @@
1
- require 'concurrent/global_thread_pool'
2
-
3
- module Concurrent
4
-
5
- class NullThreadPool
6
- behavior(:global_thread_pool)
7
-
8
- def self.post(*args, &block)
9
- Thread.new(*args, &block)
10
- return true
11
- end
12
-
13
- def post(*args, &block)
14
- return NullThreadPool.post(*args, &block)
15
- end
16
-
17
- def <<(block)
18
- NullThreadPool.post(&block)
19
- return self
20
- end
21
- end
22
- end
@@ -1,161 +0,0 @@
1
- require 'thread'
2
- require 'functional'
3
-
4
- behavior_info(:sync_event_demux,
5
- start: 0,
6
- stop: 0,
7
- stopped?: 0,
8
- accept: 0,
9
- respond: 2,
10
- close: 0)
11
-
12
- behavior_info(:async_event_demux,
13
- start: 0,
14
- stop: 0,
15
- stopped?: 0,
16
- set_reactor: 1)
17
-
18
- behavior_info(:demux_reactor,
19
- handle: -2)
20
-
21
- module Concurrent
22
-
23
- class Reactor
24
-
25
- behavior(:demux_reactor)
26
-
27
- RESERVED_EVENTS = [ :stop ]
28
-
29
- EventContext = Struct.new(:event, :args, :callback)
30
-
31
- def initialize(demux = nil)
32
- @demux = demux
33
- if @demux.nil? || @demux.behaves_as?(:async_event_demux)
34
- @sync = false
35
- @queue = Queue.new
36
- @demux.set_reactor(self) unless @demux.nil?
37
- elsif @demux.behaves_as?(:sync_event_demux)
38
- @sync = true
39
- else
40
- raise ArgumentError.new("invalid event demultiplexer '#{@demux}'")
41
- end
42
-
43
- @running = false
44
- @handlers = Hash.new
45
- @mutex = Mutex.new
46
- end
47
-
48
- def running?
49
- return @running
50
- end
51
-
52
- def add_handler(event, &block)
53
- raise ArgumentError.new('no block given') unless block_given?
54
- event = event.to_sym
55
- raise ArgumentError.new("'#{event}' is a reserved event") if RESERVED_EVENTS.include?(event)
56
- @mutex.synchronize {
57
- @handlers[event] = block
58
- }
59
- return true
60
- end
61
-
62
- def remove_handler(event)
63
- handler = @mutex.synchronize {
64
- @handlers.delete(event.to_sym)
65
- }
66
- return ! handler.nil?
67
- end
68
-
69
- def stop_on_signal(*signals)
70
- signals.each{|signal| Signal.trap(signal){ Thread.new{ self.stop }}}
71
- end
72
-
73
- def handle(event, *args)
74
- raise NotImplementedError.new("demultiplexer '#{@demux.class}' is synchronous") if @sync
75
- return [:stopped, 'reactor not running'] unless running?
76
- context = EventContext.new(event.to_sym, args.dup, Queue.new)
77
- @queue.push(context)
78
- return context.callback.pop
79
- end
80
-
81
- def start
82
- raise StandardError.new('already running') if self.running?
83
- @sync ? (@running = true; run_sync) : (@running = true; run_async)
84
- end
85
- alias_method :run, :start
86
-
87
- def stop
88
- return true unless self.running?
89
- if @sync
90
- @demux.stop
91
- else
92
- @queue.push(:stop)
93
- end
94
- return true
95
- end
96
-
97
- private
98
-
99
- def handle_event(context)
100
- raise ArgumentError.new('no block given') unless block_given?
101
-
102
- handler = @mutex.synchronize {
103
- @handlers[context.event]
104
- }
105
-
106
- if handler.nil?
107
- response = yield(:noop, "'#{context.event}' handler not found")
108
- else
109
- begin
110
- result = handler.call(*context.args)
111
- response = yield(:ok, result)
112
- rescue Exception => ex
113
- response = yield(:ex, ex)
114
- end
115
- end
116
-
117
- return response
118
- end
119
-
120
- def finalize_stop
121
- @mutex.synchronize do
122
- @running = false
123
- @demux.stop unless @demux.nil?
124
- @demux = nil
125
- end
126
- end
127
-
128
- def run_sync
129
- @demux.start
130
-
131
- loop do
132
- break if @demux.stopped?
133
- context = @demux.accept
134
- if context.nil?
135
- @demux.close
136
- else
137
- response = handle_event(context) do |result, message|
138
- [result, message]
139
- end
140
- @demux.respond(*response)
141
- end
142
- end
143
-
144
- finalize_stop
145
- end
146
-
147
- def run_async
148
- @demux.start unless @demux.nil?
149
-
150
- loop do
151
- context = @queue.pop
152
- break if context == :stop
153
- handle_event(context) do |result, message|
154
- context.callback.push([result, message])
155
- end
156
- end
157
-
158
- finalize_stop
159
- end
160
- end
161
- end
@@ -1,74 +0,0 @@
1
- require 'drb/drb'
2
- require 'drb/acl'
3
- require 'functional'
4
- require 'concurrent/reactor'
5
-
6
- module Concurrent
7
- class Reactor
8
-
9
- class DRbAsyncDemux
10
-
11
- behavior(:async_event_demux)
12
-
13
- DEFAULT_URI = 'druby://localhost:12345'
14
- DEFAULT_ACL = %w[allow all]
15
-
16
- def initialize(opts = {})
17
- @uri = opts[:uri] || DEFAULT_URI
18
- @acl = ACL.new(opts[:acl] || DEFAULT_ACL)
19
- end
20
-
21
- def set_reactor(reactor)
22
- raise ArgumentError.new('invalid reactor') unless reactor.behaves_as?(:demux_reactor)
23
- @reactor = reactor
24
- end
25
-
26
- def start
27
- DRb.install_acl(@acl)
28
- @service = DRb.start_service(@uri, Demultiplexer.new(@reactor))
29
- end
30
-
31
- def stop
32
- @service = DRb.stop_service
33
- end
34
-
35
- def stopped?
36
- return @service.nil?
37
- end
38
-
39
- private
40
-
41
- class Demultiplexer
42
-
43
- def initialize(reactor)
44
- @reactor = reactor
45
- end
46
-
47
- Concurrent::Reactor::RESERVED_EVENTS.each do |event|
48
- define_method(event){|*args| false }
49
- end
50
-
51
- def method_missing(method, *args, &block)
52
- (class << self; self; end).class_eval do
53
- define_method(method) do |*args|
54
- result = @reactor.handle(method, *args)
55
- case result.first
56
- when :ok
57
- return result.last
58
- when :ex
59
- raise result.last
60
- when :noop
61
- raise NoMethodError.new("undefined method '#{method}' for #{self}")
62
- else
63
- raise DRb::DRbUnknownError.new("unexpected error when calling method '#{method}'")
64
- end
65
- end
66
- end
67
- self.send(method, *args)
68
- end
69
- end
70
- end
71
-
72
- DRbAsyncDemultiplexer = DRbAsyncDemux
73
- end
74
- end
@@ -1,98 +0,0 @@
1
- require 'socket'
2
- require 'drb/acl'
3
- require 'functional'
4
- require 'concurrent/reactor'
5
-
6
- module Concurrent
7
- class Reactor
8
-
9
- class TcpSyncDemux
10
-
11
- behavior(:sync_event_demux)
12
-
13
- DEFAULT_HOST = '127.0.0.1'
14
- DEFAULT_PORT = 12345
15
- DEFAULT_ACL = %[allow all]
16
-
17
- def initialize(opts = {})
18
- @host = opts[:host] || DEFAULT_HOST
19
- @port = opts[:port] || DEFAULT_PORT
20
- @acl = ACL.new(opts[:acl] || DEFAULT_ACL)
21
- end
22
-
23
- def start
24
- @server = TCPServer.new(@host, @port)
25
- end
26
-
27
- def stop
28
- atomic {
29
- @socket.close unless @socket.nil?
30
- @server.close unless @server.nil?
31
- @server = @socket = nil
32
- }
33
- end
34
-
35
- def stopped?
36
- return @server.nil?
37
- end
38
-
39
- def accept
40
- @socket = @server.accept if @socket.nil?
41
- return nil unless @acl.allow_socket?(@socket)
42
- event, args = get_message(@socket)
43
- return nil if event.nil?
44
- return Reactor::EventContext.new(event, args)
45
- end
46
-
47
- def respond(result, message)
48
- return nil if @socket.nil?
49
- @socket.puts(format_message(result, message))
50
- end
51
-
52
- def close
53
- @socket.close
54
- @socket = nil
55
- end
56
-
57
- def self.format_message(event, *args)
58
- args = args.reduce('') do |memo, arg|
59
- memo << "#{arg}\r\n"
60
- end
61
- return ":#{event}\r\n#{args}\r\n"
62
- end
63
- def format_message(*args) self.class.format_message(*args); end
64
-
65
- def self.parse_message(message)
66
- return atomic {
67
- event = message.first.match /^:?(\w+)/
68
- event = event[1].to_s.downcase.to_sym unless event.nil?
69
-
70
- args = message.slice(1, message.length) || []
71
-
72
- [event, args]
73
- }
74
- end
75
- def parse_message(*args) self.class.parse_message(*args); end
76
-
77
- def self.get_message(socket)
78
- message = []
79
- while line = socket.gets
80
- if line.nil? || (line = line.strip).empty?
81
- break
82
- else
83
- message << line
84
- end
85
- end
86
-
87
- if message.empty?
88
- return nil
89
- else
90
- return parse_message(message)
91
- end
92
- end
93
- def get_message(*args) self.class.get_message(*args); end
94
- end
95
-
96
- TcpSyncDemultiplexer = TcpSyncDemux
97
- end
98
- end