Jump to content

drjdpowell

Members
  • Posts

    1,969
  • Joined

  • Last visited

  • Days Won

    172

Posts posted by drjdpowell

  1. 53 minutes ago, ShaunR said:

    Because of aggregation.

    The goal is to average a number of values all being acquired asynchronously. There needs to be a way to snapshot the multiple values at an instance in time. If you use messaging then by the time you messaged each subsystem and got a response the values are not at the same instance in time. If you use events, then the event structure only operates sequentially so you have a similar problem. The AE makes this trivial. Other solution require all sorts of hoops.

    My first thought is “consider doing views of past history for real and use SQLite”, as I’m sure you agree.  My second thought is “that sounds trivial to do with the Register-Notify messaging pattern”.  Why in the world would you message subsystems to get data in response?   This is what I mean by focussing on a few complimentary techniques and learning them very well.  SQLite is very complimentary, but if one mixes limited-capability messaging with some similarly simplistic “tag” implementation then you end up with an overly complex result that is weaker than just picking one technique and really understanding it.

  2. 5 minutes ago, ShaunR said:

    There are "Tags" too which are global. IIRC I suppose they could be leveraged for this but I've never really looked at them

    Oh yeah, there are quite a few “tag” libraries on NI.com.  Using one of those might be better than rolling your own.  I don’t use them because they wouldn’t give me anything I can’t do with messages, and they increase the amount of stuff I need to know (gotta know messaging, tags, and how tags interact with message timing).  

  3. 1 hour ago, Neil Pate said:

    The way the architecture is designed there will only ever be a single writer of each data item, but these scattered across multiple actors (different hardware components and software interfaces).

    The data in my application "runs slowly". Most new data comes in around about once per second so I do not really need to worry about extracting every last clock tick of performance out of my PC. Computers are crazy fast anyway these days, the bottleneck is certainly my skills.

    Single writer is good.  Why “global” then?   I generally have data flowing around by messages and locally stored by anyone who needs to store it.

    The other issue is constantly polling a DVR for changes, versus receiving notification messages only when things change, but for “slow” apps that doesn’t matter much (but it affects your ability to reuse your solution in “fast” apps).  

  4. 11 minutes ago, Neil Pate said:

    I am experimenting with a DVR based variant repository for my "global" data storage needs. Each actor in my system (everything is an actor) is able to reference this DVR and thus get at *any* data. Perhaps a bit dangerous, but as I said, this is an experiment. 

    What are you “global storage needs”?  How many writers are there of each data item?  

  5. On September 7, 2016 at 11:56 AM, ShaunR said:

    Actors and AEs aren't equivalent.

    Hey, let’s infinite-loop the conversation!  :)

    On September 7, 2016 at 0:20 PM, drjdpowell said:

    Actors, AEs and by-ref classes can all be used as wrappers around shared resources that serialize parallel access to them and protect critical sections of code.  They aren’t equivalent, but they have considerable overlap.   

    I should clarify.  Message-handling loops, Action Engines, and by-ref classes can all be used to organize a complex application into subcomponents and control interactions between the subcomponents.  The means of interacting may be different, async messages versus sync subVI/method calls, but the purpose of these structures is the same.  Because they are different, but used for the same underlying purpose, I would recommend that a developer focus on one.  It reduces complexity if you standardize, and allows you to really get competent at the techniques you have chosen.  If asked, I would personally recommend using messages over any by-ref techniques, and also not using globally-accessibly things like standard AEs, but it is more important that one pick a technique and get good at it.

  6. 2 hours ago, ShaunR said:

    Generalising to nebulous "actors" (which is just a hand-wave and means "insert your meaning here")

    Well, even at its most nebulous, “actors” interact by passing asynchronous messages, and are actively handling those messages.  “Message-handling loops”, basically.  That is significantly different than AE/DVRs, which passively wait to be synchronously called.  More specifically, “actors” should follow the Actor Model, and I should probably have used the more generic "Message-Handling Loop” as a thing to compare with Action Engines.

  7. 21 minutes ago, ShaunR said:

    Standard terms; not peculiar to LabVIEW.

    Link title is "Passing Arguments by Value and by Reference"

    Ah, so you’re meaning pass by reference, as applied to arguments to function calls (terminals in LabVIEW), and some of the things we are talking about are not passed as arguments.  

    I’m meaning “act on by reference”, or “having a reference to something”, meaning I have the means of acting on something that others also can act on.  I don’t care if the reference is passed as an argument or is statically compiled in (like a Global or a subVI call).

     

  8. Let’s try a different tack.

    There is an important difference between situations where one loop can affect another loop operating in parallel (a side effect), and where it cannot.  Globals, Locals, DVRs, Queues, Notifiers, FGVs, Action Engines, or the new "Channels” are all means where one can “reach in” and affect a loop while it is running.  Data on a wire is not. 

    An interesting talk related to this by AQ: Why Dataflow Works: The Potato and Candy Explanation

  9. 2 minutes ago, ShaunR said:

    Any class is a number of [atomic] methods acting on a protected storage container and this is what AEs attempt to do without the language support. 

    Ah, you mean the encapsulated data.   Your right, but you talked about a “shared resource” that might need “mutexes”, which is about accessing things from processes running in parallel.  By-value objects are not sharable and have no use for mutexes.  

  10. 23 hours ago, Neil Pate said:

    I am a bit torn on this one... I want to use ByVal as I think it makes debugging and scope easier to understand, but that means the class has to live somewhere, ok fine I have a "main controller" actor/process, so it can go there. However any time I want to interact with it I then have to create messages that the main controller can process. And then there is the issue of getting data out of it and usable by the rest of the application.

    I suppose for your example I would have the ForceCalibration object as a ByVal class in the process that is actually going to use it.

    I’m surprised there’s not more love for Action Engines.  I’ve never really used them, but instead have focused on making “actors/processes” easy to make and communicate with, and on having by-value classes live wherever it’s natural for them to live.   If they naturally need to live in an independent process, then it is easier for me to make it an actor than an Action Engine.  I’m not really negative on Action Engines, but they don’t give me capability that I can’t get with an actor, and as hooovahh said, I can do active, periodic stuff with an actor.

    I only very rarely use actual by-ref objects (usually using a DVR).  “ForceCalibration” would most likely by a by-value object for me, too.

    As a general programming principle, I believe one should standardize on a set of complimentary techniques (and get very good at those techniques), rather than mix multiple alternate ways of doing similar things.  Action Engines, “actors”, and by-ref objects are different ways of doing the same thing, so one should pick the one you think is best and run with it.

  11. Forgot to add that a goal is to make adding functionality to controls easy, ideally a single subVI that can be called multiple times with different graph references.  Customization is via references to simple subVIs used to generate the text.  Below is the code of the first example.

    Code for Twin Cursor Example.png

     

  12. 8 hours ago, JKSH said:

    This creates an undesirable coupling between the caller and the JSON library.

    JSON is an interchange format.  Reducing coupling between components is what it’s meant for, so it’s sad that we worry about unwanted dependancies.  The “variants that contain only strings and numerics as basic datatypes” that you are asking for are a much less flexible substitute to JSON text.  I would not be happy if I had to do lots of manual type conversion on everything that isn’t a simple string; that’s an undesirable dependency to me.

    Really, the best solution would be for NI to realize the value of a JSON-like datatype and build that into LabVIEW, replacing this library entirely with a much faster solution that can be widely used in interfaces between modules without worrying about unwanted dependancies.

    As an alternative, have you considered using the JSON text itself as the thing to pass on, rather than a variant?  Try this: replace your “data” Variant with a string labeled “<JSON>data”.  That tag indicates to the library that you want your “data” subitem as JSON text.  Pass that string across your subVI boundary.  If you are just using strings and numerics, then your Caller can use the inbuilt JSON primitives to convert very quickly into data, so it isn’t dependent on this JSON library.

    Personally, I solved this issue by deciding to make this JSON Library a standard component always used in all cases where complex structured data is passed between modules.  But then I did write the library.

  13. The attached VIPM contains an extension of Messenger Library that is intended to add extended functionality to controls/indicators, via a background process that is launched and which registers for the events of the control (the background process is a Messenger-Library “actor”).  This is meant to be an alternative to XControls.   Included are two “Augments”, both with examples.  See <examples>/drjdpowell/UI Augments/Examples/EXAMPLE Twin Cursor Graph Augment.  This takes any graph with two cursors and draws a line between the two and displays summary info of the data between the two cursors:

    Example Augment, Twin Cursor.png

    There is also a cross-section plotting for a 2D intensity chart:

    Augment, Crossection plot.png

     

    This package is in LabVIEW 2015, and requires Messenger Library (latest, in the LAVA-CR) and JSON LabVIEW and Shortcut menu from Cluster (both in the LAVA-CR).

    drjdpowell_messenger_ui_augments-1.0.0.8.vip

    • Like 2
  14. 2 hours ago, kull3rk3ks said:

     

    
    { 
    	"serverConfig": {  
    		"read": {   
    			"address": "164.3.157.40",
    			   "port": 5010,
    			   "bytesToRead": 130,
    			   "connectionMode": "Server",
    			   "connectionTimeout": 5000,
    			   "readTimeout": 2000
    		}
    	}
    }

    throws error 1 (Parser error)

    I quickly tried this string and I didn’t get any error.

  15. 15 hours ago, smithd said:

    My other question is, if you want these N actions to be taken synchronously without interruption, why not subVIs?

    I tend to use subVIs one layer lower down from the loop actions, as explained in this post.  One can have subVIs that represent actions of the loop itself (as the AF does, for example), but I usually find that to have (minor) disadvantages.

    • Like 1
  16. 21 hours ago, smithd said:

    My problem isn't with the enqueue semantics but with the idea that an external person should ever have to queue up multiple actions. I'd prefer separating the external interface (which in this case yes would be the macros) from the internal (which might take multiple actions based on the request/event which occurred.

    I agree, but the JKI “state queue” is not an external interface.  It cannot be accessed from outside the loop (it’s by-value, not by-ref).   Requests from external sources enter via the Event structure, which is only consulted when the “state queue” is empty.  “Macros” are multiple actions based on a single request/event. 

    Added later: my talk at the 2016 eCLA Summit was on how to handle actions like a subVI, though I forgot to mention that the JKI “state queue” can be used that way.

     

×
×
  • Create New...

Important Information

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