07-24-2019 10:03 AM
Hi All!
I've got a quick question about the way DQMH handles broadcasts.
Lets say I have 3 modules total (A, B, and C). All three modules are launched externally by some "Launcher". I'm confident that I can get Module A to subscribe to Module B's broadcasts but let's say I want Modules A and B to subscribe to module C's broadcasts. How would I do this? Looking at the Module/Event Sync vis, I feel like if Module A reports that it has registered for Module C's broadcasts, but Module B is taking it's sweet time to register for the same broadcasts also from Module C, Module B could miss out on some of the broadcasts sent out from Module C. Are these DQMH sync VIs smart enough to wait for ALL of the subscribers to report that they have successfully registered for the broadcasts from Module C? I've not used rendezvous VIs much in my own development so maybe I'm missing something fundamental about how they work.
Thank you in advance for your help!!
-John
07-24-2019 07:09 PM - edited 07-24-2019 07:11 PM
Hi John,
Instead of having a separate launcher launching A, B, and C. I would do this:
Launcher launches A
A launches B and C, and then A registers for broadcasts straight after they are launched and synced.
B launches C, and then registers for broadcasts straight after C is launched and synced.
If C is a singleton, then it doesn't matter who launched it. If C is cloneable, then you will need some smart code to determine if the right number of clones have been launched, otherwise B will happily launch further instances of C.
The benefits of this approach:
1) Testing - Now that you have A launching B and C, of which it is dependent on, it is easier to test through the API Tester. When you run module A through the API tester, it will automatically launch B and C and then you can proceed to run your tests. If A did not launch B and C, then you would be having to still launch via the launcher and then opening up the Tester - doable, but fiddly. Further, if you wanted to test B in isolation via the API Tester, then because it launches C by default, you can easily test B without having to separately launch C.
2) Synchronisation happens at the right time
In past projects I did not follow the above, and so found myself having a delay in MHL Initialize case before generating an internal event to register for any broadcasts, which worked, but isn't nice code.
07-25-2019 03:29 AM
Hey John,
if you haven't read it yet, this thread might be of interest to you and your question:
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 )
07-25-2019 10:31 AM
Hi Ozfarmboy and Joerg,
Thank you for your insights here. The general idea I'm picking up from both of your comments is that the way in which you start your modules influences how broadcasts can be registered for. The sense I am getting is that a caller will usually have no problem registering for broadcasts of one of it's nested modules (callee), the issue appears when two "sibling" modules are trying to register for their complimentary "sibling's" broadcasts. I'm thinking that this is where you can get a deadlock situation, they are both waiting for the other to verify the broadcast refnums which may never happen.
While not required, it seems like broadcasts are kind of designed to go up the chain in that you really shouldn't start broadcasting info until everyone is ready to hear it. Chances are good that I'm missing something fundamental about DQMH. I understand how the tree structure works in AF but the fact that DQMH doesn't require that has me all twisted up especially in the context of Broadcasts and how they are actually set up by the DQMH modules themselves.
The broadcast creation/registration process really only has 2 concrete participants. The module creating the broadcasts and the module with plans to register them. I guess you could hijack this process and have your registering module send messages out to other relevant modules saying "hey, new broadcasts references, get em while they're hot!" and wait until those are registered before telling the module creating the broadcasts that everything is registered, but that feels like it goes against how DQMH was set up.
I think I came into the Broadcast idea thinking that any module could hear any broadcast whenever wherever (similar to a radio broadcast). The downside to this idea is that alike a radio broadcast, you would probably never hear the "first brodcast message" unless you tuned in right as the first broadcast started. DQMH makes the guarantee that at least ONE module will hear every broadcast message, but I feel like it can't guarantee that for more than one.
The only way I can think to do this with current DQMH vis is to dynamically modify the rendezvous size based on the number of of modules waiting for valid broadcast events. Once the events are valid, they will be registered for and the broadcasting module will have to wait until every subscribing module has registered before continuing.
Just thinking out loud now.
07-25-2019 12:42 PM - edited 07-25-2019 12:43 PM
The more I think about it, the broadcast creation/registration doesn't really have 2 CONCRETE participants. It really just has 2 participants, one of which is guaranteed to be the broadcasting module, but the person who "confirms" the registration doesn't have to be a child, it could be a child of a child (etc.)
A creates it's broadcasts, waits for confirmation that they have been registered for while also launching B.
B registers for the broadcasts, does NOT send registration confirmation, starts executing, and launches C
C registers for the broadcasts, DOES send registration confirmation back to A, and starts executing.
A little message handshaking between B and C might be needed to make absolutely sure both are registered, but it really doesn't matter who confirms registration as long as everyone else is ready to start listening.
Any flaws in my thinking here?
07-25-2019 03:00 PM
Just a suggestion, but an alternative to waiting for "everyone" to register before broadcasting is to re-broadcast after each new registrant. This does mean some repeat messages, but if these aren't a problem then it means that new registrations can happen at any time.
07-25-2019 03:31 PM
The way I see it, the broadcast registration / synchronisation wasn't created with the registrants in mind. It was designed to stall the starting module until it can rest assured that its messages will be received by someone. Fabiola will be able to shed more light on this.
The way we use DQMH, there is really no need for more than one module to register for broadcasts. No module will do anything important automatically when starting up. Each of our modules implements a dedicated "Configure" case that needs to be called if and when the whole application is ready for whatever is happening there.
As we created a small library of VIs which logs to file and to a separate user event that's created before the modules are even loaded, we don't even have to rely on the DQMH broadcasts for error catching during starting up. In fact, for the top level modules of our Windows applications, the "main VI" doesn't register for their broadcasts at all.
Anything else can then happen in an ordered way, much like James describes it.
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 )
07-25-2019 05:42 PM
Hi John,
The thing that took me a little while to realise with DQMH, is that it is not exactly a free-for-all - any module messages any module type of framework. This would become a nightmare to debug. You still need to have a bit of an architecture and structure, where there are higher level modules that depend on lower level modules. In other words it is inadvisable to have two modules both registering for each other's broadcasts. There is simply no need. One broadcasts, and the other requests.
Consider for a moment the NI VISA driver API - this driver is not dependent on anything else - ie it does not need another module for it to run. Let's say you were to write a simple application that uses the VISA driver. The application needs the VISA driver - it is dependent on it. The application calls functions from the VISA driver (ie it sends requests to the VISA driver to get it to act or request information). The VISA driver does not require any information from the application however.
I like to think about DQMH in the same way. I have an Application module, and a Device Module. The Device module needs to work by itself. Therefore it CAN'T be registering for another module's broadcasts, because it then it can't work on its own. The Application on the other hand needs the Device module to run, so because the Device module is a dependency, the application can register for the Device's broadcasts. Further, there is no need for both modules to broadcast to each other. Instead the Application simply calls the Device's requests and request and wait for replies, and the Device broadcasts.
I hope I am making sense! This is a very simple example of course, and it can get trickier with more complex applications.
To quote Sam Taggart from here https://delacor.com/simple-dqmh-dos-and-donts/ - well worth a read by the way.
" Down the tree = parent sends request events to child
07-26-2019 02:22 AM
@ChrisFarmerWIS wrote:
...
Yes to everything.
On top of that, I think it's important to separate between the default broadcasts (like Status and Error), and application-specific broadcasts.
Imagine a Device module that acquires data. In most of our applications, we would have several modules (like Logger, UI, SomeFurtherProcessing...) that receive that acquired data via broadcast from the Device module. Those modules, however, are not interested in the error broadcast or the status broadcast from the Device module.
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 )
07-26-2019 05:59 AM - edited 07-26-2019 06:01 AM
@ChrisFarmerWIS wrote:
You still need to have a bit of an architecture and structure, where there are higher level modules that depend on lower level modules.
[...]
To quote Sam Taggart from here https://delacor.com/simple-dqmh-dos-and-donts/ - well worth a read by the way.
" Down the tree = parent sends request events to child
- Up the tree = parent registers for child’s broadcast events"
I understand that. Until now I thought, that design has the benefit of the possibility to test upper parts of the tree on their own, withoud the need to start a bunch of modules just to test the very lower end of a tree / branch. But lets have a look at the case where one siblings needs the data of another as Johnny proposed.
Just to be clear: There won't be direct communication between siblings. Communication should always go either up or down and never horizontally.
So either Sibling B can only be tested within the Operator Test, or we must "move" Sibling B Functionality up, between Sibling A and the Operator.
In both cases no broadcast events will be missed by any Module.
Are my thoughts right?