LabVIEW

cancel
Showing results for 
Search instead for 
Did you mean: 

Actor Model and Producer Consumer

When developing any application that involves more than a loop with an event structure I tend to use Actors, or similar architecures like parallel qmh or a different vi with executing a loop.

But I like actor for it's simlicity as it is already buld in LV. Besides sharing a VI (easier to share refnums, queues, local vairables, etc.) I don't see any benefit for using qmh over actors.

 

However the actor makes it obvious that communication - especially transfering data - is always a directional 1:1 communication between caller/callee. Eventually when passing the data in a producler/consumer style to the (non actor based) UI I tend to reinvent the wheel over and over again. Distributing refnums, queues etc. globally just makes it cumbersome, especially when you want to consum data at differen places (e.g. one to display on the UI and one in an Actor that logs data). And eventually the producer should in no way care of what is the consumer and how it want's to get the data.

 

I settled on using project scoped global variables for "a bit" data. For bigger projets it's usually a FGV as wrapper for some generic way to read/write data.

Using the FGV in an Action Engine style you can also use it to distribute e.g. change events.

 

What is annoying me: I spend way too much time on building the architecture for distributing data.

 

I actually don't see a much better option. Any thoughts?

Christoph

 

 

 

 

 

 

0 Kudos
Message 1 of 7
(2,267 Views)

Hi ChristophHS,

I know what you mean. Passing data around an application can be a pain regardless of what architecture you are using. I can't say that there is a magic bullet that will solve your problem in every scenario. However, there are a few techniques that can make your life a little easier in some scenarios.

 

One thing I noticed is that you mention the 1:1 communication between caller/callee. Something to consider. Handle your broad actor communications from your root actor. So, whichever actor is at the top of the tree, pass it's enqueuer down to all of the nested actors. By doing this all of your actors can have a centralized communication link. In fact, for distributing data among them, you can have a message type for each kind of data you want to distribute so all data is sent up to the first actor, then you can have a message for requesting the data that includes either a queue or a notifier depending on how you want updates sent that your nested actors can send to tell the first actor how to send the data back.

 

Another way of obfuscating highly discrete data endpoints within your application is to use network communication protocols. For small amounts of data like log messages and the like it can be useful to just send tcp messages though you need a network comm architecture to handle that. I wouldn't recommend going this route unless you absolutely have to, though it can be useful for connecting different parts of your application regardless of where they are running (same application instance, different instance, different user on the same machine, or a completely different machine).

 

Lastly, and probably my least recommended solution. If you require a high volume of data transfer between application instances on the same machine, you could consider using a RAMdisk. A RAMdisk is a part of computer RAM that gets mounted as if it were a physical disk. This works great for data volumes too large for network communication but of course then doesn't work over a network. This allows you to make a file to keep your functional global data in instead of a vi. It is the same solution at its core but is more flexible since you can create and destroy the variables at run time.

 

If I was going to point you in a single direction, it would be to share the root actor enqueuer as described above. Still reference passing, but simplified somewhat by having a single point of contact for your data communications.

Philip Bear
Certified LabVIEW Developer
0 Kudos
Message 2 of 7
(2,227 Views)

You might want to have a look at the Delacor Queued Message Handler, which has a TON of scripting to do much of this for you.  I have just started looking at it, but it does look very well thought out (expect no less from Fabiola).


GCentral
There are only two ways to tell somebody thanks: Kudos and Marked Solutions
Unofficial Forum Rules and Guidelines
"Not that we are sufficient in ourselves to claim anything as coming from us, but our sufficiency is from God" - 2 Corinthians 3:5
0 Kudos
Message 3 of 7
(2,215 Views)

You could also try my "Messenger Library".  Both the Actor Framework and DQMH use Queues, making a User Interface structure a separate thing.   But the standard "DEV Actor Template" in Messenger Library is a single loop with an Event Structure, so UI stuff is trivial.  Messenger Library is also intended to allow one to never need to use ad-hoc communication between loops, as you seem to be applying to AF.  

 

Here is a very good summary of Messenger Library, written by Bob Edwards.

0 Kudos
Message 4 of 7
(2,180 Views)

@philipbear wrote:

Hi ChristophHS,

 

One thing I noticed is that you mention the 1:1 communication between caller/callee. Something to consider. Handle your broad actor communications from your root actor. So, whichever actor is at the top of the tree, pass it's enqueuer down to all of the nested actors. By doing this all of your actors can have a centralized communication link. In fact, for distributing data among them, you can have a message type for each kind of data you want to distribute so all data is sent up to the first actor, then you can have a message for requesting the data that includes either a queue or a notifier depending on how you want updates sent that your nested actors can send to tell the first actor how to send the data back.

 


Thanks for the input. I understand what your saying and basically the possibilities are endless here. But thats more or less redoing the same thing over and over again. Of couse I could also write a common implementation and reuse it but I found generic reusable actors are getting bulky quite fast.

Regarding network communication: I also played around with ZQM. It simplifies communication patters very much. But the one thing that stopped me: I never fully understood in which case I might not receive a message. (Early/late subscriber, buffer overflow, ....). I only use it for a distributed logging system. I think I never lost any messages, but even if so it's not ctitical.

 

@crossrulz wrote:

You might want to have a look at the Delacor Queued Message Handler, which has a TON of scripting to do much of this for you.  I have just started looking at it, but it does look very well thought out (expect no less from Fabiola).


Thanks, I'll have a look.

@drjdpowell wrote:

You could also try my "Messenger Library".  Both the Actor Framework and DQMH use Queues, making a User Interface structure a separate thing.   But the standard "DEV Actor Template" in Messenger Library is a single loop with an Event Structure, so UI stuff is trivial.  Messenger Library is also intended to allow one to never need to use ad-hoc communication between loops, as you seem to be applying to AF.  

 

Here is a very good summary of Messenger Library, written by Bob Edwards.


Thank you, that looks interesting. Tbh I am not a big fan of large external libraries that require you to read a manual to get started. Not saying they are no good but I try to stick to LV standards.

I'll look into it.

btw. the link on lava.org appears broken, but it's the same file you attached ?

 

 

Generally I think LV is missing a generic 1:n and n:1 comunication mechanism. Soomething like a named queue but distributed (preferrably even network based to distribute via processes and devices). I think that would solve most of my headache.

0 Kudos
Message 5 of 7
(2,132 Views)

@ChristophHS wrote:

Here is a very good summary of Messenger Library, written by Bob Edwards.


Thank you, that looks interesting. Tbh I am not a big fan of large external libraries that require you to read a manual to get started. Not saying they are no good but I try to stick to LV standards.

 


Too much documentation?  The first couple of youtube videos listed on the LabVIEW Wiki for Messenger Library is probably all you need, if not just the first one.

 

If you want to stick with "standard LabVIEW tools", though, then you're stuck with Actor Framework (DQMH and zeroMQ are add-ons).  I would suggest you go on the Actor Framework forum, rather than here, to get more expert advice on UI's in Actor Framework.  I would suspect at least some of them would be strongly opposed to your various "global" techniques (including Action Engines), as that is rather against the idea of "actors", which communicate only by messages.

0 Kudos
Message 6 of 7
(2,118 Views)

Your last statement makes me think you may have good use for network queued shared variables. I usually don't recommend shared variables as there is a fairly stiff upper limit on how much data you can pass through them. (the shared variable engine is single threaded) But if you are looking for generic 1:n and n:1 communication that may be your solution. Shared variables can be configured to be used over a network, but also, they can be set to have a single writer (1:n) or to have a receive queue instead of last value only. Also, it is worth noting that shared variables are a legacy only feature in NXG, they moved to tags which are not able to be networked or queued.

Philip Bear
Certified LabVIEW Developer
0 Kudos
Message 7 of 7
(2,109 Views)