Actor Framework Discussions

cancel
Showing results for 
Search instead for 
Did you mean: 

Suggestion: a different class structure for Queues

In the current actor framework, there is "Send Queue" and "Receive Queue", which both wrap "Message Priority Queue", and a "Message Queue Pair" class that wraps all three of them.  All these classes are children of LVObject.

I'd like to suggest an alternate design, consisting of:

1) a "Send Queue" virtual class, with no private data, that contains all "Send" or "Enqueue" virtual functions.

2) a "Message Queue" child of "Send Queue", that adds "Obtain", "Dequeue", and "Release" virtual methods (also a virtual class with no private data items).

3) "Message Priority Queue", child of "Message Queue" with overrides all the above methods with a concrete implementation.

All actual objects would be of "Message Priority Queue" class, but most wire types would be one of the virtual parent classes.   Actors would have there own "Message Queue", but would know other actors queues only as "Send Queue" wire types.  "Message Priority Queue" would only be explicitly referred to on creation.

Advantages:

1) no need for the "Message Queue Pair Class" with it's "Get Send Queue" method.  Pass a "Message Priority Queue" object directly into a "Send Queue" terminal and you have a "Send Queue" that only supports enqueue methods.  Personally, I found "Message Queue Pair" to be very confusing when I first studied the Actor Framework.

2) Easy to substitute alternate concrete queue implementations in place of "Priority Message Queue", such as a possible future "Network Message Queue", or a "Simple Message Queue" if you don't want priority messages (personally, I think priority is undesirable in a messaging system; overly complicated and encourages message queues to be used as job queues).

Disadvantages over the current system:

1) no "Receive Queue" that allows dequeue but no enqueue.

2) nothing to prevent objects on "Send Queue" wires being downcast to "Message Queue" wires, allowing access to dequeue and release methods.  One could create a "Send Only" class that wraps a "Send Queue" object in order to prevent this; an actor would wrap it's Message Queue in a "Send Only" object before passing it to another actor.

-- James

0 Kudos
Message 1 of 10
(9,140 Views)

Your disadvantage #2 is enough to kill this idea in my book. We really want to be able to assert certain facts about the framework, and lifetime of the refnums is bullet point number one. The lifetime issue has been the downfall of too many other framework attempts. Creating the Send Only wrapper class puts you right back where we are today because I wouldn't use the raw Send Queue class anywhere in any public VI.

I wouldn't mind improving the API somehow -- it is a bit heavyweight for my tastes when I use it on the diagram -- but any changes have to meet that lifetime control requirement.

One thing I have considered is making Obtain have two additional outputs: the Send and Receive queues. It certainly makes it easier to use on the diagram (because you almost always drop the Obtain followed by both of the Reads) but it makes it less clear exactly what is being obtained -- we don't have other precedents for multiple object wires all being the same actual refnum (although that's kind of odd to me because the idea of wrapping to limit the API has come up a lot and is really useful... what I observe is most people just document "don't call this function" instead of making an API that actually enforces not calling that function).

0 Kudos
Message 2 of 10
(4,743 Views)

I think it would be a lot clearer if the same protection is acheived with "Send Only" Wrappers.  Create a Message Queue, pass it to Actors you Launch.  Have the Launch VI make sure that the queue is wrapped as "Send Only" so internal to the actor one cannot destroy or otherwise mess with the queue.  The the User is creating a queue and passing it to the Launch function.  Very intuitive.  Much simpler and less confusing than creating a "Message Queue Pair", then creating another object from it that is passed to Launch, and possibly creating yet a third object that can be used to dequeue messages.

0 Kudos
Message 3 of 10
(4,743 Views)

Launch Actor has to take only a Send Queue because that's all that is available for launching nested actors.

The Message Queue pair is needed only for the top-level VI that kicks off the first actor. After that, it is unneeded. Since that's boilerplate code, I'm pretty comfortable with the current setup.

0 Kudos
Message 4 of 10
(4,743 Views)

> Launch Actor has to take only a Send Queue because that's all that is available for launching nested actors.

In my proposed scheme, "Send Only" and "Message Queue" are both children of the parent class, so "Launch Actor" (and other methods) can be made to accept both classes.  Sorry, I didn't make that clear.

> The Message Queue pair is needed only for the top-level VI that kicks off the first actor. After that, it is unneeded. Since that's boilerplate code, I'm pretty comfortable with the current setup.

Ah, I hadn't appreciated that!  But isn't this boilerplate code useful for interfacing actors into older code?  For example, see LVB's recent question about using an actor in place of a pre-existing "Functional Global" style API.  What's the best way to interface actors with other coding styles?

0 Kudos
Message 5 of 10
(4,743 Views)

> Ah, I hadn't appreciated that!  But isn't this boilerplate code useful for interfacing

> actors into older code?  For example, see LVB's recent question about using an

> actor in place of a pre-existing "Functional Global" style API?

Yes, but I think you can still use the same code.

The current situation provides the guarantees we need and, to my eye, provides the best segregation of responsibility, which gives us the best flexibility for adding additional features in the future. I don't see it as particularly problematic. David Staab posted the boilerplate in his last post:

https://decibel.ni.com/content/servlet/JiveServlet/downloadImage/2-30438-26071/534-259/Untitled.png

You take the Send Queue ouptut of Launch Actor.vi and run it down to your own code. Now you can send it messages. Receiving messages other than LastAck from non-actor code is trickier because there's no actor to receive them so you can't really call Do.vi, but if you can find ways to send back actorless messages (like LastAck) then you can make it work.

0 Kudos
Message 6 of 10
(4,743 Views)
You take the Send Queue ouptut of Launch Actor.vi and run it down to your own code. Now you can send it messages. Receiving messages other than LastAck from non-actor code is trickier because there's no actor to receive them so you can't really call Do.vi, but if you can find ways to send back actorless messages (like LastAck) then you can make it work.

It would be nice to have a message class in the framework for actorless messages.  The Actorless Msg would not have a "Do.vi" override requirement.  It is slightly confusing to have an override method that would never be used (in the case of actorless messaging).

I currently implement actorless messaging by adding a child "Actorless Msg" class that overrides Do.vi and requires the call parent.  If anyone calls the Do, it will return an error that Do.vi should never be called with Actorless Messaging.  However, this does not prevent the developer from creating a Do override.

The "Actorless Msg" would also be useful for the Synchronous Reply "Returned Message".

CLA, CTA
0 Kudos
Message 7 of 10
(4,743 Views)

AristosQueue wrote:

The current situation provides the guarantees we need and, to my eye, provides the best segregation of responsibility, which gives us the best flexibility for adding additional features in the future. I don't see it as particularly problematic. David Staab posted the boilerplate in his last post:

You take the Send Queue ouptut of Launch Actor.vi and run it down to your own code. Now you can send it messages. Receiving messages other than LastAck from non-actor code is trickier because there's no actor to receive them so you can't really call Do.vi, but if you can find ways to send back actorless messages (like LastAck) then you can make it work.

I worry that there is a big barrier to widespread adoption of the Actor Framework in that it is hard to see how to interface it with pre-existing code.  For example, if one had several existing projects or reuse components that use User Events (based on JKI state machines, say), one isn't going to want to start writing Actors unless one can make them play nicely together.  Thus, the "boilerplate" code is more important to potential users than it is to you, the framework creator.  One of the advantages of my suggested alternate class structure is the ability to "plug in" alternate communication methods, via children of "Message Queue".   This can be done while still maintaining refnum security within actors via "Send Only" wrappers.  

And it make the boilerplate less confusing.  The first thing I did on downloading the Actor Framework Demo was open the diagram of "Demo.vi" and try to understand what a "Message Queue Pair" is (a pair of queues for two-way communication, I wrongly assumend).  The confusing and seemingly over-complicated boilerplate is the "first impression" people get of the Actor Framework.  It's not a good impression.

Message 8 of 10
(4,743 Views)

drjdpowell wrote:

The first thing I did on downloading the Actor Framework Demo was open the diagram of "Demo.vi" and try to understand what a "Message Queue Pair" is (a pair of queues for two-way communication, I wrongly assumend). 

I made same assumption the first time I opened it as well.  It took a little bit to wrap my head around it.  It does not seem intuitive at first.

Sam Taggart
CLA, CPI, CTD, LabVIEW Champion
DQMH Trusted Advisor
Read about my thoughts on Software Development at sasworkshops.com/blog
GCentral
0 Kudos
Message 9 of 10
(4,743 Views)

Taggart wrote:

drjdpowell wrote:

The first thing I did on downloading the Actor Framework Demo was open the diagram of "Demo.vi" and try to understand what a "Message Queue Pair" is (a pair of queues for two-way communication, I wrongly assumend). 

I made same assumption the first time I opened it as well.  It took a little bit to wrap my head around it.  It does not seem intuitive at first.

Then you are working with an old version of the AF... the "Pair" was removed sometime last year.

0 Kudos
Message 10 of 10
(4,743 Views)