Actor Framework Documents

cancel
Showing results for 
Search instead for 
Did you mean: 

Data Broadcasting Library

This library provides extensions to the Actor Framework to facilitate the broadcast of messages from one actor to several others. Listeners subscribe to a message when they want to receive it from the Broadcaster, and they unsubscribe when they want to stop receiving it. The library provides a set of common interfaces that decouple Broadcasters from Listeners so any two actors in a messaging hierarchy can communicate via broadcast without having the same caller.

This library extends the Actor Framework; it does not modify the core framework in any way, so it may be used in existing projects as well as new ones.

Classifying Messages by their Intent

An actor shouldn't broadcast any kind of message anywhere; that breaks the purpose of the Actor Framework and actor-oriented design because it allows the actor to call state-changing methods on actors other than its caller and callees. When designing a message,  first decide its intent. Three kinds of messaging intent were identified in this discussion:

  1. Command (or Request): A message sent to a callee actor to tell it to do something. Because actor-oriented design allows the recipient of this message to ignore it, cache it for later processing, or act on it at will; it may also be called a Request. In AF, Commands are implemented as simple concrete classes with both data and a method that executes an action on the recipient.
  2. Status (or Event): A message sent to a parent actor to notify it that something happened. Note the past-tense language! Actors aren't allowed to control their parents, so they can't send Commands up the chain; they can only notify their parents of the occurrence of something and let the parent decide how (and even whether) to handle it. In AF, these messages should be designed as loosely-coupled pairs, with an oubound class in the child actor that holds the message data and an inbound message in the parent actor that holds the message method. The parent actor's concrete message inherits from the child actor's abstract message.
  3. Data: A message sent anywhere that only carries data; it does not dictate what should be done with the data, nor does it imply any state information along with the data. (In contrast, Commands dictate action and Events notify state changes.) This kind of message can be safely sent to any other actor, given the recipient's unique identifier, and it can be sent with any multiplicity. In AF, that means the sender needs to have a copy of the Enqueuer for every recipient of the message. If the sender wants to broadcast the message to multiple listeners, it just needs those listeners to register their Enqueuers with him. The implementation of a Data message in AF is highly dependent on minimizing coupling between otherwise unrelated actors, so it also uses a loosely-coupled message pair like the Event message.

Documentation

Documentation for the library and the included example program is attached. A class diagram of the library's structure is provided. A "messaging diagram" is also provided to explain the runtime behavior of the example program. The messaging diagram is a UML sequence diagram that shows the lifetimes, activity states, and interactions of each actor's message handler. The user interfaces and other Actor Core.vi override behaviors for actors are not shown in the diagram. The following legend explains the conventions used in the messaging diagram:

Messaging Diagram Legend.png

  • A box over an actor's lifetime indicates that the actor's message handler is busy and cannot process incoming messages.
  • Arrows with a closed head represent synchronous interactions, like a blocking method call or a Reply Message. Arrows with open heads represent asynchronous interactions; any other type of Message.
  • Right-facing solid arrows represent a caller commanding with its callee, and left-facing solid arrows represent the callee sending status to its caller.
  • Dotted arrows represent the broadcast of data, which can be sent to any registered actor in the system.

Installation

The library is distributed as a VI Package. You must install VI Package Manager to install the library.

Dependencies

v1.0.0 of this library depends on the Actor Framework v4.0.1. It is provided for LV 2011 and LV 2012.

  • LV 2011 users must install the Actor Framework and can download it here.
  • LV 2012 users may have to upgrade the Actor Framework to v.4.0.1 and can download it here.

v1.1.0 of the library depends on the Actor Framework that is installed in <vi.lib>. It is provided for LV 2013+.

How to Use this Library

As with Actor Framework.lvlib, It is recommended that you add the library to your LV Project in order to more easily access its methods and inherit from its classes.

example_project.png

The library includes tools for broadcasting a data message to listeners (Broadcast Registry.lvclass), subscribing to and unsubscribing from a data broadcast (Subscription Token.lvclass), and common types for messages involved in the broadcast mechanism:

  • The Registration Msg  is sent from a Listener to a Broadcaster to register that listener for a data broadcast.
  • The Unregistration Msg  is sent to unregister a listener from a broadcast.
  • The Data Msg is sent from a Broadcaster to a registered Listener when broadcasting.

In order to decouple Listeners from Broadcasters, Registration and Unregistration messages are stored inside a Subscription Token. The Subscription Token is created by a Broadcaster and shared, via messages sent through the actor call chain, with Listeners. A Listener uses methods in the Subscription Token to send Registration/Unregistration messages to the Broadcaster without having any direct coupling to that Broadcaster.

A Registration Msg holds the Listener's enqueuer and an instance of the concrete Data Msg that it will receive from the Broadcaster. When the Registration message is sent to the Broadcaster, the Broadcaster reads these elements and stores them in its Broadcast Registry to be referenced whenever it broadcasts data. An Unregistration Msg holds the Listener's enqueuer as well. When the message is sent to the Broadcaster, the Broadcaster uses the enqueuer to find and remove that Listener's registration from its Broadcast Registry.

Example Program

An example program is included with the library and can be found at <labview>\examples\Staab\AF Data Broadcasting\Simple Example\Simple Example.lvproj . It can also be found using the LabVIEW Example Finder when browsing by directory structure.

example.png

The program contains an actor that broadcasts two kinds of data, 3-axis coordinates and temperature, and listeners for each kind of data. Any number of listeners may be launched simultaneously; each will register for its broadcast and display updates in real time.

screenshot.png

Where is the Library?

The library can be downloaded from LAVAG.org here. It is provided under the 2-clause BSD license.

Comments
helcio
Member
Member
on

The library is not there!

Active Participant
Active Participant
on

Edit: I spoke with one of the LAVA admins, and the link should be fixed now.

helcio
Member
Member
on

Hi,

Download works fine now!

By the way, which tool did you use to make the messaging diagrams?

Thanks for posting the library!

Active Participant
Active Participant
on
helcio
Member
Member
on

Hi David,

I am having trouble to install the data broadcast library in labview 2013. Probably because the Actor Framework version in labview 2013 is newer than the version that your library requires. Do you have a updated version of the data broadcast library that would install without problems in labview 2013?

thanks

Active Participant
Active Participant
on

I haven't upgraded the library. I'll look into it when I get back from vacation the week of 10/7. Can you post a screenshot of the VIPM installation failure message or summary?

Thanks for letting me know about the incompatibility.

Drew.Rankin
Member
Member
on

Just downloaded this and the only thing that was different from 2012 AF is the final error code terminal on the Stop core. This was specified as "Required" while the AF Stop Core on my install is "Recommended". Changed the method connector panes in the example and it wirked well. Haven't looked at this in 2013 yet though. Haven't gotten a customer project in '13 yet.

Drew

AristosQueue (NI)
NI Employee (retired)
on

2013 should be fully backward compatible with 2012. At least, it tested that way and no one has reported any bugs contrariwise. 😉

helcio
Member
Member
on

During the instalation of the data broadcast library with the VIPM, the actor framework 4.1.0.29 is grayed out, probably because it was not included in the library when the package was built.

data broadcast library.png

     Then when I install and try to launch the example I get conflicts (I have the actor framework 4.3.0.35 installed)

data broadcast library_2.png

Then, in the end:

data broadcast library_3.png

I I hope this helps to troubleshoot what is going on.

thanks

Active Participant
Active Participant
on

helcio wrote:


                       

During the instalation of the data broadcast library with the VIPM, the actor framework 4.1.0.29 is grayed out, probably because it was not included in the library when the package was built.

Fixed. The package depended on AF existing in <user.lib>, but that has changed. I had to upgrade the entire project to LV 2013 to reflect the new dependency locations.

Use v1.0.0 for LV 2011, LV 2012.

Use v1.1.0 for LV 2013+.

helcio
Member
Member
on

Hi David,

The version v1.1.0 works perfectely in labview 2013.

Thanks for this great library and for your time!

Helcio

cirrusio
Active Participant
Active Participant
on

Nice work David.  So would this fall under the an actor framework implementation of the observer pattern?

Active Participant
Active Participant
on

mtat76 wrote:

Nice work David.  So would this fall under the an actor framework implementation of the observer pattern?

I'm not falling for that trap. There are ten implementations of Observer and a hundred opinions on how they're each wrong. Let's just stick with "Data Broadcasting" for the title.

Edit: (I just can't shut up and leave it alone.) The more I see people trying to start their design with Patterns (capital "P"), the more I see them over-designing their software. Don't use Patterns. Learn them, try to understand their intent, and then throw the book away. Design software iteratively, with the minimal code necessary in each iteration to solve one specific, extant problem. This lets your code evolve instead of being framed up from the start, and as we've seen, evolution always wins.

cirrusio
Active Participant
Active Participant
on

Meh.  If it publishes and subscribes like a duck....

Must.not.take.bait....Argggggh!

David Staab wrote:

Edit: (I just can't shut up and leave it alone.) The more I see people trying to start their design with Patterns (capital "P"), the more I see them over-designing their software. Don't use Patterns. Learn them, try to understand their intent, and then throw the book away. Design software iteratively, with the minimal code necessary in each iteration to solve one specific, extant problem. This lets your code evolve instead of being framed up from the start, and as we've seen, evolution always wins.


                   

I think that we can all agree that patterns are to programming as theoretical physics is to engineering - the fundamental knowledge is powerful, but most will find that there is no ideal way of applying these Design Patterns as you might see in textbook.  That being said, you can travel years down a path when you find that massive refactoring is required due to a poor (but not obvious) design decision that might have been avoided had you been aware of some of these key "Patterns".  I will whole heartedly agree that you should not try to design an application around patterns in a book, but it is absurd to think that you should throw out the book just because you might use it in an unnatural way. 

And I would argue that evolution in many cases is a poor analogy for the design process.  Many of us (particularly free lance consultants) do not have the luxury to work iteratively, so evolution can be an unacceptably slow process.  Why not stand on the shoulders of those who have thought long and hard about this and take away what we can from them (even when there work is not in our field)?  And, if you don't understand how a similar problem might have been solved in the past, do you have any hope of developing a better way of solving the problem in a reasonable amount of time (i.e. before you die)?  I guess if even a monkey can write Shakespeare....

My feeling is the statement "Don't use Patterns" seems a tad bit histrionic.  How about - don't attempt to mold your development process around patterns, but rather fold patterns into your development process as the opportunity arises?  "Don't use Patterns" is a little less wordy, so I am betting that will stick.  Sigh.

This discussion seems a tad ironic given that we are sitting in the Actor Framework forums; the same concerns that we talk about here could easily be pushed up into a discussion of frameworks.  Alas, any good idea can be easily misused.

And now, a leavener: what did the fish say when he ran into a wall?  Dam.

Cheers, Matt

Daklu
Active Participant
Active Participant
on

Language is a funny thing--the same words mean different things to different people.  All David is saying is, "Don't go around looking for ways to apply patterns in your applications.  It creates more work than necessary."  We all get excited when we learn new ways of thinking about things, and we've all gone through the stage of looking for nails to pound on with our Pattern hammer.  And while I learned an awful lot by doing that, I now recognize that those applications are more complex than necessary. 

Personally I find the patterns themselves have relatively limited usefulness.  The really valuable lessons I learned had to do with creating application components and making sure they are loosely coupled.  I have a couple design pattern books and rarely crack them open any more, not because I know all the patterns, but because I rarely need design patterns.

"And I would argue that evolution in many cases is a poor analogy for the design process.  Many of us (particularly free lance consultants) do not have the luxury to work iteratively, so evolution can be an unacceptably slow process."

Evolution is an extremely good analogy for how some consultants design and build software.  I have found it is not only faster, but my clients are happier with the end result.  It's not a matter of luxury, it's simply saying "this is how I can most effectively meet my customer's needs."

AristosQueue (NI)
NI Employee (retired)
on

> patterns are to programming as theoretical physics is to engineering

I deal with less-than-ideal software all the time. But I refuse to become a hardware engineer until I can have a spherical moose seek out a point potato on a frictionless, airless plane -- like my physics professor promised.

DFGray
NI Employee (retired)
on

As a physicist, I dealt with less-than-ideal reality all the time.  But I refuse to become a software engineer until all my actors are totally decoupled -- like my design patterns book promised .

drjdpowell
Trusted Enthusiast Trusted Enthusiast
Trusted Enthusiast
on

Hello, I've just had a look at this example and I have some suggestions:

First I'm going to enumerate what I need to publish a new piece of information ("Voltage", let's say):

1) I need a "Voltage" Data Message class with Write and Read methods.

2) I need to add a "Voltage Msg Registry" data item to the Broadcaster actor, with two accessor methods.

3) I need Register and Unregister Voltage Listener message classes, each with a "Do" method.

I'm already up to three classes and six methods, and I haven't even set the voltage nor registered to receive it yet!  This seems quite a lot, even with scripted automation of data accesors and message-class creation. 

Suggestions to reduce this burden:

1) Make a common-parent "Publisher" actor class to do the broadcasting.  Child actors call a "publish" ("broadcast", "notify") method that accepts the Data Message. 

2) Publisher actor has "Register" and "Unregister" messages that DO NOT need child classes made for each instance; instead, those messages contain an object of the Data Message of interest.  The Publisher identifies which messages to send where by matching up the Data Messages. 

This would reduce the amount of code needed to publish something new, from one data item, three classes, and six methods, to only one class and two methods (the specific Data Message, itself).

Opps, forgot something important: 3) rather than have the "inbound" data message be a child of the "outbound" data message, have the inbound message contain the outbound data message.  The inbound message, let's call it an "envelope", would call a "read" method on the contained data message, rather than call the read method on itself.  The advantage of this is that the original sender of the message does not ever need to have an instance of the final message form, instead the "Publisher" parent actor can just place the data message inside the "envelope" provided in the registration message.  This also allows the "Publisher" to retain a copy of the data message and send it to any new actors registering for it.

Active Participant
Active Participant
on

drjdpowell wrote:


                       

I'm already up to three classes and six methods, and I haven't even set the voltage nor registered to receive it yet!  This seems quite a lot, even with scripted automation of data accesors and message-class creation. 

I agree. That's part of why I don't use AF anymore. It's a hell of boilerplate.

1) Make a common-parent "Publisher" actor class to do the broadcasting.  Child actors call a "publish" ("broadcast", "notify") method that accepts the Data Message. 

2) Publisher actor has "Register" and "Unregister" messages that DO NOT need child classes made for each instance; instead, those messages contain an object of the Data Message of interest.  The Publisher identifies which messages to send where by matching up the Data Messages. 

Opps, forgot something important: 3) rather than have the "inbound" data message be a child of the "outbound" data message, have the inbound message contain the outbound data message.  The inbound message, let's call it an "envelope", would call a "read" method on the contained data message, rather than call the read method on itself.  The advantage of this is that the original sender of the message does not ever need to have an instance of the final message form, instead the "Publisher" parent actor can just place the data message inside the "envelope" provided in the registration message.  This also allows the "Publisher" to retain a copy of the data message and send it to any new actors registering for it.

Good ideas! Since I don't use AF anymore, the odds of me going back and refactoring the library in this way are nil. It's licensed open-source, though, so go ahead and make the edits and add yourself to the list of contributors/copyright holders!

Drew.Rankin
Member
Member
on

David Staab wrote:

I agree. That's part of why I don't use AF anymore. It's a hell of boilerplate.

Good ideas! Since I don't use AF anymore, the odds of me going back and refactoring the library in this way are nil. It's licensed open-source, though, so go ahead and make the edits and add yourself to the list of contributors/copyright holders!


                   

Interesting comment, Dave, since many of us are just now looking at using AF and are building applications using it and the scripting engines that have been built around it. Can you talk about where you have moved onto with you current architecture? May not be appropriate in this thread, perhaps in a sidebar convo or a new thread?

Thanks,

Drew

Contributors