ntl-actor 0.6.2 → 1.0.0.pre1

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 (68) hide show
  1. checksums.yaml +4 -4
  2. data/lib/actor.rb +45 -19
  3. data/lib/actor/actor.rb +12 -132
  4. data/lib/actor/build.rb +36 -0
  5. data/lib/actor/controls.rb +7 -7
  6. data/lib/actor/messages.rb +20 -4
  7. data/lib/actor/messaging/address.rb +26 -0
  8. data/lib/actor/messaging/address/controls.rb +11 -0
  9. data/lib/actor/messaging/address/dependency.rb +13 -0
  10. data/lib/actor/messaging/address/none.rb +33 -0
  11. data/lib/actor/messaging/message.rb +39 -1
  12. data/lib/actor/messaging/message/name.rb +33 -0
  13. data/lib/actor/messaging/publisher.rb +39 -0
  14. data/lib/actor/messaging/publisher/assertions.rb +11 -0
  15. data/lib/actor/messaging/publisher/dependency.rb +13 -0
  16. data/lib/actor/messaging/publisher/substitute.rb +62 -0
  17. data/lib/actor/messaging/queue.rb +21 -0
  18. data/lib/actor/messaging/queue/substitute.rb +53 -0
  19. data/lib/actor/messaging/reader.rb +32 -0
  20. data/lib/actor/messaging/reader/assertions.rb +25 -0
  21. data/lib/actor/messaging/reader/dependency.rb +13 -0
  22. data/lib/actor/messaging/reader/substitute.rb +31 -0
  23. data/lib/actor/messaging/writer.rb +28 -0
  24. data/lib/actor/messaging/writer/dependency.rb +13 -0
  25. data/lib/actor/messaging/writer/substitute.rb +45 -0
  26. data/lib/actor/module/dependencies.rb +30 -0
  27. data/lib/actor/module/dependencies/assertions.rb +23 -0
  28. data/lib/actor/module/handler.rb +31 -0
  29. data/lib/actor/module/handler/macro.rb +13 -0
  30. data/lib/actor/module/handler/method_name.rb +13 -0
  31. data/lib/actor/module/include_assertions.rb +18 -0
  32. data/lib/actor/module/run_loop.rb +19 -0
  33. data/lib/actor/module/start.rb +27 -0
  34. data/lib/actor/module/suspend_resume.rb +36 -0
  35. data/lib/actor/module/suspend_resume/assertions.rb +26 -0
  36. data/lib/actor/module/suspend_resume/configure.rb +13 -0
  37. data/lib/actor/module/suspend_resume/controls.rb +17 -0
  38. data/lib/actor/module/suspend_resume/handle.rb +17 -0
  39. data/lib/actor/module/suspend_resume/initialize.rb +13 -0
  40. data/lib/actor/start.rb +34 -34
  41. data/lib/actor/supervisor.rb +60 -71
  42. data/lib/actor/supervisor/address/get.rb +15 -0
  43. data/lib/actor/supervisor/address/put.rb +13 -0
  44. data/lib/actor/supervisor/address/registry.rb +7 -0
  45. data/lib/actor/supervisor/assertions.rb +20 -0
  46. metadata +42 -28
  47. data/lib/actor/address.rb +0 -18
  48. data/lib/actor/controls/actor.rb +0 -89
  49. data/lib/actor/controls/address.rb +0 -48
  50. data/lib/actor/controls/error.rb +0 -11
  51. data/lib/actor/controls/message.rb +0 -39
  52. data/lib/actor/controls/message/attribute.rb +0 -17
  53. data/lib/actor/controls/thread.rb +0 -9
  54. data/lib/actor/controls/uuid.rb +0 -15
  55. data/lib/actor/destructure.rb +0 -23
  56. data/lib/actor/duration.rb +0 -7
  57. data/lib/actor/future.rb +0 -38
  58. data/lib/actor/handle_macro.rb +0 -37
  59. data/lib/actor/messaging/read.rb +0 -54
  60. data/lib/actor/messaging/read/substitute.rb +0 -33
  61. data/lib/actor/messaging/write.rb +0 -26
  62. data/lib/actor/messaging/write/substitute.rb +0 -39
  63. data/lib/actor/observers.rb +0 -45
  64. data/lib/actor/router.rb +0 -94
  65. data/lib/actor/stream.rb +0 -36
  66. data/lib/actor/substitutes/kernel.rb +0 -23
  67. data/lib/actor/substitutes/thread.rb +0 -39
  68. data/lib/actor/substitutes/thread_group.rb +0 -26
@@ -0,0 +1,23 @@
1
+ module Actor
2
+ module Module
3
+ module Dependencies
4
+ module Assertions
5
+ def dependencies_configured?
6
+ address_configured? and reader_configured? and writer_configured?
7
+ end
8
+
9
+ def address_configured?
10
+ address.instance_of? Messaging::Address
11
+ end
12
+
13
+ def reader_configured?
14
+ reader.instance_of? Messaging::Reader
15
+ end
16
+
17
+ def writer_configured?
18
+ writer.instance_of? Messaging::Writer
19
+ end
20
+ end
21
+ end
22
+ end
23
+ end
@@ -0,0 +1,31 @@
1
+ module Actor
2
+ module Module
3
+ module Handler
4
+ def self.included cls
5
+ cls.class_exec do
6
+ extend Macro
7
+ end
8
+ end
9
+
10
+ def handle message
11
+ handler_method_name = MethodName.get message
12
+
13
+ return unless handler_method_name and respond_to? handler_method_name
14
+
15
+ handler_method = method handler_method_name
16
+
17
+ if handler_method.arity == 0
18
+ return_value = handler_method.()
19
+ else
20
+ return_value = handler_method.(message)
21
+ end
22
+
23
+ if Messaging::Message === return_value
24
+ writer.write return_value, address
25
+ end
26
+
27
+ return_value
28
+ end
29
+ end
30
+ end
31
+ end
@@ -0,0 +1,13 @@
1
+ module Actor
2
+ module Module
3
+ module Handler
4
+ module Macro
5
+ def handle message_pattern, &handler
6
+ method_name = MethodName.get message_pattern
7
+
8
+ define_method method_name, &handler
9
+ end
10
+ end
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,13 @@
1
+ module Actor
2
+ module Module
3
+ module Handler
4
+ module MethodName
5
+ def self.get message_pattern
6
+ message_name = Messaging::Message::Name.get message_pattern
7
+
8
+ :"handle_#{message_name}"
9
+ end
10
+ end
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,18 @@
1
+ module Actor
2
+ module Module
3
+ module IncludeAssertions
4
+ def self.call assertions_module, receiver
5
+ receiver.module_exec do
6
+ unless const_defined? :Assertions, false
7
+ receiver_assertions_module = ::Module.new
8
+ const_set :Assertions, receiver_assertions_module
9
+ end
10
+
11
+ receiver_assertions_module ||= const_get :Assertions
12
+
13
+ receiver_assertions_module.include assertions_module
14
+ end
15
+ end
16
+ end
17
+ end
18
+ end
@@ -0,0 +1,19 @@
1
+ module Actor
2
+ module Module
3
+ module RunLoop
4
+ def run_loop &supplemental_action
5
+ loop do
6
+ message = reader.read
7
+
8
+ handle message
9
+
10
+ supplemental_action.() if supplemental_action
11
+ end
12
+ end
13
+
14
+ def handle_stop(_=nil)
15
+ raise StopIteration
16
+ end
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,27 @@
1
+ module Actor
2
+ module Module
3
+ module Start
4
+ def start *arguments, include: nil, **keyword_arguments, &block
5
+ arguments << keyword_arguments if keyword_arguments.any?
6
+
7
+ actor, thread = Actor::Start.(self, *arguments, &block)
8
+
9
+ address = actor.address
10
+
11
+ if include
12
+ return_values = [address]
13
+
14
+ Array(include).each do |label|
15
+ argument = { :thread => thread, :actor => actor }.fetch label
16
+
17
+ return_values << argument
18
+ end
19
+
20
+ return return_values
21
+ else
22
+ return address
23
+ end
24
+ end
25
+ end
26
+ end
27
+ end
@@ -0,0 +1,36 @@
1
+ module Actor
2
+ module Module
3
+ module SuspendResume
4
+ def self.included cls
5
+ cls.class_exec do
6
+ prepend Configure
7
+ prepend Handle
8
+ prepend Initialize
9
+
10
+ IncludeAssertions.(Assertions, self)
11
+ end
12
+ end
13
+
14
+ attr_accessor :suspended
15
+ attr_writer :suspend_queue
16
+
17
+ def handle_suspend
18
+ self.suspended = true
19
+ end
20
+
21
+ def handle_resume
22
+ self.suspended = false
23
+
24
+ until suspend_queue.empty?
25
+ deferred_message = suspend_queue.deq
26
+
27
+ writer.write deferred_message, address
28
+ end
29
+ end
30
+
31
+ def suspend_queue
32
+ @suspend_queue ||= Messaging::Queue::Substitute.build
33
+ end
34
+ end
35
+ end
36
+ end
@@ -0,0 +1,26 @@
1
+ module Actor
2
+ module Module
3
+ module SuspendResume
4
+ module Assertions
5
+ def message_deferred? message=nil, wait: nil
6
+ non_block = wait == false
7
+
8
+ begin
9
+ msg = suspend_queue.deq true
10
+ rescue ThreadError
11
+ end
12
+
13
+ if message.nil?
14
+ msg ? true : false
15
+ else
16
+ msg == message
17
+ end
18
+ end
19
+
20
+ def suspended?
21
+ @suspended == true
22
+ end
23
+ end
24
+ end
25
+ end
26
+ end
@@ -0,0 +1,13 @@
1
+ module Actor
2
+ module Module
3
+ module SuspendResume
4
+ module Configure
5
+ def configure
6
+ self.suspend_queue = Messaging::Queue.get
7
+
8
+ super
9
+ end
10
+ end
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,17 @@
1
+ module Actor
2
+ module Module
3
+ module SuspendResume
4
+ module Controls
5
+ def suspend!
6
+ self.suspended = true
7
+ end
8
+
9
+ def defer_message *messages
10
+ messages.each do |message|
11
+ suspend_queue.enq message
12
+ end
13
+ end
14
+ end
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,17 @@
1
+ module Actor
2
+ module Module
3
+ module SuspendResume
4
+ module Handle
5
+ def handle message
6
+ self.suspended = false if Messages::Resume === message
7
+
8
+ if suspended
9
+ suspend_queue.enq message, true
10
+ else
11
+ super
12
+ end
13
+ end
14
+ end
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,13 @@
1
+ module Actor
2
+ module Module
3
+ module SuspendResume
4
+ module Initialize
5
+ def initialize *;
6
+ @suspended = false
7
+
8
+ super
9
+ end
10
+ end
11
+ end
12
+ end
13
+ end
data/lib/actor/start.rb CHANGED
@@ -1,57 +1,57 @@
1
1
  module Actor
2
2
  class Start
3
- attr_writer :supervisor_address
4
- attr_writer :thread_class
5
- attr_writer :writer
6
-
7
- def self.build supervisor_address: nil
8
- supervisor_address ||= Supervisor.address
9
-
10
- instance = new
11
- instance.supervisor_address = supervisor_address
12
- instance.thread_class = Thread
13
- Messaging::Write.configure instance
14
- instance
15
- end
3
+ include Messaging::Writer::Dependency
4
+
5
+ attr_reader :actor
6
+ attr_accessor :supervisor_address
16
7
 
17
- def self.call actor, address, supervisor_address: nil
18
- instance = build supervisor_address: supervisor_address
19
- instance.(actor, address)
8
+ def initialize actor
9
+ @actor = actor
20
10
  end
21
11
 
22
- def call actor, address
23
- address ||= Address.build
12
+ def self.call actor_class, *arguments, &block
13
+ actor = Build.(actor_class, *arguments, &block)
24
14
 
25
- start = Messages::Start.new
26
- writer.(start, address)
15
+ instance = new actor
16
+ instance.writer = Messaging::Writer.new
17
+ instance.supervisor_address = Supervisor::Address::Get.()
18
+ instance.()
19
+ end
27
20
 
28
- actor_started = Messages::ActorStarted.new address
29
- writer.(actor_started, supervisor_address)
21
+ def call
22
+ writer.write Messages::Start, address
23
+
24
+ thread = Thread.new do
25
+ actor_started
30
26
 
31
- thread = thread_class.new do
32
27
  begin
33
- actor.start
28
+ actor.run_loop
29
+ actor_stopped
34
30
  rescue => error
35
- actor_crashed = Messages::ActorCrashed.new error
36
- writer.(actor_crashed, supervisor_address)
31
+ actor_crashed error
37
32
  end
38
33
  end
39
34
 
40
- thread.name = actor.class.name
35
+ return actor, thread
36
+ end
41
37
 
42
- thread
38
+ def actor_crashed error
39
+ actor_crashed = Messages::ActorCrashed.new error
40
+ writer.write actor_crashed, supervisor_address
43
41
  end
44
42
 
45
- def supervisor_address
46
- @supervisor_address ||= Address::None
43
+ def actor_started
44
+ actor_started = Messages::ActorStarted.new address
45
+ writer.write actor_started, supervisor_address
47
46
  end
48
47
 
49
- def thread_class
50
- @thread_class ||= Substitutes::Thread
48
+ def actor_stopped
49
+ actor_stopped = Messages::ActorStopped.new address
50
+ writer.write actor_stopped, supervisor_address
51
51
  end
52
52
 
53
- def writer
54
- @writer ||= Messaging::Write::Substitute.new
53
+ def address
54
+ actor.address
55
55
  end
56
56
  end
57
57
  end
@@ -1,118 +1,107 @@
1
1
  module Actor
2
2
  class Supervisor
3
- include Actor
3
+ include Module::Dependencies
4
+ include Module::Handler
5
+ include Module::RunLoop
4
6
 
5
- attr_reader :assembly
6
- attr_writer :broadcast_address
7
+ include Messaging::Publisher::Dependency
8
+
9
+ attr_accessor :actor_count
10
+ attr_writer :assembly_block
7
11
  attr_accessor :error
8
12
  attr_writer :thread_group
9
- attr_writer :router_address
10
13
 
11
- def initialize &assembly
12
- @assembly = assembly
14
+ def initialize
15
+ @actor_count = 0
13
16
  end
14
17
 
15
- class << self
16
- attr_accessor :address
17
-
18
- def run &assembly
19
- self.address = Address.build
20
-
21
- _, thread = start include: %i(thread), &assembly
18
+ def self.build &assembly_block
19
+ instance = new
20
+ instance.assembly_block = assembly_block
21
+ instance.configure
22
+ instance
23
+ end
22
24
 
23
- thread.join
24
- end
25
+ def self.start &assembly_block
26
+ thread = Thread.new do
27
+ thread_group = Thread.current.group
25
28
 
26
- def build &assembly
27
- instance = new &assembly
28
- instance.configure
29
- instance
30
- end
29
+ prior_thread_count = thread_group.list.count
31
30
 
32
- def start include: nil, &assembly
33
- instance = build &assembly
31
+ instance = build &assembly_block
34
32
 
35
- start = Messages::Start.new
36
- instance.writer.(start, address)
33
+ thread_count = thread_group.list.count
37
34
 
38
- thread = Thread.new do
39
- instance.start
35
+ unless thread_count > prior_thread_count
36
+ raise NoActorsStarted, "Assembly block must start at least one actor"
40
37
  end
41
38
 
42
- thread.name = "Supervisor"
43
-
44
- Destructure.(address, include, { :thread => thread, :actor => instance })
39
+ instance.run_loop
45
40
  end
41
+
42
+ thread.join
46
43
  end
47
44
 
48
- handle :start do
49
- thread_group.add Thread.current
50
- thread_group.enclose
45
+ def configure
46
+ self.thread_group = Thread.current.group
51
47
 
52
- assembly.(self) if assembly
48
+ Address::Put.(address)
53
49
 
54
- :continue
55
- end
50
+ assembly_block.(self)
56
51
 
57
- handle :continue do
58
- if actor_threads.empty?
59
- raise error if error
52
+ self.publisher = Messaging::Publisher.build
53
+ end
60
54
 
61
- :stop
62
- else
63
- sleep Duration.millisecond
55
+ handle Messages::ActorStarted do |message|
56
+ publisher.register message.address
64
57
 
65
- :continue
66
- end
58
+ self.actor_count += 1
67
59
  end
68
60
 
69
- handle :actor_started do |message|
70
- reader = Messaging::Read.build broadcast_address
71
- output_address = message.actor_address
61
+ handle Messages::ActorStopped do |message|
62
+ publisher.unregister message.address
72
63
 
73
- add_route = Router::AddRoute.new reader, output_address
64
+ self.actor_count -= 1
74
65
 
75
- writer.(add_route, router_address)
66
+ if actor_count.zero?
67
+ Messages::Stop
68
+ end
76
69
  end
77
70
 
78
- handle :actor_crashed do |message|
71
+ handle Messages::ActorCrashed do |message|
79
72
  self.error ||= message.error
80
73
 
81
- :shutdown
82
- end
83
-
84
- handle :shutdown do
85
- stop = Messages::Stop.new
74
+ self.actor_count -= 1
86
75
 
87
- writer.(stop, broadcast_address)
88
- writer.(stop, router_address)
76
+ Messages::Shutdown
77
+ end
89
78
 
90
- :continue
79
+ handle Messages::Shutdown do
80
+ publisher.publish Messages::Stop
91
81
  end
92
82
 
93
- def actor_threads
94
- list = thread_group.list
95
- list.delete Thread.current
96
- list
83
+ handle Messages::Suspend do |message|
84
+ publisher.publish message
97
85
  end
98
86
 
99
- def configure
100
- self.broadcast_address = Address.build
101
- self.router_address = Router.start
102
- self.thread_group = ThreadGroup.new
103
- self.address = self.class.address
87
+ handle Messages::Resume do |message|
88
+ publisher.publish message
104
89
  end
105
90
 
106
- def broadcast_address
107
- @broadcast_address ||= Address::None
91
+ handle Messages::Stop do |stop|
92
+ raise error if error
93
+
94
+ super stop
108
95
  end
109
96
 
110
- def router_address
111
- @router_address ||= Address::None
97
+ def assembly_block
98
+ @assembly_block ||= proc { }
112
99
  end
113
100
 
114
101
  def thread_group
115
- @thread_group ||= Substitutes::ThreadGroup.new
102
+ @thread_group ||= ThreadGroup::Default
116
103
  end
104
+
105
+ NoActorsStarted = Class.new StandardError
117
106
  end
118
107
  end