Actor Framework Discussions

cancel
Showing results for 
Search instead for 
Did you mean: 

An idea to make Class Private Data accessible to helper loops

As a beginner in Actor Framework I was really frustrated that my helper loops weren't able to access class private data.  This is an idea we had to make that data more accessible.  User events are a convenient way to transfer data, so we started by creating an event whose data type is Actor.lvclass (We also created an event to shut down the helper loop.):

Initialize.png

Because we need the registration refnum for the event structure in a helper loop, the above sub.vi is called on the block diagram of the Actor Core.vi.  The event can be triggered by a message or by calling the method directly in a method in the actor core:

Snapshot.PNG

Here's the big caveat we've identified - you're making a COPY of the class data.  This has memory implications and this is just a snapshot of the class data at whatever point in time.  The guts of the snapshot .vi look like this:

Snapshot core.PNG

Once the event is generated, you just have to convert to more specific and unbundle the data snapshot:

Actor core.PNG

So, my question is this:  Other than the memory implications of copying class data, what problems/drawbacks do you see with this idea?  I've attached a sample project in 2013.

0 Kudos
Message 1 of 20
(11,766 Views)

I think that the memory implications are usually the more minor issue. The main problem is that the basic design is that you have a single copy of the object in the shift register and this guarantees that your object is always in a well-known state. If you create a snapshot, you run the risk of creating bugs, not necessarily in the present, but as time goes by, it becomes more likely you won't take into consideration the fact that you have a parallel loop handling a copy of the object.

We had some discussion about this here - https://decibel.ni.com/content/message/51597#51597

I didn't see that anyone there saw any real benefits to this. Some of us said we might be willing to make that tradeoff under specific circumstances, but I don't think anyone thought it was a good idea.


___________________
Try to take over the world!
0 Kudos
Message 2 of 20
(5,189 Views)

That's certainly good information, but the [initial] topic in that thread is sending an actor object to another actor.  In this case the actor object copy keeps it all in the family.

The problem I was trying to solve was how to update UI elements based on the object's data.

The benefits I see:

This provides a path to get data from the object to the UI helper loop without passing UI references into the object.

This allows any change to the .lvclass data to be immediately available to the UI helper loop.

This functionality is inherited so anything that I have inherit from this class can send their unique type of data to their own UI.

Do you see a way to accomplish the same function while protecting the object copy from abuse?

0 Kudos
Message 3 of 20
(5,189 Views)

I personally like this approach and think it a decent way to do things.  I think a lot of people on this forums would say that you should make the GUI is own actor and pass messages to it. At some point though you just need to show info and i like your approach.

If you are REALLY concerned about data copies, and i wouldn't be unless you have a lot of actors, you might consider a DVR. You could fire a generic event that doesn’t contain the actor as its data type. It could just be a Boolean or even the DVR reference if you want to. 


Then when you handle the event read info out of the DVR. This should give you the current state of your actor object, however it has some caveats.  You need to be careful about reading out of the DVR since it’s blocking and could slow down your actor core if you aren't aware of it. You obviously also have the potential to directly edit your actor object in a separate loop which is also dangerous. 

The nice part is that you can use property nodes to read directly out of the DVR if you set up public accessors for your actor object.  Again you need to be careful with writing in another loop. 

You would also have to use a generic actor object as the DVR since a object can't contain an reference to itself.  There are obviously other way to get the latest data as well.  You could use a notifier, although i think this also leads to data copies, or a varient attribute lookup table.   

One other thing to consider, that might make your program more flexible is to add a "DataObject" to your actor and instead of passing your entire actor to other places in your program, pass this data object.  You could even start with a generic object that you would use in several different components and make child objects that provide specific methods for certain actors or data sets.  This once agian creates more data copies, however it gives you a flexible way to process and work with only the data component of your actor.

0 Kudos
Message 4 of 20
(5,189 Views)

I also think this is a good approach, but am biased since I've been using it along with fairlyFunctional (:

Here is my two cents. The point is that this method _is_ being used in/as our GUI Actors. It gives us a great way to get a snapshot of the class private data that is generally accessed via referencess previously. Honestly, one of the major reasons behind our design decision was that we were trying to sell the idea of the AF to some of our workmates, and we wanted the code to be as clean as we could get it and abstract out as much functionality as we could into a parent helper class (because in my opinion Actor Cores are generally pretty dang ugly, no offence AQ and NiACS). So, in this idea we've been using, you have your UI actors inherit from this helper class, and then all you have to do is drop the initialize.vi (that first image), wire the event registration and unbundle whatever Class Private Data you need to into the UI event structure, and then whenever you need to update your UI (like after you update some data for instance), just drop the send "CPD Snapshot" and voila, your UI is automagically updated. I want the name of that VI to be "Send a snapshot of the Class Private Data to the UI Helper Loop Event Structure" but the name wouldn't fit on the icon (;

It makes it so we don't have a group of controls hanging around without a home in the Actor Core, all the mess of getting the UI control references into the class private data before spinning up the Actor Core loop, and it updates the controls directly instead of by reference, which is much faster. You also only need to update your UI when data changes, which could be a benefit, but which is likely balanced by the unfortunate fact that it is just a snapshot. Oh, and it is nice that when you change your class data, like fairlyFunctional mentioned, the data is already available for the UI, without any additional coding. I mean, just look at that last image. For a GUI Actor Core, it is pretty clean!

In response to tst, I agree that it is unfortunate that there is the potential for abuse which is why we've tried to delineate it as just a snapshot as best as we could, so that *hopefully* I will not ever be tempted to modify the data in the helper loop and think that the class private data is actually changing. I guess I have that drilled into my head because I've been using the Actor Framework for a bit, but I can certainly see new users grabbing that class wire and using it for something other than a UI updates since as a new user I was always looking for an easy way to access the class private data when in a helper loop. I mean, I'm in the class, shouldn't I be able to access my own data... but sadly, no, I need to send a message to myself since my class object is stuck in a different loop waiting for messages (:

-Carl

0 Kudos
Message 5 of 20
(5,189 Views)

Only thing I would change in fairlyFunctional's design is the thing Jed394 suggests:

Jed394 wrote:

... One other thing to consider, that might make your program more flexible is to add a "DataObject" to your actor and instead of passing your entire actor to other places in your program, pass this data object.  You could even start with a generic object that you would use in several different components and make child objects that provide specific methods for certain actors or data sets.  This once again creates more data copies, however it gives you a flexible way to process and work with only the data component of your actor.

However in this case you have to take care to use the proper child object (of "DataObject") when writing to or reading from it.

By the way I also use user events to pass data from actor core to helper loop, but I separately register every piece of data that I want to have in the helper loop. This is more tedious work, but you can handle different data in different event cases. Also a bit less data copy.

0 Kudos
Message 6 of 20
(5,189 Views)

I didn't actually remember that the other thread talked about a separate actor. It's true that doing it in the same actor is somewhat safer, because it all supposedly goes together, but the same conceptual issues exist as soon as you create a copy of the object, regardless of where it actually ends up.

Sleepy_Engineer wrote:

...we've tried to delineate it as just a snapshot as best as we could, so that *hopefully* I will not ever be tempted to modify the data in the helper loop and think that the class private data is actually changing.

Note that this isn't limited just to that problem. There are other things which could be affected by this. For instance, maybe you're modifying something in some subVI in the main loop and the UI loop no longer has the updated value. Maybe you have DVRs or other references and now the UI loop is also interacting with the the main loop's data, etc.

Like I said in the other thread, there are certainly places where I might use this direction, but it is important to be aware of the potential pitfalls and make a calculated decision.


___________________
Try to take over the world!
0 Kudos
Message 7 of 20
(5,189 Views)

I thought about the concept a bit and tried to compare to my solution. In my solution I create and register user events for every level of the class hierarchy separately to not to overwrite any previously created or registered user event of a child with a parent (using the "Call Parent Method"). This makes it necessary for me to make a static dispatch method for every class to "create and register events", and it makes it harder to copy the class as a template, because I have to rename the "create and register events" method in every copy. You can read more on my problem with using dynamic dispatch methods together with "Call Parent Method" here.

In your concept you have a problem if you ever want to make a child of the Sample Actor, because your "Initialize.vi" will be called first by the child object and than by the parent object. So the user events in the private data will be overwritten, and the child loop will never get the event case fired.

This situation gets to be the most critical (IMO) in case of stopping the actors. The parent actor will receive the user event to stop it's helper loop, but the child actor not. So you will not have a proper shut-down procedure and sequence.

By the way this problem never happens if you work with a flat hierarchy, and make only children but no grandchildren of the Carma Actor.

I edited your sample project to try it. Run the "Run Me" with Launch Child set to TRUE and you can see it for yourself. I actually opened the block diagram of both "Child Sample Actor" and "Sample Actor" and turned on Highlight Execution to see what happens.

0 Kudos
Message 8 of 20
(5,189 Views)

I made another try and modified the project a bit. I moved the "Initialize.vi" in to PreLaunch Init. (The splash screen queue has to updated with a different VI than.) This way it works, both event structures receive the events.

However it is against the recommendation to use one Event Registration Refnum in multiple event structures.

One caveat I already see is the deinitialization. It should be moved to the stop core to not to do it twice. But that's no problem, it can be done. (or at least I don't see any problem with it now )

Edit: There is a problem with moving the deinitialization, namely the "Shutdown.vi" to the stop core. It kills the Event Registration Refnum before the event structures could handle the stop event... Shold be done later. Maybe with the Handle Last Ack? don't really know, just an idea.

Honestly I don't know what happens inside LabVIEW when handling events, but you should be aware of this recommendation... Maybe it's not even true, I don't know. In this case it works.

An expert could step in at this point and explain why not to use one Event Registration Refnum in multiple event structures, if it is so.

0 Kudos
Message 9 of 20
(5,189 Views)

komorbela wrote:

However it is against the recommendation to use one Event Registration Refnum in multiple event structures.

...

An expert could step in at this point and explain why not to use one Event Registration Refnum in multiple event structures, if it is so.

I don't know if I would consider myself an expert on this, but I am someone with experience and I can tell you that you shouldn't look at this as a recommendation or a best practice - consider it an absolute rule you must not break. My experience was that if you do break it, you will get completely undefined behavior (which is bad in itself), which is also weird (which is worse. I'm talking about things like events being processed twice or completely disappearing even though no one registered for them, timeouts not executing, etc.). Just don't do it. It's easy enough to have a separate event reg refnum for each event structure.

If you want more details, there's a link on LAVA to a video of Jack Dunaway's NIWeek 2013 presentation about events, where he goes into the behavior of events under all kinds of circumstances, which is highly recommended.


___________________
Try to take over the world!
0 Kudos
Message 10 of 20
(5,189 Views)