… | |
… | |
217 | |
217 | |
218 | configure nodeid => "eg_receiver", binds => ["*:4040"]; |
218 | configure nodeid => "eg_receiver", binds => ["*:4040"]; |
219 | |
219 | |
220 | my $port = port; |
220 | my $port = port; |
221 | |
221 | |
222 | AnyEvent::MP::Global::register $port, "eg_receivers"; |
222 | grp_reg eg_receivers => $port; |
223 | |
223 | |
224 | rcv $port, test => sub { |
224 | rcv $port, test => sub { |
225 | my ($data, $reply_port) = @_; |
225 | my ($data, $reply_port) = @_; |
226 | |
226 | |
227 | print "Received data: " . $data . "\n"; |
227 | print "Received data: " . $data . "\n"; |
… | |
… | |
340 | talking about the receiver. |
340 | talking about the receiver. |
341 | |
341 | |
342 | Let's look at the next line(s): |
342 | Let's look at the next line(s): |
343 | |
343 | |
344 | my $port = port; |
344 | my $port = port; |
345 | AnyEvent::MP::Global::register $port, "eg_receivers"; |
345 | grp_reg eg_receivers => $port; |
346 | |
346 | |
347 | The C<port> function has already been discussed. It simply creates a new |
347 | The C<port> function has already been discussed. It simply creates a new |
348 | I<port> and returns the I<port ID>. The C<register> function, however, |
348 | I<port> and returns the I<port ID>. The C<grp_reg> function, however, is |
349 | is new: The first argument is the I<port ID> that we want to add to a |
349 | new: The first argument is the name of a I<global group>, and the second |
350 | I<global group>, and its second argument is the name of that I<global |
350 | argument is the I<port ID> to register in that group. group>. |
351 | group>. |
|
|
352 | |
351 | |
353 | You can choose the name of such a I<global group> freely (prefixing your |
352 | You can choose the name of such a I<global group> freely (prefixing your |
354 | package name is highly recommended!). The purpose of such a group is to |
353 | package name is I<highly recommended> however and might be enforce din |
355 | store a set of I<port IDs>. This set is made available throughout the |
354 | future versions!). The purpose of such a group is to store a set of port |
356 | L<AnyEvent::MP> network, so that each node can see which ports belong to |
355 | IDs. This set is made available throughout the L<AnyEvent::MP> network, |
357 | that group. |
356 | so that each node can see which ports belong to that group. |
358 | |
357 | |
359 | Later we will see how the sender looks for the ports in this I<global |
358 | Later we will see how the sender looks for the ports in this global |
360 | group> to send messages to them. |
359 | group to send messages to them. |
361 | |
360 | |
362 | The last step in the example is to set up a receiver callback for those |
361 | The last step in the example is to set up a receiver callback for those |
363 | messages, just as was discussed in the first example. We again match |
362 | messages, just as was discussed in the first example. We again match |
364 | for the tag C<test>. The difference is that this time we don't exit the |
363 | for the tag C<test>. The difference is that this time we don't exit the |
365 | application after receiving the first message. Instead we continue to wait |
364 | application after receiving the first message. Instead we continue to wait |
… | |
… | |
375 | |
374 | |
376 | configure nodeid => "eg_sender", seeds => ["*:4040"]; |
375 | configure nodeid => "eg_sender", seeds => ["*:4040"]; |
377 | |
376 | |
378 | my $find_timer = |
377 | my $find_timer = |
379 | AnyEvent->timer (after => 0, interval => 1, cb => sub { |
378 | AnyEvent->timer (after => 0, interval => 1, cb => sub { |
380 | my $ports = AnyEvent::MP::Global::find "eg_receivers" |
379 | my $ports = grp_get "eg_receivers" |
381 | or return; |
380 | or return; |
382 | |
381 | |
383 | snd $_, test => time |
382 | snd $_, test => time |
384 | for @$ports; |
383 | for @$ports; |
385 | }); |
384 | }); |
… | |
… | |
392 | becomes our seed node. |
391 | becomes our seed node. |
393 | |
392 | |
394 | Next we set up a timer that repeatedly (every second) calls this chunk of |
393 | Next we set up a timer that repeatedly (every second) calls this chunk of |
395 | code: |
394 | code: |
396 | |
395 | |
397 | my $ports = AnyEvent::MP::Global::find "eg_receivers" |
396 | my $ports = grp_get "eg_receivers" |
398 | or return; |
397 | or return; |
399 | |
398 | |
400 | snd $_, test => time |
399 | snd $_, test => time |
401 | for @$ports; |
400 | for @$ports; |
402 | |
401 | |
403 | The only new function here is the C<find> function of |
402 | The only new function here is the C<grp_get> function of |
404 | L<AnyEvent::MP::Global>. It searches in the global group named |
403 | L<AnyEvent::MP::Global>. It searches in the global group named |
405 | C<eg_receivers> for ports. If none are found, it returns C<undef>, which |
404 | C<eg_receivers> for ports. If none are found, it returns C<undef>, which |
406 | makes our code return instantly and wait for the next round, as nobody is |
405 | makes our code return instantly and wait for the next round, as nobody is |
407 | interested in our message. |
406 | interested in our message. |
408 | |
407 | |
409 | As soon as the receiver application has connected and the information |
408 | As soon as the receiver application has connected and the information |
410 | about the newly added port in the receiver has propagated to the sender |
409 | about the newly added port in the receiver has propagated to the sender |
411 | node, C<find> returns an array reference that contains the I<port ID> of |
410 | node, C<grp_get> returns an array reference that contains the I<port ID> of |
412 | the receiver I<port(s)>. |
411 | the receiver I<port(s)>. |
413 | |
412 | |
414 | We then just send a message with a tag and the current time to every |
413 | We then just send a message with a tag and the current time to every |
415 | I<port> in the global group. |
414 | I<port> in the global group. |
416 | |
415 | |
… | |
… | |
662 | rcv $server, privmsg => sub { |
661 | rcv $server, privmsg => sub { |
663 | my ($nick, $msg) = @_; |
662 | my ($nick, $msg) = @_; |
664 | msg "$nick: $msg"; |
663 | msg "$nick: $msg"; |
665 | }; |
664 | }; |
666 | |
665 | |
667 | AnyEvent::MP::Global::register $server, "eg_chat_server"; |
666 | grp_reg eg_chat_server => $server; |
668 | |
667 | |
669 | warn "server ready.\n"; |
668 | warn "server ready.\n"; |
670 | |
669 | |
671 | AnyEvent->condvar->recv; |
670 | AnyEvent->condvar->recv; |
672 | |
671 | |
… | |
… | |
714 | }; |
713 | }; |
715 | |
714 | |
716 | And finally, the server registers itself in the server group, so that |
715 | And finally, the server registers itself in the server group, so that |
717 | clients can find it: |
716 | clients can find it: |
718 | |
717 | |
719 | AnyEvent::MP::Global::register $server, "eg_chat_server"; |
718 | grp_reg eg_chat_server => $server; |
720 | |
719 | |
721 | Well, well... and where is this supervisor stuff? Well... we cheated, |
720 | Well, well... and where is this supervisor stuff? Well... we cheated, |
722 | it's not there. To not overcomplicate the example, we only put it into |
721 | it's not there. To not overcomplicate the example, we only put it into |
723 | the..... CLIENT! |
722 | the..... CLIENT! |
724 | |
723 | |
… | |
… | |
736 | configure; |
735 | configure; |
737 | |
736 | |
738 | my ($client, $server); |
737 | my ($client, $server); |
739 | |
738 | |
740 | sub server_connect { |
739 | sub server_connect { |
741 | my $servernodes = AnyEvent::MP::Global::find "eg_chat_server" |
740 | my $servernodes = grp_get "eg_chat_server" |
742 | or return after 1, \&server_connect; |
741 | or return after 1, \&server_connect; |
743 | |
742 | |
744 | print "\rconnecting...\n"; |
743 | print "\rconnecting...\n"; |
745 | |
744 | |
746 | $client = port { print "\r \r@_\n> " }; |
745 | $client = port { print "\r \r@_\n> " }; |
… | |
… | |
772 | usage. |
771 | usage. |
773 | |
772 | |
774 | The next relevant thing is... finally... the supervisor: |
773 | The next relevant thing is... finally... the supervisor: |
775 | |
774 | |
776 | sub server_connect { |
775 | sub server_connect { |
777 | my $servernodes = AnyEvent::MP::Global::find "eg_chat_server" |
776 | my $servernodes = grp_get "eg_chat_server" |
778 | or return after 1, \&server_connect; |
777 | or return after 1, \&server_connect; |
779 | |
778 | |
780 | This looks up the server in the C<eg_chat_server> global group. If it |
779 | This looks up the server in the C<eg_chat_server> global group. If it |
781 | cannot find it (which is likely when the node is just starting up), |
780 | cannot find it (which is likely when the node is just starting up), |
782 | it will wait a second and then retry. This "wait a bit and retry" |
781 | it will wait a second and then retry. This "wait a bit and retry" |
… | |
… | |
869 | use AnyEvent::MP; |
868 | use AnyEvent::MP; |
870 | use AnyEvent::MP::Global; |
869 | use AnyEvent::MP::Global; |
871 | |
870 | |
872 | configure; |
871 | configure; |
873 | |
872 | |
874 | AnyEvent::MP::Global::register $NODE, "eg_chat_server2"; |
873 | grp_reg eg_chat_server2 => $NODE; |
875 | |
874 | |
876 | my %clients; |
875 | my %clients; |
877 | |
876 | |
878 | sub msg { |
877 | sub msg { |
879 | print "relaying: $_[0]\n"; |
878 | print "relaying: $_[0]\n"; |
… | |
… | |
936 | my $port = port; |
935 | my $port = port; |
937 | |
936 | |
938 | my ($client, $server); |
937 | my ($client, $server); |
939 | |
938 | |
940 | sub server_connect { |
939 | sub server_connect { |
941 | my $servernodes = AnyEvent::MP::Global::find "eg_chat_server2" |
940 | my $servernodes = grp_get "eg_chat_server2" |
942 | or return after 1, \&server_connect; |
941 | or return after 1, \&server_connect; |
943 | |
942 | |
944 | print "\rconnecting...\n"; |
943 | print "\rconnecting...\n"; |
945 | |
944 | |
946 | $client = port { print "\r \r@_\n> " }; |
945 | $client = port { print "\r \r@_\n> " }; |