Actor Framework Discussions

cancel
Showing results for 
Search instead for 
Did you mean: 

Communication cross-talk with spawned actors

I just upgraded to LV 2012 and decided to buckle down and try out some OOP for the first time and implement my next very simple project using the actor framework. This simple project is, in essence, cycling power to the DUTs and then watching them (through VISA) as they boot up and send data for the first few minutes to make sure they don't freeze or get their default flash data messed up or something, then cycling the power again and repeating indefinitely.

After spending a bit of time last week trying to get my mind around how OOP works and how I should structure everything I essentially came up with the following:

The Main Application spawns a Cycle Task Manager which at runtime spawns a user determined number of DUT Controller Actors which in turn spawns several subActors for power cycling, serial communication, reporting, etc.

This would allow us to add more DUTs without changing any code and in essence means that I have these groups of spawned actors that I want to be completely independent from each other.

The problem I have is that each spawned DUT Controller Actor does not seem to be independent. I have the DUT Controller Actors displaying their Front Panels, and when the program is running and I switch to the block diagram of the running clones (Actor Core) and probe the Object on the wire, the Object changes randomly. At one moment the VISA reference could show COM1 and the next moment it could show COM4. I'm guessing that this happens because the Actor Cores are shared clones, and being dynamic dispatch cannot be pre-allocated.

A solution in the forums is to make a parent class a static dispatch so that it can be set to pre-allocate the clones, but I don't know how I would go about making a parent class to the Actor Core, and I can't change one Actor Core without changing all of them. My first erroneous though was that I would be able to fix it by pre-allocating all of the Sub-VI's (the methods in all of the spawned actors), but that didn't do anything, I'm guessing because the Parent VIs (the Actor Cores) are not preallocated.

I hope I am just missing something simple.

Is this an issue of the Actor Cores being shared clones?

And more importantly how should I have set this up, or what can I do to get rid of the cross-talking?

In short, Is there a good way, using the actor framework, to spawn a bunch of actors and then to be able to communicate with each one independently, know which one you are talking to, and know that the data is coming from a specific actor instead of just from a random clone?

-Carl

0 Kudos
Message 1 of 7
(6,859 Views)

crwecker wrote:

The problem I have is that each spawned DUT Controller Actor does not seem to be independent. ...

I can assure you they are independent. The object in the shift register is not affected by anything other than the methods that you call on that data.

crwecker wrote:

... I have the DUT Controller Actors displaying their Front Panels, and when the program is running and I switch to the block diagram of the running clones (Actor Core) and probe the Object on the wire, the Object changes randomly. At one moment the VISA reference could show COM1 and the next moment it could show COM4. I'm guessing that this happens because the Actor Cores are shared clones, and being dynamic dispatch cannot be pre-allocated.

I can pretty much guarantee that cross-talk between the VIs at the LV level is *not* the problem. You say you probe the object on the wire and it changes randomly. It can only change in response to the methods that you tell it to run. I hope you'll forgive me if I disbelieve any other option without substantial evidence, since if that were true, we would have meltdowns throughout LV 2012 on a host of projects.

You have to be sending messages that put different refnums into the object. If I had to wager, I would suggest that you're sending messages you intended to send to one of the launched actors to a different launched actor.

If you really believe that you're seeing cross talk, please post a video. If you haven't heard of Jing, it's a piece of freeware that allows you to record videos (with sound if you have a microphone) of whatever you're working on and save them as a video file. http://www.techsmith.com/jing.html Works great for reporting these kind of bugs.

0 Kudos
Message 2 of 7
(3,793 Views)

shared reentrancy is appropriate for the AF. one of the harder lessons i was forced to learn when switching from QDMH design to Actor-Oriented design is the appropriate encapsulation of state. this subthread of a discussion I posted awhile ago may help you get started; the rest of that thread isn't a bad read, either.

note: discussions in this group tend to sprawl heinously. i recommend enabling threaded viewing in your NI Community settings to help make discussions navigable. i linked to the first post of a subthread above, but the following posts that directly respond to it may not be easy to find without threaded viewing.

0 Kudos
Message 3 of 7
(3,793 Views)

crwecker wrote:

Is this an issue of the Actor Cores being shared clones?

Yep.

crwecker wrote:

And more importantly how should I have set this up, or what can I do to get rid of the cross-talking?

There isn't *really* any cross-talking between actors.  It just looks that way because you're probing a single instance of a vi that is being used by several different objects.  The objects themselves are separate and distinct in memory.

crwecker wrote:

In short, Is there a good way, using the actor framework, to spawn a bunch of actors and then to be able to communicate with each one independently, know which one you are talking to, and know that the data is coming from a specific actor instead of just from a random clone?

There are two parts to your question:  How do you know which instance of the subactor you're sending a message to, and how do you know which instance of the subactor you're receiving a message from?

The first part is simple.  Launch Actor returns a "Caller-To-Actor Enqueuer."  Create a lookup table (key-value pair data structure) and store each enqueuer in the lookup table along with a unique identifier.  Then when you need to send a message to the subactor, use the ID to fetch the enqueuer from the lookup table and send the message.

The second part is a bit more difficult.  Since the owning (or "calling") actor receives messages from all the subactors on the same queue, each message received needs have the ID of the sender encoded into it.  When the message is received, the owning actor reads the ID to figure out who the sender is and stores the data returned by the message in a data structure assigned to that subactor.

There are lots of ways you can implement this.  One easy way is to build the subactor so you can assign it an ID when it is created (not launched.)  Then take that ID and a data structure containing all the data relevant to that subactor (enqueuer, run state, cycle count, whatever...) and put them in a lookup table.  That way a single lookup table contains all the information the Cycle Task Manager needs about its subactors.

0 Kudos
Message 4 of 7
(3,793 Views)

Awesome! Thanks for your replies! I am glad to learn that I was a great distance off-kilter in my assumptions about what I was seeing and glad to know that I can most likely fix it just by tightening up the messaging chains. So far, though it took me longer than I thought it would, I've really enjoyed building the classes and getting everything put together using the Actor Framework. I can see the benefits to it and am slowly getting a grasp on how it all fits together. Awesome tool! Thanks AQ!

-Carl

0 Kudos
Message 5 of 7
(3,793 Views)

Well, I'm embarrassed to say that it was all a simple matter of me having an uninitialized shift register holding on to the serial data in a subvi that determined whether a full line of data had been received yet or not. This happened to be the first thing that the new guy at MGI (Derek?) suggested to me at the User Group Meeting this last week, to which I promptly replied "Nope, no shift registers, that can't be the problem."

While it wasn't obvious to me as I was creating everything why having a shift register in that subvi would be a problem, it was very obvious when I started thinking of them as instances of vi's that any of the spawned objects could be using as Daklu suggested. And in general after reading through more of the forums and hopefully getting a better grasp on the idea of encapsulated data.

Thanks everyone!

Now happily cycling away!

-Carl

Message 6 of 7
(3,793 Views)

Glad to hear you figured out the problem. Now go vote for my idea to remove the same kinds of shift registers from LV functions in vi.lib!

0 Kudos
Message 7 of 7
(3,793 Views)