Jump to content

Recommended Posts

Following on the "Self-addressed Stamped Envelopes" topic, I'd like to present a design of an Active Object using my messaging library. This template has the ability to both "reply" to messages and to allow "observers" to register for event updates. I haven't used this template yet (just wrote the observer-registration part yesterday) and I would appreciate any feedback before I use it in a real-world project (which I'll be doing after a weeks vacation).

The example object, "PP Template" does the following:

Responds to "Current Time?" with a text string of the current time.

Sets the format string for the time by the command "SetTimeFormat"

Starts generating "TimeUpdate" messages periodically on the period given in the command "AutoGenerateTime"

Allows external processes to register as observers of the following events:

"SetTimeFormat" received

"Current Time" issued

"TimeUpdate" issued

"Macro: Exit" received (this is the shutdown command for the active object)

All error messages

Here is how a higher-level VI might create ("launch") and communicate with "PP Template":

post-18176-0-00763100-1311861159_thumb.p

In this example we launch "PP Template", register a Message Logger (another active object) as observer of all published events, send a nonsense message "Blah Blah" just to demonstrate error handling, set the time format, and query "Current Time?" first synchronously(*), then asynchronously with the message reply going to the "Asynchronous Receiver" loop. Then we register "Asynchronous Receiver" as an observer of TimeUpdate events (and set the autogenerate time of these events). On pushing the "stop" button, "PP Template" is sent a "Macro: Exit" command to shut down.

Here's what the Message Logger receives when we run this VI:

post-18176-0-14882000-1311861819_thumb.p

And here is the VI dynamically launched VI at the heart of the active object. It's basically a message handler with eight cases; three of the cases handle the three commands, then there is a timeout case, an error handling case, a shutdown case, an "ignore null messages" case (not shown), and a default case to catch unhandled commands (and spelling errors). The way receiver timeout and errors feed into the message case structure is stolen from Daklu's Lapdog messaging library.

post-18176-0-21972200-1311860551_thumb.p

Some details of communication with the active object:

post-18176-0-15356800-1311860453_thumb.p

1) The object is launched by dynamically calling the PP Template.vi, setting it's "Startup Message" control via a VI Server call, and then doing some handshaking messages between "Launch.vi" and the "Startup" and "Acknowledge Startup" VI's. This creates the incoming command messenger for the process (in this case it is a queue based messenger, but there is an alternate "Startup" VI for a User-Event-based messenger). Calling a "Send" or "Query" method on the active object calls the same method on the command messenger. There are two startup modes: when started as an "autoshutdown slave", the messenger is created inside the Launch.vi, which means that if the main VI goes idle, the queue reference will become invalid, which triggers a "MSRReceiverError" that shuts down the launched VI ("Message Logger" in the above example shuts down in this way). The other way creates the Messenger inside the "Startup" VI, making the active object independant of the Launching process.

2) Observer registration is handled by an "ObsReg" by-ref object, with two methods: "Registration", which filters out and acts on registration commands, maintaining a list of all observers for each event message (and sets for all events and all error events), and "Notify Observers", which accepts messages and sends them to all observers registered for them. Thus, it is extremely easy to publish new event types; just package a message for the event and pass it to "Notify Observers".

3) Reply-based communication involves a "return address" (a messenger or other active object reference) to be attached to the message, and the active object using a "Reply" VI to respond (in synchronous communication, the "Query" VI creates a single-use response queue to receive the reply). For error handling, the Reply VI will package any error in it's error terminal as an error message and send this to the return address (this is in addition to an observers being notified of the error).

-- James

(*) Please note the potential problems of synchronous communication brought up by mje.

  • Like 1

Share this post


Link to post
Share on other sites

I just update an Active Object/Design Pattern video showing how I implemented Active Object in Symbios's DVR class.

http://goop.endevo.n...DesignPatterns/

//Mike

Unless I'm missing something, these are pretty fundamentally different patterns. The Symbio one focuses on method calls to by-reference objects [aka synchronous messages] while the Active Object focuses on message passing and announcements [aka asynchronous messages]. Although the two can be mixed, there's a huge amount of distinction in how to build up an application from scratch depending upon which one you're relying upon. I would not call these the same thing at all.

Am I correct in my analysis here?

Share this post


Link to post
Share on other sites

Hi Stephen

Symbio’s Active Object can be applied to the By Value Class Type As Well, but if you want to communicate between the Active Object Processand the normal Class Methods you need of cause some sort of reference (unlessyou want to use Global Variables).

So I must admit that I most often use a reference class and use the Shared Attributes to handle information between them.

The “Send Message To Process” Method Template, has support for retrieving data as well, like this.

post-941-0-03743000-1312108176_thumb.png

Cheers,

Mike

Share this post


Link to post
Share on other sites

Unless I'm missing something, these are pretty fundamentally different patterns. The Symbio one focuses on method calls to by-reference objects [aka synchronous messages] while the Active Object focuses on message passing and announcements [aka asynchronous messages]. Although the two can be mixed, there's a huge amount of distinction in how to build up an application from scratch depending upon which one you're relying upon. I would not call these the same thing at all.

Am I correct in my analysis here?

Having just watched Mike's video it seems he is mostly using asynchronous messaging (via a User Event in his example Active Object). He is using a DVR to allow some of his API methods to modify the active object's private data, and those are synchronous (but fast).

My (perhaps mistaken) impression of the differences of Mike's Active Object to mine are:

1) He uses a specific reply channel for all responses from the AO (a queue in his “Send Message To Process” Method Template), while I use multiple reply channels, provided with the incoming messages themselves or "registered" as an Observer. This means (correct me if I'm wrong) that VIs based on the “Send Message To Process” template would not work properly if multiple were called simultaneously in parallel, as there is no mechanism to route the separate replies to the correct VI.

2) He uses bare User events and queues, while I wrap all communication as "Messengers". This will hopefully allow me to substitute network communication when I get the chance to develop it, without needing to modify my active objects internally. I've been following the philosophy that the active objects should know the bare minimum about the specify communication channels they are using. My example AO given in the first post, for example, only knows that it is using a "Receive-type" incoming messenger (which could easily be TCP-based instead of queue-based), and knows nothing at all about it's outgoing communication (which could be queues, TCP, shared variables, notifiers, etc., and can be several processes instead of just one).

3) His active objects are interfaced with by an associated API, while I build messages to send to mine via the generic API of the parent "Send" class. This is a minor difference as he could just use his “Send Message To Process” Template, unmodified, to send messages, and I could easily create wrapper API VIs. I'm not sure which is a better way to do things.

-- James

Share this post


Link to post
Share on other sites

If anyone is following this, here's some images from one of my first projects using (and continuing to develop) this Active Object design. Its an active object that runs an Ocean Optics USB2000 spectrometer. There are actually 6 "Parallel Process" style objects involved: "USB2000" itself, a subprocess object ("USB2000sub") that synchronously communicates over USB to the spectrometer, two clones of the simple testing UI (two to make sure changes on one reflect in the other), and two different types of message loggers (one for errors and one to monitor all communication by "USB2000"). "USB2000" and "USB2000sub" together publish events and state information via it's Observer Register, to which the UIs and loggers subscribe. There is a mix of Queue and User-Event communication here, with "USB2000sub" and the error logger being based on the queue-messenger template I showed in the initial post, while the other active objects use User Events. "USB2000" itself is based on an adapted JKI-QSM template.

post-18176-0-13995900-1314799307_thumb.p

Here's a shot of the "State Logger", which displays the last received message of each label, organized by what VI sent it (here it's showing "USB2000sub"):

post-18176-0-98172000-1314799885_thumb.p

There is now two different types of published messages, "Event" and "State". The difference is that the Register keeps a copy of the last inputed "State"-type message, allowing it to immediately inform newly registering observers of the current state information.

post-18176-0-75406400-1314800099.png

Edited by drjdpowell

Share this post


Link to post
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.


×
×
  • Create New...

Important Information

By using this site, you agree to our Terms of Use.