SteveChandler Posted October 9, 2011 Report Share Posted October 9, 2011 I have been using the LapDogAPI Messaging library along with the Slave Loop pattern posted by Daklu. Recently I have been looking into the Actor Framework and do not yet completely understand it. Conceptually what is the difference? I know there are significant differences in how they are implemented and that the Actor Framwork dynamically launches a reentrant VI. But could the slave loop pattern be considered kind of like an actor framework? The thing I really appreciate about the LDM is it's simplicity. What are the main benefits of the Actor Framework? At the highest level aren't they both just loops with input and output queues with an object as the datatype? Quote Link to comment
drjdpowell Posted October 10, 2011 Report Share Posted October 10, 2011 I haven't actually used either and don't even have a working computer with LabVIEW at the moment, but from memory of looking at them: I would say the the "Slave Loop" design is a type of actor framework. The biggest thing about the "Actor Framework" is that one can create child actors that inherit from parent actors and add functionality. This is because it uses an "Actor" object to contain the internal state data and dynamically dispatches important methods like "Actor Core" off of it. -- James PS> you could also have a look at mje's "Message Pump" framework for a different design that does similar things. Quote Link to comment
Daklu Posted October 10, 2011 Report Share Posted October 10, 2011 Good questions Steve. I haven't used the Actor framework nor talked to AQ about it in depth, so if I misspeak hopefully somebody will correct me. You are correct in that they are both techniques to encapsulate an arbitrary unit of functionality running in one or more separate threads. The most obvious difference is AF provides more built-in functionality. Slave objects are simply a pattern you need to implement yourself. Each has its advantages. The AF requires (I believe) you to use the included command-based messaging system. Slaves can built using whatever messaging infrastructure you have. I like the command pattern for certain situations but I'm not fond of it as a general purpose messaging system. It feels too restrictive. YMMV. On the other hand, ideal OOP replaces case structures with dynamic dispatching, so command-based messaging is arguably more pure. AF's built-in messaging may make it harder to introduce Actors into existing code. I assume you could write an adapter to fit each actor into an existing messaging system, but like I said I've never used the framework. I know people have been successful using it as a springboard for designing new systems. Personally I try to follow the Agile principles of implementing only what is necessary, growing the software organically (rather than doing a lot of design up front,) and continuous refactoring. That means I need small steps of increasing functionality and encapsulation. A typical progression for me as functionality increases might look like this: [Note - While classes provide the basic unit of functionality, loops provide the basic unit of execution. It's just as important to manage the interface exposed by a loop (the messages it handles) as it is to manage the interface exposed by a class or any other api.] 1. Classes A & B collaborating in a single loop (loop 1.) 2. Class B needs to run concurrently so I move it to a separate loop (loop 2) on the same block diagram and use messages to transfer information. 3. Class B's functionality has increased and become less cohesive, so I refactor it into B, C, & D, all running in loop 2. The messages and arguments exposed by loop 2 change very little, if at all, in this step. 4. Class D needs to run concurrently so I move it to loop 3 on the same bd. Loop 3 is a subset of the functionality provided by loop 2. Loops 1 and 3 have no knowledge of each other. Any messages loop 2 receives intended for class D are forwarded to loop 3. After a few iterations the block diagram starts to get confusing, so I'll break off a branch of functionality (loops 2 and 3 in this case) and wrap it in a SlaveB object. Nothing changes in loop 1; I've simply made a small refactoring that balances the level of abstraction on the original block diagram and improves readability. At this point I can instatiate multiple instances of SlaveB by dropping more Creators on a block diagram. I don't use dynamic launching unless I need a large or unknown number of instances. However, it's easy to add a Launch method to a Slave and turn it into an Active Object. I believe it's also relatively easy to wrap a Slave in an observable object, upgrading it to Publish-Subscribe. Changing from a parallel loop to an Actor object feels like a big jump to me. There are probably logical intermediate steps between them, but without any experience using it I don't know what they are. Maybe Stephen will weigh in. I've considered adding LapDog libraries for things like Active Objects, Observables, etc. One of the reasons I haven't is they would have a dependency on the messaging system, which violates my original intention for all LapDog packages to be independent. I may just bite the bullet and do it anyway. (After I release Collections, which is only... oh... 13 months late.) But could the slave loop pattern be considered kind of like an actor framework? I don't think so. A Slave object is an intermediate step between a parallel loop on a block diagram and an Active Object, Observable, or other higher level functionality. I'm not sure what Stephen's intent is but the literature I've been able to find on Actors seems to indicate different architectural considerations. That said, I haven't heard what *he* thinks the differences between and Actor/ActiveObject/Slave are. I could be completely off base. Quote Link to comment
drjdpowell Posted October 12, 2011 Report Share Posted October 12, 2011 Changing from a parallel loop to an Actor object feels like a big jump to me. There are probably logical intermediate steps between them, but without any experience using it I don't know what they are. Maybe Stephen will weigh in. I would imagine that, if one were strictly using command-pattern messages with dynamic dispatch (instead of case structures), it would be relatively easy to convert from an on-diagram loop to an Actor (since the messages are decoupled from the structure handling them). Of course, if one doesn't strictly use the command pattern from the start, converting to an Actor would be much harder. (After I release Collections, which is only... oh... 13 months late.) I could really use such a a thing and am looking forward to it. I don't think so. A Slave object is an intermediate step between a parallel loop on a block diagram and an Active Object, Observable, or other higher level functionality. I'm not sure what Stephen's intent is but the literature I've been able to find on Actors seems to indicate different architectural considerations. That said, I haven't heard what *he* thinks the differences between and Actor/ActiveObject/Slave are. I could be completely off base. I think it's all a loosely defined continuum. Your Slaves certainly satisfy key aspects, like only being coupled by message passing. Wikipedia says: "In computer science, the Actor model is a mathematical model of concurrent computation that treats "actors" as the universal primitives of concurrent digital computation: in response to a message that it receives, an actor can make local decisions, create more actors, send more messages, and determine how to respond to the next message received." Your Slave loop can do all that except create more actors in response to a message (but adding dynamic launching would allow this too). -- James Quote Link to comment
Daklu Posted October 12, 2011 Report Share Posted October 12, 2011 I could really use such a a thing and am looking forward to it. Yeah, me too. *sigh* Wikipedia says: "In computer science, the Actor model is a mathematical model of concurrent computation that treats "actors" as the universal primitives of concurrent digital computation: in response to a message that it receives, an actor can make local decisions, create more actors, send more messages, and determine how to respond to the next message received." I'm not very satisfied with that definition. I mean, it's fine as far as it goes, but it's defining the model, not the implementation. It's not at all clear to me how the implementations for an Actor, Active Object, and Agent (to throw another construct into the mix) differ. What attributes does an object require to be considered one of those? For example, in one Java actor framework actors encapsulate the message transport. Messages can be sent to actors using the send() method...A family of sendAndWait() methods is available... The sendAndContinue() method allows the caller to continue its processing... Is that an inherent feature of an actor or is it just an implementation detail? I don't know... (Encapsulating the transport is optional for Slaves. Doing so is safer in that it protects the queue from other components, or you can skip it if you want easier decoupling.) On page the second page the author goes on to say, Active objects give actors an OO facade, allowing you to program in a more traditional OO style. You avoid dealing directly with the actor machinery, sending messages, defining message handlers and sending or waiting for replies. implying Actor Objects and Active Objects are one and the same. Yet further down he adds in the concept of "futures." Again, is this a required feature for Actor and/or Active objects or is it implementation specifc? Stephen introduced Actors in an early thread about Active Objects. Using different terminology suggests he believes there's a difference between the two. I hesitate to consider a Slave Object an Actor until I have a better understanding of Stephen's definition of "Actor." Unfortunately he's been silent on the issue so far. Quote Link to comment
drjdpowell Posted October 12, 2011 Report Share Posted October 12, 2011 It's not at all clear to me how the implementations for an Actor, Active Object, and Agent (to throw another construct into the mix) differ. I think an "Active Object" is anything that is an "object" and has an active internal process. The first active object I ever created was a PID temperature controller. Methods such as "Change Setpoint" or "Set PID parameters" could be called on the PID controller "object" (this was pre LVOOP), while the PID control cycle continued automatically in the background. An "Actor" is a process that interacts with other processes solely by passing messages (it has no shared memory with any other process). My PID controller was not really an Actor. Quote Link to comment
Daklu Posted October 12, 2011 Report Share Posted October 12, 2011 An "Actor" is a process that interacts with other processes solely by passing messages (it has no shared memory with any other process). My PID controller was not really an Actor. How did you get information to your PID controlled if you weren't passing it "messages?" I broadly define a message (in the context of Labview) as any data passed between parallel loops. The way the data gets there seems to me to be irrelevant. Functional globals, global variables, local variables, DVRs, etc. are all (imo) different ways to pass messages to a running loop. Is "no shared memory" a requirement for something to be a "message?" My messages are almost always by value data copies, but there is nothing stopping someone from packing up a by-ref object in LapDog and sending that to a recipient. Does doing that mean that "message" is no longer a message and the receiver is no longer an Actor? Quote Link to comment
drjdpowell Posted October 12, 2011 Report Share Posted October 12, 2011 Functional globals, global variables, local variables, DVRs, etc. are all (imo) different ways to pass messages to a running loop. Is "no shared memory" a requirement for something to be a "message?" I believe an "Actor" can't have any direct sharing of it's internal state information. Using a global to pass a message for the Actor to act on (in a well-defined, controlled, atomic way), is different than being able to directly fiddle with state parameters (as I did with my PID controller). It's a kind of encapsulation, in the same way that an OOP object controls access to its private data. Quote Link to comment
Recommended Posts
Join the conversation
You can post now and register later. If you have an account, sign in now to post with your account.