02-01-2019 10:35 AM - edited 02-01-2019 04:01 PM
If you look at the original Obtain Request Events.vi for a cloneable module, you'll notice that it isn't reentrant. All of the clones share the same events, and also the same Obtain Request Events.vi.
By making your VI reentrant, you effectively tell LabVIEW to keep a separate copy for every instance you place on the block diagram, even if they're next to each other in one main.vi.
One way around this would be to call your Obtain Local Requests Events.vi by reference (one per clone), that would allow you to keep track of the instances. Of course, you would have to wire the VI ref instead of the event ref, so that doesn't help with what you want to do.
I'd just manually create the needed events and wire the event refs...
DSH Pragmatic Software Development Workshops (Fab, Steve, Brian and me)
Release Automation Tools for LabVIEW (CI/CD integration with LabVIEW)
HSE Discord Server (Discuss our free and commercial tools and services)
DQMH® (Developer Experience that makes you smile )
02-01-2019 02:58 PM
I know Fab advocates creating private events using the scripting tools. My guess is that is a. to take advantage of the scripting tools and b. because some DQMH users are not comfortable with events (if you listen to her talk on why she created the DQMH, she mentions that as one of the reasons she created the tools.)
Personally for internal communications, I would just create them myself as what Fabiola terms "local" events and as Dr. Powell points out, it could be any mechanism, not necessarily an event. It strikes me that a notifier would probably be the best choice, but you could use anything.
02-01-2019 03:13 PM
Ah....I didn't quite understand what Alex was saying initially.
But now that you've clarified it more....I realise my code has an issue too!
So thank you Alex for discovering this issue!
02-01-2019 03:55 PM
Yeah it’s not immediately obvious but once it is pointed out it smacks you in the face.
02-04-2019 07:58 AM
drjdpowell, wow, I've been reading a lot of stuff, watched videos and so on. I did the first free online lessons on LV from NI, studied the CML examples, I started getting into the Actor Framework, found DQMH and then started to build my first application now - However I had never read anything about channels! You totally blasted my mind with that simple example. Thanks a lot. I like how simple it is and that you can see where the data comes from. I will definitly read some more stuff about channels soon.
Joerg, thanks again for pointing me out, that the reentrant will have effect for every instance of the VI placed on the BD and not for every instance of a clone - which was my wrong assumption.
02-04-2019 10:49 AM
@AlexElb wrote:
After implementing your approach, I wonder why it is not possible to create a VI which holds the specific local events of a clone, just like the DQMH does it for a normale module. I did try it and it is not working - but I don't know why 🙂 I configured this VI to be Preallocated clone reentrant execution:Obtain Local Requests Events Of course that would be more elegant than wiring the user event references around everytime...
Hi Alex,
This might be a lot more information than you wanted, so apologies if it is too much.
The feedback node is another way of implementing a Functional Global Variable, you might have seen it in your courses like this:Equivalent FGV for Obtain Local Request Events
You can try this on your end by right-clicking on the feedback node and selecting to replace with shift registers or taking an FGV right-click on the shift registers and select to convert to feedback node.
The FGV is called a functional global variable because with functions like a global variable. It relies on the feature of uninitialized shift registers. Uninitialized shift registers keep the value from the last time they ran as long as they stay in memory.
An FGV to work is non-reentrant, the minute you make it reentrant it stops working as a functional global variable.
If you want to learn more, you can google about Functional Global Variables and Action Engines in LabVIEW. You will learn that advanced LabVIEW programmers frown upon the use of FGVs because for the longest time there was a misconception that they protected against race conditions. Action Engines are preferred because they do modify the data in the shift register inside the VI and thus protect against race conditions.
More reading available at:
Action Engines, what are they? https://forums.ni.com/t5/LabVIEW/Community-Nugget-4-08-2007-Action-Engines/m-p/503801
Race Conditions and Functional Global Variables https://labviewjournal.com/2011/08/race-conditions-and-functional-global-variables-in-labview/
DQMH takes advantage of FGVs to pass around the references for the user events without seeing the wires. We went for this approach for clones too because we wanted to have the option of sending the same message exactly at the same time to all the clones.
I hope this helps.
Regards,
Fab
02-04-2019 10:54 AM
@AlexElb wrote:
Wow Fab, the local Events for the Helper Loops should do the trick exactly as I need it. I'll try it out later. If I undestand it correct the local events from clone A couldn't call any event structures of clone B - so there should be no way of influencing. Further more, if I inspect the clones with the Event Inspector I would only see local events from that specific clone. Perfect! Couldn't you please build in a scripted feature for creating local events? 😉
Feel free to suggest this as a new feature in the feature requests thread here and point to this discussion. If there are a lot of Kudos, we will implement it in a future DQMH release.
In the meantime, once you get your cloneable module just the way you like it, you could also create your own DQMH template and then each DQMH cloneable module you create will follow that approach, including the option of having your local events implemented as channel wires!
Regards,
Fab
Please note that we are about to release DQMH 4.2 which will have the option to save an existing DQMH module as a template, so you might want to wait for that 😉
02-04-2019 10:58 AM
@AlexElb wrote:
At least for me as a beginner this wasn't clear. I should learn not to rely to much on a framework - or better: one should really understand the used techniques.
Our apologies for this gotcha. The idea of a framework is that you can start using without understanding every single aspect of the framework. Is like when you learn how to drive, you don't worry about what the engine is doing under the hood and how the breaks work, you just want to get from point A to point B without panicking or having an accident. With time, you can start getting familiar with how the car works... or not... up to you.
You are asking very good questions and you are definitely beyond a DQMH beginner. Things will make more sense now that you are using DQMH and understand why you got into an issue. Joerg has updated his post on helper loops and we will look into ways to prevent others from getting into that problem.
Thanks for bringing this up, everyone in the DQMH community is learning from your questions.
Regards,
Fab
02-04-2019 11:02 AM
@Taggart wrote:
I know Fab advocates creating private events using the scripting tools. My guess is that is a. to take advantage of the scripting tools and b. because some DQMH users are not comfortable with events (if you listen to her talk on why she created the DQMH, she mentions that as one of the reasons she created the tools.)
Personally for internal communications, I would just create them myself as what Fabiola terms "local" events and as Dr. Powell points out, it could be any mechanism, not necessarily an event. It strikes me that a notifier would probably be the best choice, but you could use anything.
Sam,
You are correct on both counts.
I would use local events over other methods because you can register for the stop module event and have a way to exit the helper loop when the module stops. If this is not useful because the code is going to be creating multiple modules and stopping them at different times (we get back to the cloneable leaving the timeout state), then other mechanisms would work well, just make sure you send the message to exit the helper loop when the module exits.
Regards,
Fab
02-04-2019 12:20 PM
@FabiolaDelaCueva wrote:I would use local events over other methods because you can register for the stop module event and have a way to exit the helper loop when the module stops. If this is not useful because the code is going to be creating multiple modules and stopping them at different times (we get back to the cloneable leaving the timeout state), then other mechanisms would work well, just make sure you send the message to exit the helper loop when the module exits.
Regards,
Fab
I forgot about that little fact. In light of that, I do agree that events are the generally the best choice. Then you don't have to worry about having a separate mechanism for stopping the helper loop. Genius!