concurrent-ruby 0.2.0 → 0.2.1

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 (57) hide show
  1. data/LICENSE +21 -21
  2. data/README.md +275 -275
  3. data/lib/concurrent.rb +28 -28
  4. data/lib/concurrent/agent.rb +114 -114
  5. data/lib/concurrent/cached_thread_pool.rb +131 -129
  6. data/lib/concurrent/defer.rb +65 -65
  7. data/lib/concurrent/event.rb +60 -60
  8. data/lib/concurrent/event_machine_defer_proxy.rb +23 -23
  9. data/lib/concurrent/executor.rb +96 -95
  10. data/lib/concurrent/fixed_thread_pool.rb +99 -95
  11. data/lib/concurrent/functions.rb +120 -120
  12. data/lib/concurrent/future.rb +42 -42
  13. data/lib/concurrent/global_thread_pool.rb +16 -16
  14. data/lib/concurrent/goroutine.rb +29 -29
  15. data/lib/concurrent/null_thread_pool.rb +22 -22
  16. data/lib/concurrent/obligation.rb +67 -67
  17. data/lib/concurrent/promise.rb +174 -174
  18. data/lib/concurrent/reactor.rb +166 -166
  19. data/lib/concurrent/reactor/drb_async_demux.rb +83 -83
  20. data/lib/concurrent/reactor/tcp_sync_demux.rb +131 -131
  21. data/lib/concurrent/supervisor.rb +105 -100
  22. data/lib/concurrent/thread_pool.rb +76 -76
  23. data/lib/concurrent/utilities.rb +32 -32
  24. data/lib/concurrent/version.rb +3 -3
  25. data/lib/concurrent_ruby.rb +1 -1
  26. data/md/agent.md +123 -123
  27. data/md/defer.md +174 -174
  28. data/md/event.md +32 -32
  29. data/md/executor.md +187 -187
  30. data/md/future.md +83 -83
  31. data/md/goroutine.md +52 -52
  32. data/md/obligation.md +32 -32
  33. data/md/promise.md +227 -227
  34. data/md/thread_pool.md +224 -224
  35. data/spec/concurrent/agent_spec.rb +386 -386
  36. data/spec/concurrent/cached_thread_pool_spec.rb +125 -125
  37. data/spec/concurrent/defer_spec.rb +195 -195
  38. data/spec/concurrent/event_machine_defer_proxy_spec.rb +256 -256
  39. data/spec/concurrent/event_spec.rb +134 -134
  40. data/spec/concurrent/executor_spec.rb +200 -200
  41. data/spec/concurrent/fixed_thread_pool_spec.rb +83 -83
  42. data/spec/concurrent/functions_spec.rb +217 -217
  43. data/spec/concurrent/future_spec.rb +108 -108
  44. data/spec/concurrent/global_thread_pool_spec.rb +38 -38
  45. data/spec/concurrent/goroutine_spec.rb +67 -67
  46. data/spec/concurrent/null_thread_pool_spec.rb +57 -54
  47. data/spec/concurrent/obligation_shared.rb +132 -132
  48. data/spec/concurrent/promise_spec.rb +312 -312
  49. data/spec/concurrent/reactor/drb_async_demux_spec.rb +196 -196
  50. data/spec/concurrent/reactor/tcp_sync_demux_spec.rb +410 -410
  51. data/spec/concurrent/reactor_spec.rb +364 -364
  52. data/spec/concurrent/supervisor_spec.rb +269 -258
  53. data/spec/concurrent/thread_pool_shared.rb +204 -204
  54. data/spec/concurrent/utilities_spec.rb +74 -74
  55. data/spec/spec_helper.rb +32 -32
  56. metadata +20 -16
  57. checksums.yaml +0 -7
@@ -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,100 +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
- @running = true
33
- @monitor = Thread.new{ monitor }
34
- Thread.pass
35
- end
36
-
37
- def run
38
- raise StandardError.new('already running') if running?
39
- @running = true
40
- monitor
41
- end
42
-
43
- def stop
44
- return true unless running?
45
- @running = false
46
- @mutex.synchronize do
47
- Thread.kill(@monitor) unless @monitor.nil?
48
- @monitor = nil
49
-
50
- until @workers.empty?
51
- context = @workers.pop
52
- begin
53
- context.worker.stop
54
- Thread.pass
55
- rescue Exception => ex
56
- # suppress
57
- ensure
58
- Thread.kill(context.thread) unless context.thread.nil?
59
- end
60
- end
61
- end
62
- end
63
-
64
- def running?
65
- return @running
66
- end
67
-
68
- def length
69
- return @workers.length
70
- end
71
- alias_method :size, :length
72
-
73
- def add_worker(worker)
74
- if worker.nil? || running? || ! worker.behaves_as?(:runnable)
75
- return false
76
- else
77
- @mutex.synchronize {
78
- @workers << WorkerContext.new(worker)
79
- }
80
- return true
81
- end
82
- end
83
-
84
- private
85
-
86
- def monitor
87
- loop do
88
- @mutex.synchronize do
89
- @workers.each do |context|
90
- unless context.thread && context.thread.alive?
91
- context.thread = Thread.new{ context.worker.run }
92
- context.thread.abort_on_exception = false
93
- end
94
- end
95
- end
96
- sleep(@monitor_interval)
97
- end
98
- end
99
- end
100
- 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