Actor Framework Discussions

cancel
Showing results for 
Search instead for 
Did you mean: 

AF Advices for Service Implementation....

HI,

I'm using using LabVIEW since 12 years for developping a lot off different apps in different domains, and on different type of target (RT, FPGA or traditionnal OSs). I spent the last 2 days exploring he AF, and I'm asking myself some crucial questions regarding the transition from my "coding style" to  the AF coding Style.

Here is how I usually work:

- During conception, every application is divided in multiple threads (One Dynamic VI per thread, that I call Service)

- Each Service creates its own FIFO(s), and receive order from that FIFO(s). The main advantage is that we can start the Service alone, witouth the need to start a upper level VI (Very useful for debug).

- Each Service is stored in a lvlib, and I provide as a public interface:

     - A launcher of that dynamic VI

     - One or more (ready to use) VI that sends request to the FIFOs.

      - All other SubVIs are private to the lvlib

- Each request contains a Notifier saying where to respond for the Service (Interface VIs are implemented to post the order in the FIFO, and wait the answer and extract the content).

- Usually, a Service is composed by 2 loops:

     - First Loop is the Request receiver. This loop manage either the order or delegate the order to a secondary loop. In any case, on each event it must answer to the notifier as soon as possible. By this way, I know if a request has been treated correctly.

     - Second Loop is a "delegate", responsible to manage all "real" operation (HW, File or all slower operations).

I can have a multiple level of service, but communication is only working in one way. This my developper responsability to respect this rule.!

Global and FGV are forbidden in my coding style

All the previous stuff is very easy to do because I have developped a lot of library and template which make very easy the process to create a new thread and to customize it. All those libraries are made with tradionnal Lv and OOP.

Here is my questions:

Regarding the AF, I understand that what I call "Service" could be implemented as an actor, and all request are implemented through "Message Object". 

The advantage I see to this architecture is the communication tree:

     - This is more robust than my coding style.

     - This is more flexible, because for me, a Service can only respond to a higher service. A service can't send directly a message to a higher service.

1. The main trouble I have, is due to the nature of an actor: I can't launch the Actor alone without its FIFO context. Am I right? (If I want to run that Actor alone, I need a new VI which create FIFO and then Launch that Actor)

2. I didn't see any "Message" allowing to wait for an answer from the Actor, and to be sure that the message has been treated whatever the result? Do I missed something?

3. Regarding my coding style, with the AF this is very easy to implement what I call "Request Receive Loopr" from my Service Template, but I do not see how to implement the "Delegate Loop" part? I don't see or understand how to add a loop on the Actor Core which could continuously handle or modify private data while maintaining a right behavior for the messaging.

Here is an example of what I could do:

-  I need an actor which is responsible to discover modules on a cRIO system.

-  This actor manages 3 Messages: StartDiscover / IsDiscoverDone / StopDiscover

  - As the discovering process is quite long, it can't be done in a Message handle, but in a separate loop added in the Actor Core.

  - I don't see how to pass data from my added loop to the private data of Actor whithout disturbing the behavior of the Actor ?

Thanks for your suggestions.

Regards

Cordialement,
Raphael T
0 Kudos
Message 1 of 4
(5,706 Views)

Hi Jabba,

I have recently started using AF (a couple of months now) and this is definitely one of the first things that I got hung up on, but have hopefully at least gotten a small grasp of how it should work. The Actor object exists in its own little loop in the Actor Core parent method vi waiting for messages to be sent to it. My first instinct was to take the object wire, before it went into the Actor Core Parent Method and branch it into the added loop, where I could then pass it into the private methods. This obviously didn't work since I just made another copy of the object, had one sitting in the added loop and one sitting in the Actor Core Parent Method (where it belonged). Which is when I realized that you have to talk to the Actor via messages, since it is just sitting in its loop and there is no direct access to the Actor object. I know that the documentation talks about that, but it didn't click where that object exists until I tried to pass it into that added loop as well.

So, back to the question (#3). If you pass your "Self Enqueuer" into the added loop you can now pass messages to your Actor object. By going through the AF hands-on tutorial you can see how this is done: creating an write accessor method and then using the Tools->Actor Framework Message Maker to make the message and then adding the new message's "Send message_name.vi" to your added loop and wire your Self Enqueuer to it. The AF template has examples of this.

Hopefully I am at least directionally correct... I feel I am at a point where I can make the Actor Framework do what I want, but still a novice as far as understanding design and best practices.

As for question's 1 and 2, I don't know, but I'm sure that someone who does will respond soon (: I have always launched my Actors, and believe that you need to. And I haven't done anything where I needed to wait for a reply.

Regards,

-Carl

Note: Getting private data from the Actor object is entirely different. You can't send the message to run the objects "read accessor" method and expect the data to appear anywhere without a little work. The Read_Data.vi method that you create needs to somehow send the message back to the added loop. It can do this through a user event similar to what is used to stop the added loops in the Evaporative Cooler example that ships with LabVIEW 2012 or you could do this through some other method like updating the value of a control through a property node in the Read_Data.vi. This could be done by adding a reference to the control, that is in the Actor Core's added loop, into the Actor objects private data (before it goes into the Actor Core's Call Parent Method VI where it will exist for the rest of its life) and then unbundling that reference in your Read_Data.vi to feed to the property node. OK, it was simple in my mind but sounds much more complicated (:

I guess what I've found is that to get data from an Actor you either have to have some way to reference where the data is going to in the Actors private data (like the reference just mentioned or like the User Event from the first method), or if you are the caller trying to get data from a spawned actor you can get it through an abstract message (where the spawned actor sends you the data and you process it with whatever method you want). In this case you might have to message the spawned actor to tell it to send you the data. Is this a good way of doing it? It seems circuitous to me, but I guess it keeps the coupling down.

It also may be that when you say that you don't see how to pass data without disturbing the behavior of the Actor that you are asking for something other that the basic sending of a message that I described, in which case I apologize for rambling and wish you the best of luck!

0 Kudos
Message 2 of 4
(3,207 Views)

Hi Jabba,

I hope I can give you some help, however I am also not so experienced in using the AF (know it for about half a year now). So:

1. The main trouble I have, is due to the nature of an actor: I can't launch the Actor alone without its FIFO context. Am I right? (If I want to run that Actor alone, I need a new VI which create FIFO and then Launch that Actor)

If you ask whether it's possible to start an Actor without using the "Launch Actor" or not, than my answer is to use the "Launch Actor". An Actor lives by communicating though it's messages so you can test it the best way if you use it's messages. The Actor object may have other public methods that could alter it's functionality, but if you don't have messages to those, no need to test for those methods. By the way I usually have a main class that has all the functionality of the Actor, and make a child that have the methods that are used by the messages. this way you can simply run the methods of the main class from a test VI to test the proper functionality before creating messages to it.

2. I didn't see any "Message" allowing to wait for an answer from the Actor, and to be sure that the message has been treated whatever the result? Do I missed something?

There is a message that is synchronous("Send Message And Wait For Response.vi"). You can send a variant back to the sender with it (and receiver can decide what the variant should be ) It is useful sometimes but I suggest not to use it often. Rather send a message from the receiver that reflects the status of the receiver. (or sends whatever you want) This way you don't block the sender actor while waiting for the answer.

3. Regarding my coding style, with the AF this is very easy to implement what I call "Request Receive Loop" from my Service Template, but I do not see how to implement the "Delegate Loop" part? I don't see or understand how to add a loop on the Actor Core which could continuously handle or modify private data while maintaining a right behavior for the messaging.

I see 2 ways to do it:

1, The main unit of the Actor framework is an Actor. It means that you can use it build any more advanced structures that will be the unit of your programs. So what I say is that you don't have to use only one actor as a parallel running process. You can also use a combination of 2 Actors that mimic the functionality that you need. Here is how I think the actors should work:

The 1st one will be the message receiver Actor. It handles the messages and sends messages as needed. Also knows about the status of the other Actor (the Worker Actor). It sends messages to the other Actor as needed.

The 2nd Actor, the Worker should be launched by the 1st, and communicate only with it. It receives messages from the 1st Actor and does the long lasting processes. It notifies the 1st Actor about it's processes to help in correct message handling.

2, Create a queue before launching the Actor and communicate through it from the Actor Core to a loop in the Actor Core override. You can do it in the "Pre Launch Init.vi" or in the Actor Core override before calling the Actor Core and before the extra loop.

However the 2nd way is not clean. It steps out of the Actor Framework's designed way of operation. I suggest even use twice as many actors and use the 1st solution. That way you will stay compatible with the Actor Model. I don't know why, but I would avoid the 2nd solution, however it seems to be easier to do for the first run.

I hope my answers are understandable and help you. If you have any questions, just feel free to ask.

0 Kudos
Message 3 of 4
(3,207 Views)

Hi Jabba,

I'm on the Actor Framework feature team here at NI, and I am the Systems Engineer that catches most Actor Framework requests.  crwecker and komorbela are mostly right, but I'd like to give you some more succinct answers to your qeustions.

1. The main trouble I have, is due to the nature of an actor: I can't launch the Actor alone without its FIFO context. Am I right? (If I want to run that Actor alone, I need a new VI which create FIFO and then Launch that Actor)

You are correct.  If you want to run an actor, you must pass it and a message queue reference to Launch Actor.  So, in practice, if you want to test a running actor, you need to write a test harness - a VI that launches the actor, and allows you to send it messages (including Stop).

2. I didn't see any "Message" allowing to wait for an answer from the Actor, and to be sure that the message has been treated whatever the result? Do I missed something?

No, you didn't.  We hid it from you.   But you can find it in ..\LabVIEW 2012\vi.lib\ActorFramework\Reply Msg.  It's called Reply Msg.lvclass, and you can use it to implement synchronous messaging.  You have to make the message by hand; we don't (yet) provide scripting to do this.  To make a Reply Message:

1.     Create a new class, called <my function> Msg.lvclass, and make it inherit from Reply Msg.lvclass.

2.     Add whatever data you need to the message's attributes, and create a VI to set those attributes.  (For this kind of work, I often create a VI that takes the message payload as input, and returns an instance of the message.)

3.     Create an override method for Do Core.vi (not Do.vi).  That override will call a method of the receiving actor and return any output as a variant.

To use your new message, use the VI from step 2 to create the message, and then send it using Send Message and Wait for Response.vi.  The VI that sends the message will wait for data to be returned, possibly forever unless you set a timeout.

And that is the reason we made it hard to find this message type:  if you are not very rigorous in how you use them, Reply Messages can cause your system to deadlock.  We therefore strongly encourage you to avoid using them.  I vigorously argued for this message type in the framework, and I still believe it should be there, and in three years I have only found two use cases for them.  There is almost always a better way.

If you'd like, we can talk about some options for verifying that messages have been received and/or processed.  We can do it here, or you can send me a private message.

3. Regarding my coding style, with the AF this is very easy to implement what I call "Request Receive Loopr" from my Service Template, but I do not see how to implement the "Delegate Loop" part? I don't see or understand how to add a loop on the Actor Core which could continuously handle or modify private data while maintaining a right behavior for the messaging.

The previous posters outlined your two choices:

1.  Override Actor Core, and add your delegate loop.  That loop acts on private actor data just like anything else - it puts a message on its send-to-self queue.  We provide a handy accessor that will get you that queue, so you can pass it into the delegate loop.  You can pass data from the message handling loop back to the delegate loop by any method you desire:  control references (works best for user interface actors), user events, notifiers, and regular queues are all valid choices, depending on your situation.  Your delegate loop is free to maintain its own state data, as well.  (komorbela, notifiers and queues are OK within an actor, as long as you take proper care to make sure the stacked loop will properly terminate.  What we don't want is to use these methods to communicate between actors.)

2.  Launch a nested actor.  The methods of this nested actor will perform whatever actions you require of your delegate loop.  Pass data between the message handler and the delegate using the caller and actor queues.

I recommend you take the time to work through the Hands-On: Actor Framework material.  It's 2 - 3 hours, and covers most of this.

Good luck, and feel free to ask more questions!

0 Kudos
Message 4 of 4
(3,207 Views)