Commit | Line | Data |
4536f655 |
1 | chapter: Hello world! |
2 | name: A Stem Cell Cookbook |
3 | |
4 | title: A few questions about a simple sub |
5 | |
6 | *: What can you do with this sub? |
7 | *: Can it be networked? |
8 | *: Can it receive messages? |
9 | *: Can it send messages? |
10 | |
11 | code: |
12 | package World1; |
13 | |
14 | sub world_cmd { |
15 | |
16 | return "Hello world!\n"; |
17 | } |
18 | |
19 | PAGE_END |
20 | |
21 | title: A few questions about a simple sub: Answers |
22 | |
23 | *: It can be networked under Stem |
24 | *: It can receive Stem messages |
25 | *: It can send Stem messages |
26 | *: No coding changes need to be made |
27 | |
28 | code: |
29 | package World1; |
30 | |
31 | sub world_cmd { |
32 | |
33 | return "Hello world!\n"; |
34 | } |
35 | |
36 | PAGE_END |
37 | |
38 | title: Loading World1 into Stem |
39 | |
40 | *: Stem configuration files load modules and register Cells |
41 | *: This configuration loads the console module and the World1 module |
42 | *: This is YAML (yaml.org) format and other formats are supported |
43 | *: Start it with: run_stem worlds.stem |
44 | |
45 | code: |
46 | --- #YAML:1.0 |
47 | - |
48 | class: Stem::Console |
49 | - |
50 | class: World1 |
51 | |
52 | PAGE_END |
53 | |
54 | title: Stem overview |
55 | |
56 | *: Stem is a message passing, event driven system |
57 | *: Stem Cells are Perl objects that are registered |
58 | *: Cells can be Perl classes or instantiated objects |
59 | *: Cells can send and receive messages. |
60 | *: Cell classes are loaded and Cells are created via Stem configuration files |
61 | *: Stem Hubs (processes) can support many active Cells |
62 | *: Stem Hubs can be connected in networks on one or more systems |
63 | *: Any Cell can send a message to any other reachable Cell |
64 | |
65 | PAGE_END |
66 | |
67 | title: Stem message delivery |
68 | |
69 | *: Messages are objects with address, content and related fields |
70 | *: The 'to' address of a message is used to identify the destination |
71 | Cell (Perl object) |
72 | *: The destination Cell is invoked by a method and the message is |
73 | its only argument |
74 | *: The method to be called is determined by the message type and command |
75 | *: A 'foo' command message is delivered to method 'foo_cmd' |
76 | *: A 'bar' type message is delivered to method 'bar_in' |
77 | *: Command methods can optionaly return data which is sent back in in |
78 | reply to the sender. |
79 | |
80 | PAGE_END |
81 | |
82 | title: Stem addresses |
83 | |
84 | *: Stem Addresses are name triplets: Hub, Cell, Target |
85 | *: The Hub is the name of Stem process |
86 | *: The Cell is the registered name of the Stem object or class |
87 | *: The target is the unique address of a cloned Cell |
88 | *: The Cell part of an address is required and the Hub and Target are optional |
89 | *: Addresses are written in string form in Stem configuration or from |
90 | the console. |
91 | |
92 | code: |
93 | cell |
94 | hub:cell |
95 | :cell:target |
96 | hub:cell:target |
97 | |
98 | PAGE_END |
99 | |
100 | title: Adding class level data |
101 | |
102 | *: We add class level data and a method to change it |
103 | *: The file lexical variable $name stores the planet's name |
104 | *: The method 'name_cmd' can set that name from the data in a message |
105 | *: A 'name' command message can be sent from the console or anywhere |
106 | *: The configuration file doesn't change other except for the name of the |
107 | class it loads |
108 | |
109 | code: |
110 | <blue> |
111 | package World2; |
112 | use strict ; |
113 | my $name = 'UNKNOWN' ; |
114 | </font> |
115 | sub world_cmd { |
116 | <blue>return "Hello world from $name\n";</font> |
117 | } |
118 | <blue> |
119 | sub name_cmd { |
120 | |
121 | my( $class, $msg ) = @_ ; |
122 | |
123 | my $data = $msg->data() ; |
124 | |
125 | return unless $data ; |
126 | |
127 | $name = ${$data} ; |
128 | |
129 | return ; |
130 | } |
131 | </font> |
132 | PAGE_END |
133 | |
134 | title: A basic object level Cell |
135 | |
136 | *: This module has an attribute specification so we can construct an object |
137 | *: If no planet name is passed to the constructor, it will be named 'X' |
138 | *: It also has a constructor method new() that is called from the configuration |
139 | *: The hello_cmd method now returns the object data in the planet attribute |
140 | |
141 | code: |
142 | package World3; |
143 | |
144 | use strict ; |
145 | |
146 | <blue>my $attr_spec = [ |
147 | { |
148 | 'name' => 'planet', |
149 | 'default' => 'X', |
150 | }, |
151 | ] ; |
152 | |
153 | sub new { |
154 | my ( $class ) = shift ; |
155 | my $self = Stem::Class::parse_args( $attr_spec, @_ ) ; |
156 | return ( $self ); |
157 | }</font> |
158 | |
159 | sub hello_cmd { |
160 | |
161 | <blue>my( $self ) = @_ ; |
162 | |
163 | return "Hello world from $self->{'planet'}\n" ;</font> |
164 | } |
165 | |
166 | PAGE_END |
167 | |
168 | title: Configuration for object level cells |
169 | |
170 | *: We add a 'name' field which is the cell part of the address for this |
171 | object Cell |
172 | *: We add an 'args' field whose values are passed to the new() method |
173 | *: The object is constructed and registered with the selected 'name' |
174 | *: The initial value of the planet name can be set in the arguments |
175 | *: We created two object cells here using the same class but the first |
176 | uses the default planet name of 'X' and the second is named 'venus' |
177 | |
178 | code: |
179 | --- #YAML:1.0 |
180 | - |
181 | class: Stem::Console |
182 | - |
183 | <blue> class: World3 |
184 | name: planet1 |
185 | args: [] |
186 | - |
187 | class: World3 |
188 | <blue> name: planet2 |
189 | args: |
190 | planet: venus</font> |
191 | |
192 | PAGE_END |
193 | |
194 | title: Changing object data |
195 | |
196 | *: All that is needed is a name_cmd method very similar to the one in World2 |
197 | *: It just changes the value in the cell itself |
198 | *: The configuration file needs to only change the class and cell names |
199 | |
200 | code: |
201 | package World4 ; |
202 | |
203 | use strict ; |
204 | |
205 | my $attr_spec = [ |
206 | { |
207 | 'name' => 'planet', |
208 | 'default' => 'X', |
209 | }, |
210 | ] ; |
211 | |
212 | sub new { |
213 | my ( $class ) = shift ; |
214 | my $self = Stem::Class::parse_args( $attr_spec, @_ ) ; |
215 | return ( $self ); |
216 | } |
217 | |
218 | sub hello_cmd { |
219 | |
220 | my( $self ) = @_ ; |
221 | |
222 | return "Hello world from $self->{'planet'}\n" ; |
223 | } |
224 | <blue> |
225 | sub name_cmd { |
226 | |
227 | my ( $self, $msg ) = @_ ; |
228 | |
229 | my $data = $msg->data() ; |
230 | |
231 | return unless $data ; |
232 | |
233 | $self->{'planet'} = ${$data} ; |
234 | |
235 | return ; |
236 | } |
237 | |
238 | </font> |
239 | |
240 | |
241 | PAGE_END |
242 | |
243 | title: Cloning object cells |
244 | |
245 | *: Cloned Cells are similar to sessions or state objects but are much |
246 | simpler to create and manage |
247 | *: Object Cells that use the cloning services of Stem::Cell are called |
248 | parent Cells |
249 | *: All cloned Cells are owned by the Parent cell |
250 | *: When a parent Cell is triggered (via a message or internal call), it |
251 | copies and registers the clone with a unique target address |
252 | *: The Stem::Cell module is inherited and it handles the 'cell_trigger' |
253 | command message |
254 | *: The specification must include a Stem::Cell class attribute |
255 | |
256 | Note that it has its own default |
257 | *: A callback to the 'triggered_cell' method is made in a newly cloned cell |
258 | |
259 | code: |
260 | package World5 ; |
261 | |
262 | <blue>use base 'Stem::Cell' ;</font> |
263 | |
264 | use strict ; |
265 | |
266 | my $attr_spec = [ |
267 | { |
268 | 'name' => 'planet', |
269 | 'default' => 'X', |
270 | }, |
271 | <blue>{ |
272 | 'name' => 'cell_attr', |
273 | 'class' => 'Stem::Cell', |
274 | },</font> |
275 | ] ; |
276 | |
277 | sub new { |
278 | my ( $class ) = shift ; |
279 | my $self = Stem::Class::parse_args( $attr_spec, @_ ) ; |
280 | return ( $self ); |
281 | } |
282 | |
283 | sub hello_cmd { |
284 | |
285 | my( $self ) = @_ ; |
286 | |
287 | return "Hello world from $self->{'planet'}\n" ; |
288 | } |
289 | <blue> |
290 | sub triggered_cell { |
291 | |
292 | my( $self ) = @_ ; |
293 | |
294 | $self->{'planet'} = $self->cell_get_args( 'planet' ) || 'pluto' ; |
295 | |
296 | return; |
297 | } |
298 | </font> |
299 | |
300 | sub name_cmd { |
301 | |
302 | my ( $self, $msg ) = @_ ; |
303 | |
304 | my $data = $msg->data() ; |
305 | |
306 | return unless $data ; |
307 | |
308 | $self->{'planet'} = ${$data} ; |
309 | |
310 | return ; |
311 | } |
312 | |
313 | PAGE_END |
314 | |
315 | title: Cloning cell configuration |
316 | |
317 | *: This is the similar to the World4 configuration but we added the |
318 | 'cell_attr' attribute and set its 'cloneable' flag to true |
319 | |
320 | code: |
321 | |
322 | - |
323 | class: World5 |
324 | name: planet5 |
325 | args: |
326 | planet: jupiter |
327 | <blue>cell_attr: |
328 | cloneable: 1 |
329 | </font> |
330 | |
331 | PAGE_END |