concurrent-ruby 0.2.1 → 0.2.2

Sign up to get free protection for your applications and to get access to all the features.
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,131 +1,131 @@
1
- require 'socket'
2
- require 'drb/acl'
3
- require 'functional'
4
- require 'concurrent/reactor'
5
- require 'concurrent/supervisor'
6
-
7
- module Concurrent
8
- class Reactor
9
-
10
- class TcpSyncDemux
11
-
12
- behavior(:sync_event_demux)
13
-
14
- DEFAULT_HOST = '127.0.0.1'
15
- DEFAULT_PORT = 12345
16
- DEFAULT_ACL = %w{deny all allow 127.0.0.1}
17
-
18
- attr_reader :host
19
- attr_reader :port
20
- attr_reader :acl
21
-
22
- def initialize(opts = {})
23
- @host = opts[:host] || DEFAULT_HOST
24
- @port = opts[:port] || DEFAULT_PORT
25
- @acl = ACL.new(opts[:acl] || DEFAULT_ACL)
26
- end
27
-
28
- def run
29
- raise StandardError.new('already running') if running?
30
- begin
31
- @server = TCPServer.new(@host, @port)
32
- return true
33
- rescue Exception => ex
34
- return false
35
- end
36
- end
37
-
38
- def stop
39
- begin
40
- @socket.close unless @socket.nil?
41
- rescue Exception => ex
42
- # suppress
43
- end
44
-
45
- begin
46
- @server.close unless @server.nil?
47
- rescue Exception => ex
48
- # suppress
49
- end
50
-
51
- @server = @socket = nil
52
- return true
53
- end
54
-
55
- def reset
56
- stop
57
- sleep(1)
58
- run
59
- end
60
-
61
- def running?
62
- return ! @server.nil?
63
- end
64
-
65
- def accept
66
- @socket = @server.accept if @socket.nil?
67
- return nil unless @acl.allow_socket?(@socket)
68
- event, args = get_message(@socket)
69
- return nil if event.nil?
70
- return Reactor::EventContext.new(event, args)
71
- rescue Exception => ex
72
- reset
73
- return nil
74
- end
75
-
76
- def respond(result, message)
77
- return nil if @socket.nil?
78
- @socket.puts(format_message(result, message))
79
- rescue Exception => ex
80
- reset
81
- end
82
-
83
- def self.format_message(event, *args)
84
- event = event.to_s.strip
85
- raise ArgumentError.new('nil or empty event') if event.empty?
86
- args = args.reduce('') do |memo, arg|
87
- memo << "#{arg}\r\n"
88
- end
89
- return "#{event}\r\n#{args}\r\n"
90
- end
91
-
92
- def format_message(*args)
93
- self.class.format_message(*args)
94
- end
95
-
96
- def self.parse_message(message)
97
- message = message.lines.map(&:chomp) if message.is_a?(String)
98
- return [nil, []] if message.nil?
99
- event = message.first.match(/^:?(\w+)/)
100
- event = event[1].to_s.downcase.to_sym unless event.nil?
101
- args = message.slice(1, message.length) || []
102
- args.pop if args.last.nil? || args.last.empty?
103
- return [event, args]
104
- end
105
-
106
- def parse_message(*args)
107
- self.class.parse_message(*args)
108
- end
109
-
110
- def self.get_message(socket)
111
- message = []
112
- while line = socket.gets
113
- if line.nil? || (line = line.strip).empty?
114
- break
115
- else
116
- message << line
117
- end
118
- end
119
-
120
- if message.empty?
121
- return nil
122
- else
123
- return parse_message(message)
124
- end
125
- end
126
- def get_message(*args) self.class.get_message(*args); end
127
- end
128
-
129
- TcpSyncDemultiplexer = TcpSyncDemux
130
- end
131
- end
1
+ require 'socket'
2
+ require 'drb/acl'
3
+ require 'functional'
4
+ require 'concurrent/reactor'
5
+ require 'concurrent/supervisor'
6
+
7
+ module Concurrent
8
+ class Reactor
9
+
10
+ class TcpSyncDemux
11
+
12
+ behavior(:sync_event_demux)
13
+
14
+ DEFAULT_HOST = '127.0.0.1'
15
+ DEFAULT_PORT = 12345
16
+ DEFAULT_ACL = %w{deny all allow 127.0.0.1}
17
+
18
+ attr_reader :host
19
+ attr_reader :port
20
+ attr_reader :acl
21
+
22
+ def initialize(opts = {})
23
+ @host = opts[:host] || DEFAULT_HOST
24
+ @port = opts[:port] || DEFAULT_PORT
25
+ @acl = ACL.new(opts[:acl] || DEFAULT_ACL)
26
+ end
27
+
28
+ def run
29
+ raise StandardError.new('already running') if running?
30
+ begin
31
+ @server = TCPServer.new(@host, @port)
32
+ return true
33
+ rescue Exception => ex
34
+ return false
35
+ end
36
+ end
37
+
38
+ def stop
39
+ begin
40
+ @socket.close unless @socket.nil?
41
+ rescue Exception => ex
42
+ # suppress
43
+ end
44
+
45
+ begin
46
+ @server.close unless @server.nil?
47
+ rescue Exception => ex
48
+ # suppress
49
+ end
50
+
51
+ @server = @socket = nil
52
+ return true
53
+ end
54
+
55
+ def reset
56
+ stop
57
+ sleep(1)
58
+ run
59
+ end
60
+
61
+ def running?
62
+ return ! @server.nil?
63
+ end
64
+
65
+ def accept
66
+ @socket = @server.accept if @socket.nil?
67
+ return nil unless @acl.allow_socket?(@socket)
68
+ event, args = get_message(@socket)
69
+ return nil if event.nil?
70
+ return Reactor::EventContext.new(event, args)
71
+ rescue Exception => ex
72
+ reset
73
+ return nil
74
+ end
75
+
76
+ def respond(result, message)
77
+ return nil if @socket.nil?
78
+ @socket.puts(format_message(result, message))
79
+ rescue Exception => ex
80
+ reset
81
+ end
82
+
83
+ def self.format_message(event, *args)
84
+ event = event.to_s.strip
85
+ raise ArgumentError.new('nil or empty event') if event.empty?
86
+ args = args.reduce('') do |memo, arg|
87
+ memo << "#{arg}\r\n"
88
+ end
89
+ return "#{event}\r\n#{args}\r\n"
90
+ end
91
+
92
+ def format_message(*args)
93
+ self.class.format_message(*args)
94
+ end
95
+
96
+ def self.parse_message(message)
97
+ message = message.lines.map(&:chomp) if message.is_a?(String)
98
+ return [nil, []] if message.nil?
99
+ event = message.first.match(/^:?(\w+)/)
100
+ event = event[1].to_s.downcase.to_sym unless event.nil?
101
+ args = message.slice(1, message.length) || []
102
+ args.pop if args.last.nil? || args.last.empty?
103
+ return [event, args]
104
+ end
105
+
106
+ def parse_message(*args)
107
+ self.class.parse_message(*args)
108
+ end
109
+
110
+ def self.get_message(socket)
111
+ message = []
112
+ while line = socket.gets
113
+ if line.nil? || (line = line.strip).empty?
114
+ break
115
+ else
116
+ message << line
117
+ end
118
+ end
119
+
120
+ if message.empty?
121
+ return nil
122
+ else
123
+ return parse_message(message)
124
+ end
125
+ end
126
+ def get_message(*args) self.class.get_message(*args); end
127
+ end
128
+
129
+ TcpSyncDemultiplexer = TcpSyncDemux
130
+ end
131
+ end
@@ -1,105 +1,105 @@
1
- require 'thread'
2
- require 'functional'
3
-
4
- behavior_info(:runnable,
5
- run: 0,
6
- stop: 0,
7
- running?: 0)
8
-
9
- module Concurrent
10
-
11
- class Supervisor
12
-
13
- DEFAULT_MONITOR_INTERVAL = 1
14
-
15
- behavior(:runnable)
16
-
17
- WorkerContext = Struct.new(:worker, :thread)
18
-
19
- attr_reader :monitor_interval
20
-
21
- def initialize(opts = {})
22
- @mutex = Mutex.new
23
- @workers = []
24
- @running = false
25
- @monitor = nil
26
- @monitor_interval = opts[:monitor] || opts[:monitor_interval] || DEFAULT_MONITOR_INTERVAL
27
- add_worker(opts[:worker]) unless opts[:worker].nil?
28
- end
29
-
30
- def run!
31
- raise StandardError.new('already running') if running?
32
- @mutex.synchronize do
33
- @running = true
34
- @monitor = Thread.new{ monitor }
35
- @monitor.abort_on_exception = false
36
- end
37
- Thread.pass
38
- end
39
-
40
- def run
41
- raise StandardError.new('already running') if running?
42
- @running = true
43
- monitor
44
- end
45
-
46
- def stop
47
- return true unless running?
48
- @running = false
49
- @mutex.synchronize do
50
- Thread.kill(@monitor) unless @monitor.nil?
51
- @monitor = nil
52
-
53
- until @workers.empty?
54
- context = @workers.pop
55
- begin
56
- context.worker.stop
57
- Thread.pass
58
- rescue Exception => ex
59
- # suppress
60
- ensure
61
- Thread.kill(context.thread) unless context.thread.nil?
62
- end
63
- end
64
- end
65
- end
66
-
67
- def running?
68
- return @running
69
- end
70
-
71
- def length
72
- return @workers.length
73
- end
74
- alias_method :size, :length
75
-
76
- def add_worker(worker)
77
- if worker.nil? || running? || ! worker.behaves_as?(:runnable)
78
- return false
79
- else
80
- @mutex.synchronize {
81
- @workers << WorkerContext.new(worker)
82
- }
83
- return true
84
- end
85
- end
86
-
87
- private
88
-
89
- def monitor
90
- loop do
91
- @mutex.synchronize do
92
- @workers.each do |context|
93
- unless context.thread && context.thread.alive?
94
- context.thread = Thread.new{ context.worker.run }
95
- context.thread.abort_on_exception = false
96
- end
97
- end
98
- end
99
- break unless running?
100
- sleep(@monitor_interval)
101
- break unless running?
102
- end
103
- end
104
- end
105
- end
1
+ require 'thread'
2
+ require 'functional'
3
+
4
+ behavior_info(:runnable,
5
+ run: 0,
6
+ stop: 0,
7
+ running?: 0)
8
+
9
+ module Concurrent
10
+
11
+ class Supervisor
12
+
13
+ DEFAULT_MONITOR_INTERVAL = 1
14
+
15
+ behavior(:runnable)
16
+
17
+ WorkerContext = Struct.new(:worker, :thread)
18
+
19
+ attr_reader :monitor_interval
20
+
21
+ def initialize(opts = {})
22
+ @mutex = Mutex.new
23
+ @workers = []
24
+ @running = false
25
+ @monitor = nil
26
+ @monitor_interval = opts[:monitor] || opts[:monitor_interval] || DEFAULT_MONITOR_INTERVAL
27
+ add_worker(opts[:worker]) unless opts[:worker].nil?
28
+ end
29
+
30
+ def run!
31
+ raise StandardError.new('already running') if running?
32
+ @mutex.synchronize do
33
+ @running = true
34
+ @monitor = Thread.new{ monitor }
35
+ @monitor.abort_on_exception = false
36
+ end
37
+ Thread.pass
38
+ end
39
+
40
+ def run
41
+ raise StandardError.new('already running') if running?
42
+ @running = true
43
+ monitor
44
+ end
45
+
46
+ def stop
47
+ return true unless running?
48
+ @running = false
49
+ @mutex.synchronize do
50
+ Thread.kill(@monitor) unless @monitor.nil?
51
+ @monitor = nil
52
+
53
+ until @workers.empty?
54
+ context = @workers.pop
55
+ begin
56
+ context.worker.stop
57
+ Thread.pass
58
+ rescue Exception => ex
59
+ # suppress
60
+ ensure
61
+ Thread.kill(context.thread) unless context.thread.nil?
62
+ end
63
+ end
64
+ end
65
+ end
66
+
67
+ def running?
68
+ return @running
69
+ end
70
+
71
+ def length
72
+ return @workers.length
73
+ end
74
+ alias_method :size, :length
75
+
76
+ def add_worker(worker)
77
+ if worker.nil? || running? || ! worker.behaves_as?(:runnable)
78
+ return false
79
+ else
80
+ @mutex.synchronize {
81
+ @workers << WorkerContext.new(worker)
82
+ }
83
+ return true
84
+ end
85
+ end
86
+
87
+ private
88
+
89
+ def monitor
90
+ loop do
91
+ @mutex.synchronize do
92
+ @workers.each do |context|
93
+ unless context.thread && context.thread.alive?
94
+ context.thread = Thread.new{ context.worker.run }
95
+ context.thread.abort_on_exception = false
96
+ end
97
+ end
98
+ end
99
+ break unless running?
100
+ sleep(@monitor_interval)
101
+ break unless running?
102
+ end
103
+ end
104
+ end
105
+ end