Actor Framework Discussions

cancel
Showing results for 
Search instead for 
Did you mean: 

Actor messages between actors. Private class data - value copies

So, in digging into the actor core of the main AF directly, I see the actor core relies on the force call parent node function to keep the main messages dequeue structure working to handle the incoming message for any actor.  So, corect me if I'm wrong, but this class then will have the class that is initialized and all class changes done within the messages from that point on.  If I write my own loop in my actor core, then the class private data will not be in sync with this, it is specific to my loop.  The trouble I'm having and why I suspect this, is then passing data between my actors.  I was hoping to give one actor the enqueue of the other actor at the calling actor.  My message seems to do this from probing what is sent and although the correct data is in my DO.vi calls, the data is NOT there for use at the destination end in other messages (that actor says the reference is no longer valid (its zero))?  And other data I change via methods called in messages, are not available in my own loop within my actor core, which I assume is from it having a value copy of the class, different from the one in the parent actor core. I don't understand yet if the inheritance somehow shares the value state of the class or if there are any copies of it limiting access in the AF.

Anyway, was hoping that could be explained if I am right or wrong on these assumptions above and to get help with debugging these messages. The image below shows debug on the do method, there I know there is a valid priority queue passed in.  The next message shows where this comes from right after launching my actors from the main app actor.  That enqueue though cannot be used by subsequent messages, it always errors saying it is no longer a valid reference.  If I stick it on a global to test with, I can use it from the global just fine so not sure where it is getting lost?? All the message does, is store it in the class private data via a method call. Hope someone can help.

Thanks.   Mike.

Clipboard Image (3).png

Clipboard Image (1).png

0 Kudos
Message 1 of 8
(7,031 Views)

Try writing the logging enqueuer to the "Acquire" object first before launching it.  That is simpler and more direct than sending it a message and perhaps it will help you narrow down where your problem is.

0 Kudos
Message 2 of 8
(4,701 Views)

Thanks DR JDPowell, that is certainly one way to fix this particular issue and will work.  However, I am needing to understand this problem as there will be many other similar kind of messages in my application since I have a lot of things that can be changed by the user application layer which is really configuration data, but it changes at run time so it will then impact both the actor state machine as well as data in the actor class that the messages will access or manipulate.  So, this is really just one example of it I want to solve to understand how to use these messages better and to know where and how the class data is actually accessible in the AF.  Thanks.

0 Kudos
Message 3 of 8
(4,701 Views)

I didn't fully follow your description, but I would suspect you have a simple bug somewhere (dropping the reference due to an unconnected "Use default if unwired" terminal, for example) that you are misinterpreting as some more deep issue with your understanding of the AF. 

0 Kudos
Message 4 of 8
(4,701 Views)

Mike_King wrote:

...the data is NOT there for use at the destination end in other messages (that actor says the reference is no longer valid (its zero))? 

A reference is just a number, and the refernence becoming invalid does not actually change that number.  So if the reference is "zero" then you accidently set it to zero somewhere upstream; it can't become zero by itself.

0 Kudos
Message 5 of 8
(4,701 Views)

Mike,

Not sure if this will help or not, but if you are replacing the Call Parent Actor Core with your own, you will still need to process <something>.Do and yes they will be unique to that class. It seems to me that you are confusing the re-entrant characteristic of the actor core which when initialized IS the class that it is associated with. The <Message Class>:Do method is a generic method that can morph into the class you specify; however, the private class data must already reside on the inputs to the Do method. If you call a Do method in the wrong actor core, you will get a private data mismatch and get the error you are seeing.

I have had this happen to me several times where I called the wrong message for a particular actor and got some cryptic error back out that I did not understand.

Based on your description, you can certainly send messages to an actor to reset its private data, I do that all the time whether it's storing a copy of the last data acquired or some setting that needs to be used in another method.

What I am confused about your description is that you seem to be using two loops, one in the actor's override and one in the spawned parent method. Once you split the private data of the class in the override, the copies will never be in sync. From my experience, it is best to use any loops in the actor core override to send messages to the parent actor core and not try to manage data in the override loops.

Hope that helps.

Drew

EDIT: I dug around my current project and found something very similar to the method above:

InitActor.PNG

So this illustrates that what you are doing is possible, I'm just wondering if you have split the class private data in a way that is difficult to synchronize.

0 Kudos
Message 6 of 8
(4,701 Views)

If you add a second loop to Actor Core.vi, that second loop does not have the state of your actor (indeed, we generally recommend that you not fork the actor wire to both the call parent node and to your secondary loop -- just extract the bits that you need for your secondary loop to execute.

The actor object in the call parent node is getting updated to contain some bit of data value based on a message -- in your case, this bit of data is the enqueuer for another actor. You have two general options:

  1. You have given your actor object some way to communicate with your second loop before you passed it into the Call Parent Node. Check out the shipping examples... there are several places where event refnums or control refnums are bundled into the object before it is passed into the CPN. You use this communication mechanism to give the enqueuer to the second loop.
  2. You design your second loop so that it doesn't need that bit of data. Instead, whenever the second loop would want to send a message to the other enqueuer, it sends a message to itsself and then when itself receives the message, that message says to send the message onward to the other enqueuer.
0 Kudos
Message 7 of 8
(4,701 Views)

OK, This is definitely making sense now.  Thanks to all of you for your responses and ideas on solving this.  The concepts of OO with classes done by pointer instead of by value (and having that wire forked) are sure easy to forget when looking at OO in LabVIEW and data flow, despite being knowledgeable in LabVIEW.  AF is a lot to learn all at once so sometimes, these things get forgotten.  Anyway, I see now that I will have to do some kind of data value reference or control references like you suggest if I need to update the data in both the actor core override loops as well as the parent call for messages.  This makes sense and I will certainly look to design that OUT wherever possible in my applications.  That seems simpler than having to account for mulitple copies in mulitple places. 

I am definitely liking this AF as I implement more things in it, but understand some of these seemingly small maters are important to me to really understand, not just work around to then design it in well.  Thanks again for the help and the AF!

Message 8 of 8
(4,701 Views)