Oli Wachno is a guest blogger. Apart from being a CLA suffering from a serious Actor Framework addiction, he is on the quest for good software development practices.
During NI Week 2016, Fab told me the Delacor DQMH Toolkit was to be expanded by a User Event Library tool, which should make it possible to use existing Actors in the DQMH Framework. The name of the new tool is Delacor Event Scripter. Until then, I had known about the existence of the Delacor DQMH, but apart from some presentations that have been given at the CLAE summits, I did not know really much about it.
This made me curious, and thus I started playing with a Beta version Fab kindly supplied. Digging through the example supplied after installation, I realized some similarities to the Actor Framework, which I really like, being an AF addict.
Both Frameworks feature independent cloneable modules featuring asynchronous and synchronous communication channels. Put down very simply, there are three major differences regarding the architecture.
|Actor Framework||Delacor DQMH|
|Object-oriented?||Yes||No (not visible for user)|
|Communication Data||User defined Objects||User defined Clusters|
These differences show the necessity to have some kind of translator to transition between the two frameworks.
This blog post is not intended to be a shoot-out between the two frameworks. Instead, it is meant to answer the following user story (speaking in Scrum terms):
As an advanced AF developer, what measures are necessary to integrate an existing Actor without major changes into a DQMH-based application?
The Actor Framework features basically two messaging mechanisms, whereas the DQMH features four.
|Actor Framework||Delacor DQMH|
|Synchronous Messaging||User Events|
|See below||Round Trip|
DQMH Broadcast & Round Trip Communication cannot be used with an existing Actor. At least not without major changes to the existing Actor.
There is another use for the Delacor Event Scripter when working with Actor Framework and that is to handle the User events needed to stop a helper loop.
What is a minor change? IMHO extending an existing Actor by creating a child class. Whereas a major change would include creating message siblings to enable further extensions (Senior AF developer required)
Having said a lot and programmed nothing, let’s get started.
The attached LabVIEW project features a basic Actor (“Simple Actor”). The Front panel features two Boolean Controls (Stop, OK) and a string indicator. Four message classes have been defined to be used by this Actor.
|Hide FP Msg||Request|
|Synchronous Messaging||Hide Actor Front Panel|
|Show FP Msg||Show Actor Front Panel|
|OK Btn Pressed||Show Dialog|
|Update Message||Update Text in String indicator on Front Panel|
Four of those are commands to be sent to the Actor and no reply is expected. This makes them Requests in DQMH terminology. We’ll leave OK Btn Pressed aside, since it makes no sense to “DQMH” it.
- Create a child class of Simple Actor. We need to override Pre launch Init.vi, Actor Core.vi and Stop Core. This class has to provide the functionality to translate DQMH events into messages. Let’s call it Simple Actor Child.
- Create a library for the events needed using the Delacor Event Scripter. In addition to the three events / Messages above, we’ll also create a Stop Event to stop the Actor using DQMH type events instead of the Actor API.
- The translation will be done using an event-based Helper Loop running in parallel to the Actor message loop. Thus we need to have a possibility to stop it once the ActorCore parent call has finished executing. This is done by firing a user event in Stop Core.vi. The event is set up in PreLaunch Init.vi
- To provide access to event references for all member VIs of the Actor, create properties for the Helper Loop Stop Event reference.
- Overriding Actor Core is quite simple: after obtaining the DQMH Request events (Obtain Request Events.vi) and registering them along with the Helper Loop Stop event, the Helper Loop itself is started in parallel to the Actors’ message handling loop (AKA Actor Core parent call). Each event registered with the event structure translates the event by sending the appropriate message to the Actor.
Et voilà…..the Actor can be controlled using events.
There is a caveat to this structure: the DQMH type events have to be initially created by the code, which is starting the Actor before (!) starting it. Otherwise the event registration by the Actor will not work properly leaving the Actor running in the background. Nevertheless it can still be halted by sending a Stop Message if the enqueuer is available. On the other hand, if the Events haven’t been obtained properly, trying to generate one will result in runtime errors.
A critical point is obtaining the user events: in fact, there are two major possibilities:
- The application obtains the DQMH type events and makes sure to not start the Actor (to make things easier, talking about a single Actor here) before the events have been set up.
- The Actor obtains the events during PreLaunch Init.vi, the calling code will start using the events only after the Actor has started properly.
Extending your application to using several Actors
When using several Actors, the simple point-to-point communication has to give way to a more complex communication scenario:
- Several Actors are registered to the same set of events
- Several Actors are registered to different sets of events
Please note that the term several can imply multiple Actors of different classes as well as of objects of the same class.
Special care has to be taken here: after obtaining the event refnums, they are stored in a Functional Global Variable (FGV), so it is not possible to simply create multiple sets of events, calling the same VI.
So option 1.) from above is pretty simple to handle: make sure to obtain the events at a central place in the calling code, all Actors will register during their start-up, all Actors will receive events and act upon them in parallel.
Option 2.) is more tricky, since the DQMH Framework does not implement a direct support functionality yet. Nevertheless there are workarounds.
Having discussed with Fab, I see the possibility Delacor is willing to invest some work there to implement the functionality needed. Yet, in order to do so, there has to be a certain level of demand from the user base.
Do you find this useful? If yes, contact Delacor. They will be happy to get feedback!
Fab did the following recording of the code described in this post:
Also, if you want to see how fast Fab can talk, take a look at the lighting talk we gave at CLA Summit in Vienna for this topic: