Jump to content

Fab

Members
  • Posts

    193
  • Joined

  • Last visited

  • Days Won

    15

Posts posted by Fab

  1.  

    TLDR: Delacor has some cool stuff, and I had some cool stuff.

     

    Wow very cool Fab.  

     

     

    Glad you liked it, this has been a Delacor team effort: we had 3 CLAs involved in architectural design decisions, design reviews and implementation. We also have been using this in several projects and gathering feedback from customers and Delacor team members. I don't want to take all the credit.

     

     

     

    I'm starting to wonder if everyone has developed something like this in secret and just not published it.  I didn't really get around to getting permission to post my version publicly, but I talked about it and even named it Glued.

     

    I am sure there are lots of versions of this architecture out there. The community has been using variations of QMH architectures for a long, long, long time. Delacor team members have been using variations of the DQMH for at least 10 years. We decided to publish ours, because it is easier to ask our customers to use something available from the LabVIEW Tools Network that has the "LabVIEW compatible" logo and it is more convenient for us instead of having to reinvent the wheel for every project, or worse, a flatten tire, because we forgot one little detail here and there.

     

     

     

    DQMH and Glued both had scripting for adding new modules, and messages.  Glued didn't have one for removing messages so good on you.  Glued also had the ability to create global messages, which is a message all modules listen and react to.  This makes messaging 1:1, and 1:N, I never came up with a good N:1 scheme but then again I didn't really need it.

     

    IMHO, the scripting tools are the biggest feature in DQMH. I still smile every time I create an event or add a DQMH module. BTW, if there are features missing or people would like to add similar scripting tools to their existing architectures, please talk to us, we might be able to make this happen for you.

    We didn't think about adding global messages, we will give it some thought, although I believe this would go against our goal of keeping DQMH modules as stand alone modules to reduce coupling between modules.

     

     

     

    When doing a Do Something Wait for Reply, you use a user event to send the message and a notifier to wait on the reply.  I found this to be a bit problematic when doing a shutdown.  If I have a sequencer running that is requesting analog data and waiting on the reply, but at some point the user closes the software.  That close is going to be a global event telling the whole application to shutdown.  If my analog actor loop shuts down, but my sequencer doesn't get the request to shutdown, before requesting a read, then all actors will shutdown except the sequence, which will be waiting for the reply from the analog.

     

    We realized we were not covering 100% of the use cases for "Request and Wait for Reply" events. We went for the template that would answer 80% of the cases with a very short timeout. In the future we will have a blog post with some of the alternatives we have for this type of event. We even hesitated to include this type of event, because of the potential for deadlock. This type of event is very rare in our current applications. Some of the comments/feedback we got from the CLA summit was that we should have used a SEQ instead of a notifier, because for large data sets the notifier will result in a data copy and the Queue would not. We decided that the notifier was more readable and again it covered 80% of the usage. If the reply requires large datasets, the argument of the notifier reply could be wrapped in a DVR.

     

     

     

    For the messaging there are essentially three functions you need to have.  Sending the request, convert the request variant to the request type def, and send the reply.  There were also two typedefs, one for the request data one for the reply.

     

    This is not always the case, when using the Tools>Delacor> Create New DQMH Event... menu, you will see that there is an option of creating a "Round Trip (Request + Broadcast)". This option creates the Request Event and the Broadcast Event both sharing the same typedef for their argument.

     

     

    In Glued this was all contained in one polymorphic VI.  The purpose of this was to quickly find where in the code a request was being sent, or a reply was being sent by right clicking on the polymorphic instance and selecting Find All Instances.  Then I could find all places I was requesting data, where I was acting on that, and where I was sending that data back.  The Request, or the Request and wait functions were in the same VI, and there was a boolean input for Wait For Reply.

     

     

    In a DQMH module, the Requests can be found as part of the Public API virtual folder in the DQMH Module.lvlib. When finding where these functions are called, we can find what other code is making requests of the module.

    The Broadcasts can be found as part of the Broadcasts Private folder in the DQMH Module.lvlib. These VIs should only be called by functions within the DQMH Module.lvlib.

    In our case, we found that keeping these functions separated in this fashion resulted in the best Developer Experience. Especially when dealing with different levels of proficiency.  Some of the teams we work with, the architect would create the DQMH and a CLD or CLAD would just call the Public API VIs, they only care about using the Requests. In fact, some of our customers choose to lock the DQMH Module library so the junior developers have access only to the Public API VIs.

     

     

     

    In Glued modules has the ability to send a message to itself using the same polymorphic request VI mentioned before.

     

    In a DQMH module the Queue is private to each module and it is used to send messages within the module itself. The Events are used for any external communication handling.

     

     

    There existed a manual screen module.  This module was a place for all other modules that had manual panels to be seen.  It basically was a listbox of modules, and a subpanel to insert into it.  This is where sending messages to itself would come in handy because the buttons on the FP of the module invoked the same code as that message would coming from any other module.  In this manual screen actors could be undocked, which would just make floating windows of each.

     

     

    This is an interesting idea. It is really hard to draw the line on what is needed for every single application and what is needed only for some applications. We tried to keep the DQMH Project Template to the bare minimum we found ourselves and our customers using in all of their projects.

     

     

     

    I prefer state machines that have the ability to have multiple cases queued up.  Either a multi-line string like JKI, or an array of string, or even an array of enums if you want.  I'm sure you are familiar with the pros and cons.  Glued used an array of string, but I've been using a modified JKI lately and think I prefer that.

     

    The DQMH Enqueue Message is a polymorphic VI that has the option of enqueing a single message or an array of messages.

    Also, the DQMH is a Queued Message Handler, not a state machine. Implementing a State Machine with a module that is asynchronous and can receive messages from a lot of different points in the application leads to getting messages in between the state machine states. If a true state machine is needed where none of its states can be interrupted, then we would code that case in the Message Handling Loop to call an actual State Machine. See my blog post on the NI QMH the section on Using a QMH as a State Machine: http://www.walkingthewires.com/2015/05/08/ni-qmh-template/

     

     

    There existed a config module…

     

    This is another example of us deciding to keep things to a minimum. We do have a DQMH Configuration Editor module that we use internally and gets modified to fit the needs of every application. So far this module has changed so much depending on the requirements of each customer, that we decided we couldn't include a version generic enough in the DQMH Project Template. Depending on how many people end up using DQMH, we might make modules like this one available in the future. Or maybe other members of the community decide to share their DQMH modules with the rest of the community.

     

     

    For debug I had an actor probe which registers for all events, request, reply, and global events, and has a central place to see all the events, and their data in the order they are generated.  Here is a post talking a bit about it and showing it.

     

     

    For debugging we went with the option of including a Test DQMH Module API.vi with every DQMH Module. It includes a status window that can be used to monitor what is going on with that particular DQMH module.  This tester can be used to test the DQMH module or as a sniffer when the main application is running to eavesdrop on the communication for that DQMH module.

     

     

     

    And lastly Glued had no cloning of actors.  In my design I haven't really had a need for it.

     

    We kept the Singleton and Cloneable modules separate, because we agree with you that most of the time cloning actors is not needed and we didn't want to burden the 90% of developers with the clone management needed just a few times.

     

     

     

    So if I needed a CAN actor for doing CAN communication, I would make that actor and call it in parallel with all the other actors.  They all started at the same time, and all stopped at the same time.  No actor ever shutdown, without sending a message to shutdown the other actors.

     

    We wanted to make it possible to restart a module without having to restart the entire application.

     

     

     

    This again might be because I focused on request reply more and sending a request to an actor that doesn't exist, had issues.

     

    The DQMH Module Public API VIs return an error if the module is not running. This can be tested via the Test DQMH Module API.vi, if any of the buttons are pressed before the Start Module is pressed, the error will be shown that the module is not running and the tester will stop.

     

     

     

    Actors not being clones makes debug a lot easier.  At any point in the software I could go to the main VI, hold CTRL and double click the actor…

     

    The Test DQMH Module API.vi includes a "Show Block Diagram for Troubleshooting" button, this works both in the Singleton DQMH module and the Cloneable module. In the cloneable module, the developer can choose to send the request to All clones or to an individual clone at a time. This is one of my favorite features. One that I thought at the beginning it was not needed, because my workaround of holding the CTRL and double clicking kind of worked, but if you have a chance, give this button a try… this is another feature that makes me smile every time I use it and prove that having a team to review your decisions leads (hopefully) to a better developer experience for all.

     

     

    Wow wall of text so sorry, can't wait to meet up with you next week and we can talk more if you are interested.  Thanks again.

     

     

    Even longer now with all my replies ;) I appreciate you taking the time to take a look at the DQMH toolkit. I am looking forward to meeting up with you next week and talking more about this.

     

    Happy wiring,

    Fab

    • Like 1
  2. Maybe the customer VI contains multiple event structures and becomes somehow deadlocked?

     

    See the thing is that if I turn highlight execution both the Event handler loop on top and the Message Handler loop on the bottom finish executing, the queues get destroyed, the events unregistered and destroyed, the whole code executes, gets to the very last node (in the extreme case the VI Server Abort VI method I added), seems to execute and then the running arrow never turns off. 

     

    I am just pushing this to the list of "we will never know". It is definitely not the code, because just changing the launching with start asynchronous call to using the old Run VI method just works. The VI stops right after it executes its last node. And I was able to remove the abort. 

     

    I will the customer if I can share the VI. I was just curious if anyone else had seen that weird behavior. 

  3. A wild guess but do you call any VIs in there that call into a DLL?

     

    Nope, this is a VI that one of my customers has been using in a project that calls other similar VIs asynchronously. This is the only VI to have that strange behavior.

     

    I tried desperate measures like calling the Abort VI method at the end of the code, and it would still continue to run after executing that last node. The only way to stop it was to press the abort control on the tools bar.  

     

    Once we replaced the call and forget code with the Run VI method, it did stop and I was able to remove the abort method.

  4. I started saying Wife/Spouse in my message and then got lazy and only said wife.  I hope it is understood that I meant it for spouses not just wives.  If I remember I'll start a new thread next year to see if there is interest in a spouse ribbon.

     

     

    Just pulling your leg ;)

  5. Had a great time with you guys.  Her comment about how the ribbon collection started did get me thinking.  Would it be a good idea to have a "Wife/Spouse" ribbons made?  On the one hand I don't like the idea of having ribbons made for every category, but I think the wives catch on to the fact that the length of your ribbons is something to show off.  Wives probably feel left out with no ribbons of their own.  I was the one that had the LAVA ribbons made this year so I feel like I could probably get something together and make some for the wives to have.  I just feel like they should feel more welcomed, not isolated.  It did seem like there were a good number of wives there this year.

     

    EDIT:  BTW I almost brought my wife but something came up.  There is a good chance she'll be coming with me next year.

     

    Hooovahh, 

     

    If you are going to do these ribbons have them say spouses, you don't want to leave some of your friends' spouses out ;) 

     

    You can also have some fun with the ribbon and be more like "NI Week widow/er" LOL!

    Loved meeting her! and definitely, she has to be here next year! 

     

     

  6. they were, they were!! 

     

    Delacor will add a little something to go with the NI myRIO the LabVIEW Tools Network team is giving away.

     

     

    If the LabVIEW Tools Network team is OK with this, Delacor would like to add an extra little something to go with the NI myRIO they are giving away. I would love to give more details, but you will have to wait until NI Week to find out what I am talking about ;)

     

    Can't wait!

     

    Fab

    • Like 1
  7. If the LabVIEW Tools Network team is OK with this, Delacor would like to add an extra little something to go with the NI myRIO they are giving away. I would love to give more details, but you will have to wait until NI Week to find out what I am talking about ;)

     

    Can't wait!

     

    Fab

     

    Looks like we're going to have some AWESOME door prizes this year.  I've just received word that the LabVIEW Tools Network team will be donating a brand new NI myRIO!  If you are unfamiliar with myRIO, specs and details can be found at ni.com/myrio

     

    myRIO.jpg

     

    Can't wait to see everyone in a few weeks!

    • Like 1
  8. I was expecting to see the update for LAVA BBQ 2014, any updates yet?



    I was expecting to see the update for LAVA BBQ 2014, any updates yet?

     

    by the way I got here by the traditional lavag.org/bbq link

  9. I know there has not been any activity on this thread for a long time, but thought I'd give my 2 cents on our recent experience. Our (FairlyFunctional and my) medium size Actor Framework (~70 classes total, including messages) project started getting bogged down and updates to class data started incrementally getting longer, as well as moving things around in classes and libraries. In reading through this forum we first moved all of our classes out of libraries, which didn't seem to help, and then recalled Daklu saying something in this forum about clearing the mutation history, which I had to look up. 

     

    It seems to me that many of the heartaches in this thread were due to mutation history. To delete the mutation history (see this Preserving LabVIEW Class Data whitepaper) you can either edit out the text of the .lvclass file, or rename the class and then name it back. FairlyFunctional added an add right-click option to delete class mutation history idea to the Exchange. We had a fairly large array of clusters that was initialized in the private class data, so every time we made a change to the private class data it was adding another copy of that array to the mutation history (at least that is my guess). If that is the case, another (and better) fix would be for LabVIEW to only update what changes in the class data for the mutation history instead of making a new copy of everything into the geneology.

     

    My thought is that previously (pre LV2013?) moving a class out of a library would delete its mutation history, which is why that worked for many people. This idea to warn the user that the mutation history was being destroyed may have prompted the idea to not delete the history when moving it out of libraries?

     

    -Sleepy Engineer

     

    Thanks for adding this, what you are saying regarding mutation history makes sense. I tend not to put default data in clusters in the private data, just as I don't put type def cluster constants that do not have default values in a block diagram (see VI Analyzer test for this one). 

    Instead what I do is to add a method to my class that is called "Default.vi", and then generate the clusters there and return the default object that way. This way I don't have to worry about the mutation history and I don't have to worry about the organization of my private class changing. I can see now by your post why this practice inadvertently made things better for  me.

     

    Thanks,

    Fab

    • Like 1
  10. This is an old thread, so I understand if nobody answers ;) 

     

    I need to be able to have check boxes in multiple columns, in my case 12 columns. I tried the MCL control that PJM found and I was able to get the symbols to show in 8 columns, more than that does not work.  Any ideas how to get this done?

     

    I could always go back to the hack of old days of using the Symbol font and show the check box this way, but I want to see if there is better way.

     

    Thanks,

    Fab

×
×
  • Create New...

Important Information

By using this site, you agree to our Terms of Use.