08-16-2012 02:40 PM
Given that Actors are multi-instanceable, are there simple rules of thumb for setting the reentrancy (none, shared, full) of public methods called by Message:Do.vi and methods used in the Actor Core.vi override?
08-16-2012 03:11 PM
And an adjunct question: If full reentrancy is used on message methods, then I think those methods can't be allowed to retain state between calls. Is that correct? It seems like I need to cache state in the object wire instead of a SR or FN inside the method, because the same instance of that method isn't guaranteed to be used by the next received message.
08-16-2012 03:18 PM
For debugging purposes, I find it easier to disable re-entrancy. If this is not possible, then I generally launch the Actor core's front panel and "Step Into" the methods of interest.
DavidStaab wrote:
And an adjunct question: If full reentrancy is used on message methods, then I think those methods can't be allowed to retain state between calls. Is that correct? It seems like I need to cache state in the object wire instead of a SR or FN inside the method, because the same instance of that method isn't guaranteed to be used by the next received message.
Yes, feedback nodes/uninitialized shift registers become evil. All "flags" should go in the private class data.
08-16-2012 03:23 PM
Hi LVB,
Could you expand on how you launch the Actor Core's front panel (and if the method will work in a RT environment running in development mode) and then how you "Step Into" the methods?
Cheers
08-16-2012 03:30 PM
To show the actor core front panel:
You can create a custom probe to check the message type in the Actor Core and break on the name. Then use the Operate -> Step Into (CTRL+DOWN) to open the Do.vi method that is dynamically dispatched and the associated Actor class method. Note: This is on a windows desktop, not a RT system.
08-16-2012 03:39 PM
Debugging functional logic isn't an issue here. I develop my classes for static operation first, test them, then wrap them in AC.vi and Do.vi. This lets me debug using the native LV tools with statically linked code.
The issue is that I wrote this huge class using a lot of stateful subVIs, and only when I moved to a multi-instance testbench did I realize the mistake. I'm going through the class and setting reentrancy on all its methods (which led to the first question about which type of reentrancy to use in each situation), and I realized that I'm going to have to move all that stored state out to the class's scope in order to make it work correctly.
The longer I write software, the more I become convinced that internal storage of any state is a generally terrible idea. Scope it privately it and push it all up to the caller for storage!
08-16-2012 03:49 PM
I think the re-entrancy decision is the same with or without the Actor Framework.
The rule of thumb I use for re-entrancy is the KISS principle. If I don't need the performance or am not concerned about "blocking" methods, then I don't make it re-entrant. One nice "feature" of a non-reentrant VI is the developer will know that no other Actor can be executing the method (psuedo locking/mutex).
08-16-2012 03:52 PM
If you write an Actor, you have to assume it's going to be multi-instanced. If you want to prevent that, the only way to do it is with a run-time check that throws an error when the second instance is launched.
In my specific use case, I need exactly 4 instances of this actor now and up to 16 later. So I'm stuck working with reentrancy. (For those following along, my original post about defining rules of thumb is still unanswered.)
08-16-2012 04:14 PM
i haven't had time to test this out, but this is the approach i was planning to use when i go to the AF.
for initialization & shutdown VIs, make them non-reentrant. performance shouldn't be as critical here. i typically launch all of my dynamic stuff in a serial manner and this jives with that.
for message and core VIs, make them reentrant with shared clones. it should be efficient in a single instance and scale up when you need it.
of course, the above approach doesn't make any considerations for ease of debugging...my plan there was to change them over as needed during the debug process.
08-16-2012 05:58 PM
The guidance for which methods to make which kind of reentrancy is the same as for any other VI. There is no difference.
Non-reentrant: By far the most common setting for VIs. Use this for functions that
Full reentrant: Use this for functions that
Shared reentrant: Also known as pooled reentrant because clones are in a common pool. Use this for functions that:
DavidStaab wrote:
And an adjunct question: If full reentrancy is used on message methods, then I think those methods can't be allowed to retain state between calls. Is that correct? It seems like I need to cache state in the object wire instead of a SR or FN inside the method, because the same instance of that method isn't guaranteed to be used by the next received message.
Shared reentrancy is the one that cannot have state. Full reentrancy can have state because every subVI node will get the same instance every time it is called. It cannot have *shared* state -- shared state is for non-reentrant VIs.