Jump to content

drjdpowell

Members
  • Posts

    1,969
  • Joined

  • Last visited

  • Days Won

    172

Posts posted by drjdpowell

  1. As I understand it, LVOOP objects are extensions of by-val clusters, not refnums.  There is no create nor destroy action and no meaning to “Not and Objectâ€; there is always a valid object.  If the objects class contains a refnum of something as an element (a Queue, say), then that will be uncreated by default, and you can write a class method that tests that refnum, but that is not the same as “Not an Objectâ€.

  2. Sharing a single reference would solve this particular problem.  It would also add more messaging overhead.  The process that closes the reference would have to notify the other processes and wait for acknowledges before it could safely close the reference.  Otherwise another process could attempt to access the TDMS file with a bad reference.  

     

     

    One of the reasons I chose to use the TDMS file format was its out-of-the box support for concurrent access.  Perhaps properties writes don't work the same way as data writes do (as you hypothesize hooovahh)... ;)

     

    You could solve this with custom Open and Close VIs that maintain a single TDMS reference, and a running count of the number of processes that have called “Openâ€.  Count up for Open and down for Closed, closing the file when the count gets to zero.  One could also use a named single-element queue to hold the file, as named queues have similar “count-the-number-of-opens†properties.

  3. That is only half the truth. For an unitialized object reference you are right but for an object reference that has been created and then destroyed the actual refnum value is not null but still not valid anymore!

    I’m not familiar with by-ref GOOP, but I imagine GOOP objects wrap a reference of some kind (DVR?).  So you are right, one needs to consider stale refnums.  However, there’s a difference between something that might be called “null†versus something that is “invalid".  An “abstract†parent object might indicate a no-op, while a destroyed object might indicate an error condition.  I forget what the OP was requesting.

  4. No.

     

    That's annoying.  I understand the reasoning of not letting the called code know access the subpanel ref... because I want the opposite; I don't want the calling code to access the VI ref.  I have "actors" for which the actual VI that defines their UI should be private to the actor.  I send "Insert yourself in this subpanel messages" and I need a way to get myself out of any previous subpanel I've been insert in.

     

    Thanks,

    -- James

  5. I did discuss the different options with Allen Smith at NI Week and the conclusion was for command pattern across a network, the abstraction (or interface) design was the cleanest or at least easiest to understand.

    Uh, my demo is command pattern over TCP.  I needed to create two new classes and four simple VIs, and if you are willing to use standard Variant/Object messages for data then you only need one class and two VIs.  One of those VIs (configuring the command with any meta info) is optional, so that leaves a single Command.lvclass:Do.vi as the only required.  

     

    Surely this is simpler than any abstraction design, no?

  6. On 8/13/2014 at 7:47 PM, John Lokanis said:

     I concluded that the way I am decoupling my network messages is the only practical solution for a command-pattern based message system.  

     

    Didn't like my "envelope" demo, eh?  Personally I would drop the command pattern for the data message (using standard Variant or Object messages instead) and just use command pattern for actual commands.   Then there is one class per message transfer, with server decoupled from client.

  7. I never thought of that, but I use User Events not Queues.  So while the reference will still be destroyed, I wouldn't have any idea it was destroyed unless I again polled the reference to see that it was still valid.

     

    EDIT:  Maybe I could get away with just the watchdog actor polling the reference, and the other actors being told by the watchdog to shutdown if the reference goes invalid.

    Yes, I encountered the same problem with User Events.   I now use a watchdog Queue separate from communication.  No one ever posts data to this Queue; the watchdog just waits on it to be destroyed.  When it does, it posts a shutdown message on the communication Queue/UserEvent (which is always created/owned by the receiving subactor). The watchdog does have to do polling, not on this watchdog Queue, but rather on the communication reference itself, as the watchdog must also abort itself if the subactor shuts down.

     

    An advantage of a watchdog Queue separate from communication is that the subactor can continue to receive messages from subsubactors that it has created, should it need to as part of its shutdown procedure. 

  8. Correct. I have a watchdog.vi in the top-level VI, with watchpuppy.vi in each actor. The watchdog sends out an event every so often (about 1sec), if the watchpuppy doesn't receive an event in say 1.5 secs, it aborts the vi. I can post an example if you'd like. They are easily removed or disabled later if you decide you do not want them in the final version. Although I usually keep them.

    If your actors are dynamically called, you can use a Queue or other reference created in the top-level.  When the top-level goes idle it destroys the reference and this can be used to trigger an error in the watchdog.  I stopped bothering to write shutdown code for most subactors a while ago and happily hit the top-level abort button if needed.

  9. The problem arises when you wish to send these messages across a network between two separate applications.  In most cases, these applications are not duplicates of each other, but rather serve completely separate purposes.  An example would be a client and a server.  The client needs to message requests to the server and the server needs to push data to the client.  For a process to send a message, it needs to package the inputs in the private data of the message class and then transmit it via the network transport (which can be implemented in multiple different ways and is not material to this discussion).  In order to construct the message, the sender will need a copy of the message class included in their application.  This will mean they will need to also load the class of the message recipient since it is statically linked to the message class within the method that executes the message.  And since that will trigger many other class dependencies to load, the end results is the majority of the classes in the recipient application will need to be included in the sending application.  This is not an optimal solution.

    So, we need to find a way to decouple messages from their recipients but still be able to execute them.

     

    Note: I was on vacation when this conversation was going on, and I haven’t read it in great detail.

     

    I only use Command-Pattern messages in limited cases, favouring a variation on string-variant messages mostly.  But the framework I use can do Command Pattern, and can decouple the command from the “serverâ€.   So I made a test example.  In it, the Client sends a request (non-command-pattern for simplicity) for a data message (DataAA.lvclass).   As part of its reply “addressâ€, it specifies an “envelope message†(CommandAA.lvclass) that it wishes to receive the data message inside of.  The TCP Framework keeps the reply address in flattened form while on the server side, so the server never needs to load class CommandAA.  The “Do.vi†method of CommandAA.lvclass invokes the “Read.vi†static method of DataAA.lvclass.

     

    post-18176-0-69546800-1407254804_thumb.p

     

    The methods one needs to write are Write and Read for the Data message, and Do for the Command (with an optional method to add metadata to the Command if desired).  [aside: AQ proposed a slightly different form, where the Command class is a child of the Data Message Class; he would need an additional method to support building the Command from the Data message.]  

    Command Pattern Uncoupling.zip

    drjdpowell_lib_messenging-1.2.1.29.vip

    drjdpowell_lib_cyclic_table_probes-1.1.0.8.vip

  10. Hi,

     

    If I'm not mistaken, Vision Common Resources provides the ability to run those VIs in a deployed environment, while the IMAQdx drivers provides the ability to develop code using those VIs.

     

     

    Have you installed IMAQdx drivers?

    Hmm, your right, I seem to have a misunderstanding of what this package is for; it does state that it is to allow deployment of the list of VIs without the Vision Runtime license.  Yet I felt sure that I needed this in a past project to access a key VI in development mode without Vision.  Must have just needed it for an EXE.

     

    Thanks for the help.

  11. Hmmm, interesting. So do your low level processes trigger events which your UI is registered for? I'm trying to think how the one loop arrangement differs in anything other than an aesthetic sense? Also, if you need to save data, how does that work? Is the File IO actor event structure based as well?

    Just to be clear, I’m talking about using a Message User Event created by the receiving module, instead of a Message Queue, and passed to other modules so they can send messages.  This is different that the archetypal User Event, which is created in the sending process and passed to other modules so they may choose to register.  The later is usually a separate User Event for each strictly-type message, while the former uses a weakly-typed message like the Lapdog message objects you are using.

     

    Using a Message User Event is interchangeable with using a Message Queue, and avoids the extra work of sending messages from a separate event-structure loop.  I don’t really understand why your “File IO” actor is displaying “Microscope Images”, but if it needs to do UI work like that, then why not use an event structure?

  12. Takes a bit of thinking about as any long running processes (i.e. stuff happening in another diagram) can really scupper things, so now you need to do things like spawn off workers etc.

    Didn’t you already have that problem?  If your “Do Action A” event sends a “UI—>CTRL:Do Action A” message to your second loop, nothing will actually happen till it finishes with “Somebody->CTRL:Do Long Running Action B”.

  13. I routinely use User Events to receive messages in anything that is a UI component, and often in things that aren’t a UI component (so I can give them a ‘debug’ UI if needed).  To me, the topmost loop you have is redundant; it does nothing other than stream the Event Queue into the Message Queue, with no ability to do any actual work (since it doesn’t have access to any state information) and it requires you to write lots of extra build-and-parse message code.  Pointless.

  14. There is no direct way to write a cluster.  Partly this is because there is no direct one-to-one correspondence between LabVIEW and SQLIte types; in particular, a LabVIEW string can be either text of binary (SQLIte Text and Blob types).  Note that it is relatively easy to wire a long set of “Get Column” into a corresponding cluster bundle (or an unbundle into the corresponding “Bind”).  That is part of the reason for making “Get Column” and “Bind” property nodes.

×
×
  • Create New...

Important Information

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