Actor Framework Discussions

cancel
Showing results for 
Search instead for 
Did you mean: 

Wrapping an Actor in a Class

Solved!
Go to solution

Hi All

 

Is it possible to wrap a single Actor Object in a typical class (derived from LabVIEW Object), and be able to Launch, Stop and Send/Receive messages from it?

I don't want to derive the wrapper class from the AF Actor class, because I never want to launch it. I don't need the extras that come with it. I just want to encapsulate the actor with manipulation complexity, and work with it in a single wrapper class instance, and make as many further instances as I need with different configuration setup, etc. The reason I want to wrap it is because the parent actor is getting full and complicated, and I want to decompose this complexity. The nested actors do a job, and I want to keep as much of what they do hidden in this wrapper class.

 

Launching, I was thinking I can pass in the parent class, just into a public VI. Or even have a private copy of the parent Actor in the wrapper.ctl properties.

Stopping just need the Enqueuer.

Sending just needs the Enqueuer.

Receiving Callbacks - This is where I get stuck. I am not practices at creating an abstract message callback, and only know the new (LV 2020+) Class Interface creation approach for actor return messages. I am therefore not clear as to whether I can have override handler VI's in the wrapper class, which will be called separately for each Actor instance that gets created when I make instances of the wrapper. What I mean is, does the handler VI for return/callback messages HAVE to reside in the parent Actor, or can I actually have wrapper class instance callback handlers? Or maybe wrapper class static callback handlers?!

 

I hope you get where I'm coming from.

Anyone got any experience of doing this and maybe a sample?

 

Thanks in advance.

 

Message 1 of 7
(413 Views)

It sounds, you need multi-inheritance but this is not supported be LVOOP design.
Well, I assume, it would be easier to make your base class inherit from Actor.lvclass, add additional stuff by composition in the child classes and make it accessible by interfaces. As long you do not launch your actor, it just a passive LVOOP object and the unused AF overhead is quite small.

 

I not really understand: should only some child classes have actor behaviour and the others not? Alternatively, do you want to make passive actor active by a non-actor container object? Can you please send a class diagram and describe your application?

0 Kudos
Message 2 of 7
(399 Views)

Thanks for the reply.

 

I have made a "TCP TxRx" Actor, which when sent a message, Opens/Sends/Waits for reply/Passes Back reply/Closes, a TCP interchange.

The wrapper class was to provide a queue of messages to be fed the Actor as messages are completed.

An instance of the wrapper would allow different TCP interchanges between different target hosts on the network, at the same time (different ports, IP addresses of targets, etc). 

 

The callback from the "TCP TxRx", once a message was received back, was going to pass the received content on to a Static VI configured within the wrapper, for consumption. Thereby allowing tailoring of response processing depending on the message type, content, etc., received back. The message to be sent could also be configured to many different message types.

 

I wanted the wrapper to fully encapsulate the Actor, so that I did not need to worry about it falling over if an error took place, or restarting a send if there were timeouts, etc.

 

I have realized now I can't even launch an encapsulated actor because the "Launch Nested Actor" is protected. It looks like I am forced to have to inherit, and call my wrapper something like "Command Manager" or something.

 

It seems a bit of a weakness of the AF that I can't do this. Though I can accept and work around it.

I just hoped there was an approach, as I feel I am overusing the AF in my application. It feels like an AF rabbit hole. You are forced to inherit from AF.

 

I think I've answered my own the question. But if there is a technique to wrapping an Actor it would be useful for the future.

If you still want it, I will pass you a test project. But it won't work as the actor won't launch within a class that is not inherited from the AF Hierarchy.

 

0 Kudos
Message 3 of 7
(380 Views)

Typically in such a situation, you would not wrap the class... you would make it a nested class of a higher level actor and forward messages to it. With interfaces, this is pretty trivial: your main actor launches actor A which launches actor B. B is the one whose functionality you want to isolate. I recommend that you hide the complexity with deeper layers of nesting, not with encapsulation. 

 

Wrapping an actor in another class causes a lot of headache code... I won't go into all the details, but I'll just say that although it is totally possible to do, you'll find yourself writing a bunch of brittle glue code that you probably don't want to maintain. 

0 Kudos
Message 4 of 7
(373 Views)
Solution
Accepted by topic author skol45uk

What speaks against making your wrapper object a root actor? It in turn launches Nested Actors, which take over point-to-point TCP communication. Maybe the Network-Endpoint-Actor is useful for you.

 

I am quite sure, you will save a lot of work, if you stay in standard AF-concept. You will get automatic error handling. If an actor crashes, you can handle this in "Handle Last Acknoledge Core.vi" and restart it on demand.

 

By the way, of course our can start an encapsulated actor object by calling Launch Root Actor.vi . You can communicate with non-actor wrapper as described here by AristosQueue.

 

 

0 Kudos
Message 5 of 7
(366 Views)

I kind-of got to the same conclusion thats its better to work with the framework, than try and crowbar it.

Thanks. It really helps just having my problems confirmed as 'normal'. And the link to a discussion really expands my appreciation of the AF.

 

 

0 Kudos
Message 6 of 7
(290 Views)

Sometimes I've wanted to put my Nested Actors inside a non-AF wrapper class too. But in my case it's adding management functionality that belongs to the Caller, for example the Nested's state, enqueuer, display-name, stuff like that.

 


@skol45uk wrote:

I have realized now I can't even launch an encapsulated actor because the "Launch Nested Actor" is protected... It seems a bit of a weakness of the AF that I can't do this.


I bump into this limitation too - it is only possible to Launch Nested Actor from the Caller's VIs. It sounds fine on the surface, but I think there are valid cases where the actual "Launch" should be delegated into helper classes. You can probably use the original (and now deprecated) Launch Actor, but this is a workaround and you'll need to re-implement the auto-stop functionality.

 


@skol45uk wrote:

I have made a "TCP TxRx" Actor, which when sent a message, Opens/Sends/Waits for reply/Passes Back reply/Closes, a TCP interchange.

 

...the wrapper would allow different TCP interchanges between different target hosts on the network, at the same time (different ports, IP addresses of targets, etc).

 

...allowing tailoring of response processing depending on the message type, content, etc., received back. The message to be sent could also be configured to many different message types.


This sounds like you should:

  1. Launch one "TCP TxRx" Actor per target host on the network (configure the Actor with IP:port before launching it).
  2. Create an AF Message for each TCP message & response type (assuming they're reasonably enumerable, like less than 20(?) types).
  3. Send those messages to a subclass of "TCP TxRx" that flattens the AF Message to TCP format, calls your core Open/Tx/Rx/Close, parses the TCP Rx into an AF Message that's sent back to the Caller.
  4. If the target hosts need different behavior, make more sub-classes of "TCP TxRx".
0 Kudos
Message 7 of 7
(267 Views)