Jump to content

Aristos Queue

Members
  • Posts

    3,183
  • Joined

  • Last visited

  • Days Won

    204

Posts posted by Aristos Queue

  1. All the internal benchmarks that I've done show a substantial speed improvement for all queue operations from 7.1 to 8.5. I didn't redo benchmarks for 8.6. There is a new queue primitive in 8.6, but to the best of my memory none of the functionality of the existing primitives changed.

    QUOTE (Gary Rubin @ May 1 2009, 08:45 AM)

    On Windows (and I believe all the desktop platforms) the timing cannot be any more exact than milliseconds. There just isn't a more precise timer available. The fact that the time reported is zero means that it is taking less than 1 millisecond to execute, so the sum of all iterations is still zero. That's why it makes sense to benchmark in aggregate but not individual operations. If you want a more precise timing, you need LV Real Time running on a real-time target.

    QUOTE (PJM_labview @ May 1 2009, 11:43 AM)

    I have had a lot of questions about the profiler since
    LV
    8.0. I believe something was changed somewhere so that it does no longer behave quite the same way that in previous
    LV
    version

    I don't believe it had any significant changes since at least LV 6.1 other than displaying VIs from multiple app instances, added in LV 8.0. I could be wrong -- it isn't an area that I pay close attention to feature-wise.

    QUOTE (jzoller @ May 1 2009, 02:18 PM)

    (Edit: thinking more on the above, unless the queue has a lock-on-read, it seems unlikely. Sorry.)

    I'm not sure if you're asking about this, but, yes, there is a mutex that must be acquired by the thread when it reads the queue.

  2. QUOTE (Diego Reyes @ May 1 2009, 05:52 PM)
    Create references to all my controls, bundle them into a cluster and pass it into my state machine using a shift register. Then when the application ends, close the references.
    I'm not commenting on the pros/cons of the two architectures. I just want to point out that if you choose the 2nd idea, you don't have to worry about closing control references. Control references all close when you close the VI that owns those controls. You have to be careful to close any App references that you open and close any VI references that you open, but not control references (the same applies, if you use scripting, for all the block diagram references). Having an App reference open will keep LV from quitting. Having a VI reference open will keep the VI from leaving memory. But having a control reference open won't keep anything in memory. Those go stale as soon as the VI unloads.

  3. QUOTE (Black Pearl @ Apr 29 2009, 06:48 AM)

    Got it working. It goes actually very nice as I can execute each plugin-exe on it's own as well as launching it as plugin.

    But I observed some strange behaviour of the plug-in's FP. Although set to 'top-level' (open front panel when called), it did not show up using the run method. I had to use the FP.Open property in the plugin vi.

    "Run when called" literally means "when called as a subVI." If it is run as a top level VI (i.e., when you use the Run method of a VI), it doesn't open the FP. If you run it using the Call By Reference node, that calls as if it is a subVI, but it does not sound like you want the rest of the behavior that comes with that. So, yes, the right way for a top-level VI is to use the FP.Open method.

  4. The property node does exist, but it doesn't work in the runtime engine.

    You can get the version in a very strange way... take an instance of the class and flatten it to a string. Then read this post for instructions on how to get the version number out of the flattened string.

    That's the only mechanism I can propose that will work in the runtime engine.

    QUOTE (Aristos Queue @ Apr 28 2009, 01:37 PM)

    That's the only mechanism I can propose that will work in the runtime engine.
    I thought of another option... you could read the XML file directly. The class version number is stored in plain text in the .lvclass file.
  5. QUOTE (normandinf @ Apr 28 2009, 12:13 PM)

    I partially agree. A project is only available in the development environment. But a lvclass (lvlib/llb/...) can be used with a plugin architecture. That's a resource I'd like to tap in when I'm in the runtime environment. If you can dynamically load a class, why not access it's constituents (datatype, tags, icon, etc.) in read-only? I'd argue the editor line is not where it should be. There are tons of VI properties that are read-only in run-time while being read-write in the development.
    I'm surprised you couldn't hear my cry of frustration back in 2006 when I realized that someone had coupled the library interface to the project interface... unfortunately, we're tied to it now and there's no way to change it without breaking all user VIs to create a separtate refnum hierarchy independent of ProjectItem.

    LV Classes have tried to expose out functionality for the runtime engine that we think is useful in various utility VIs. The most important two are in the palettes (one appeared in 8.5, the other in 8.6). You can find others here:

    vi.lib\Utility\LVClass

    Please note that the ones not in the palettes may be removed/refactored/renamed between LV versions. This is basically my hiding place for lvclass functionality that multiple customers ask for but for which I don't have time to make a nice, stable, documented interface.

  6. Yair posted an example where events were fired A then B but the event structure was handling them B then A, which contradicts the stated behavior of the event structure that it handles events in the order they occur.

    QUOTE (Yair @ Apr 27 2009, 02:37 PM)

    If you look at the block diagram, you'll see this:

    post-5877-1240863300.png?width=400

    You'd expect that the user event would be handled before the control value change event. I followed up on this. It is "regrettable but correct behavior." In other words, not intended behavior but a logical result from the rules of the system, so not really a bug.

    When events fire, they are placed in a queue. They record a timestamp of the time they occurred. The timestamp has millisecond resolution.

    There are separate event queues for dynamically registered events and statically registered events. In Yair's demo, the user event is registered dynamically and the value change is registered statically, so there are two queues. The event handler looks at each of its queues and takes the earliest timestamp. In this case, the timestamps are identical and the statically registered event wins.

    Workarounds:

    1. Dynamically register for both the user event and the value change event. [This is the preferred workaround.]

    2. Add a millisecond delay after the firing of the user event before firing the value change event to guarantee different timestamps. [This is a hack.]

  7. QUOTE (ShaunR @ Apr 26 2009, 11:53 PM)

    Even if there IS data in the queue but not for that "thread"?
    Loop A reaches a Dequeue node. If there is data already in the queue, it gets the data out and continues running the rest of the diagram. If there is no data, it goes to sleep until data is supplied by another section of the diagram running an Enqueue node.

    QUOTE

    And (just a point to fill my knowledge gap) Are you saying that 2 while loops (or 50 even) will run in their own separate threads?

    Generally, yes. Any parallel node in LV (meaning any two nodes where the outputs of one do not flow through wires to inputs of the other) will run in parallel. We only spawn N threads where N is "number of CPU cores x 4". This includes while loops. If the number of parallel nodes exceeds the number of threads, the threads will use cooperative multitasking, meaning that a thread occassionally stops work on one section of the diagram and starts work on another section to avoid starvation of any parallel branch. If you have two parallel nodes and you have two available CPU cores, each node will execute truly in parallel, one on each core.

    This is the key reason why LV is such an incredibly powerful language in modern computers: from the raw syntax of the language, parallelism can be identified and acted upon without requiring explicit coding from the programmer (where as in other languages the programmer must manually create calls to Fork and Join and manage all of the communication between those).

    QUOTE

    There's a big difference between events and queues. (I think your comparison is to events as the rest of your post is about them although Aristos is talking about queues and notifiers I beleive). Events can happen in any order an at any time I think I heard someone say before
    :P

    Events are fired from the user clicking/typing or from one of four nodes: the user event firing node, the Value (signaling) property node, the FP.Close invoke node and the AppExit node. I believe this is a comprehensive list. So the events can be *generated* in any order. But that's no different from saying any two parallel branches can Enqueue into the same queue in any order.

    When the events are *handled* they are always handled in the order they were generated. In the same way, data is always dequeued from the queue in the order it was enqueued.

    QUOTE

    API? Thats windows speak...lol. You weren't a C++ programmer in an earlier life were you?

    API is pretty common term in any programming language when you have different modules or libraries. 21 years ago, when I started programming before Windows even existed, the term API was used for the C libraries, as in "I created a new .c file that runs faster than the UNIX version, but it has the same API."

  8. QUOTE (jdunham @ Apr 26 2009, 12:29 PM)
    I generally run these handlers with infinite timeout, so there is no timeout case (and no wait function). LabVIEW's internal execution scheduler may have to poll the queue somewhere deep in the bowels of LV, but that's not exposed to me.
    Let me assure you -- it really does go to sleep. There is no CPU load at all from a sleeping queue prim. There is no polling for data. Thread A executes and goes to sleep on a queue. Thread B runs free. When Thread B puts data into the queue, it wakes up thread A. In fact, it doesn't even put the data into the queue. It puts it directly into the output of Thread A and A wakes up and starts running as if it had just gotten the data out of the queue.

  9. QUOTE (Yair @ Apr 25 2009, 12:48 PM)

    I fail to see the big difference between this and the original form of the question. In any case, you should note that the behavior I demonstrated only occurs until you close the VI. When you reopen it, the constant is equal to 0.
    The constant's value is always zero. That's the key thing to realize -- if you change a control whose value is non-zero into a constant, for refnums, you always get zero.

    QUOTE

    All this circumvents the main issue I and others brought up - should such a thing be asked, at any level of certification? I would say that this is both arcane and unreliable knowledge, as NI could change it, and doesn't have any real value, other than as a trivia question (which as we can see needs to be checked before it can be answered correctly). Ideally, any advanced developer should know to use the Not a... primitive, although I'll admit to using the type-cast-and-compare-to-0 method myself in production code in the past.

    It better not be something that NI could change. That's equivalent -- to me -- of saying you can't rely on the behavior of the Add primitive because LV might decide to make it do subtraction. These behaviors are exactly the sort of behaviors that I consider "language" as opposed to "editor". Both the "what does the "not a" prim do" and the "what is the value of a refnum constant" ought to be things that a LV programmer can absolutely depend continuing to work in future LV versions. If a change were to occur, this is the sort of thing that (a) would require significant mutation code such that existing VIs continue to operate as they did before, (b) an change to the diagram drawing such that the new primitive or the non-zero refnum constant look substantively different from the existing prim or constant, © "save for previous" functionality, and probably (d) some way to continue to drop the previous functionality in the new LV version.

    I did botch the original post, but that was slop on my part, and shouldn't factor into whether or not this is defined LV behavior. Runtime functionality cannot be "just trivia."

    The value of the constant is in the same category as behavior of an output tunnel of a For Loop that executes zero times. LV users' ability to read the diagram and understand what was happening would be severely impacted by changes in that functionality, in addition to the runtime logic changes.

    The functionality of the primitive falls in the same category as knowing that the "Search 1D Array" primitive does a linear search, not a binary search, and knowing how "Sort 1D Array" behaves on a heterogenous array of LV classes. These are runtime details of these functions that have to be spec'd out and nailed down explicitly.

    For both of these categories, any variation in that functionality from NI has to be compensated for by mutation code between LV versions and with changes in draw style on the diagram to highlight the difference.

  10. QUOTE (Yair @ Jun 27 2008, 06:33 AM)

    I realized the correct answer to this: The name of the class can be a whole string of PStrs connected together when the class is itself inside an owning library. So if the name of the class is "MyLib.lvlib:InnerLib.lvlib:MyClass.lvClass" then the string would be

    WXMyLib.lvlibYInnerLib.lvlibZMyClass.lvclass

    where W = length of the whole string

    X, Y and Z = length of their respective substrings

  11. Write linker info is not recommended unless you are one of two developers on the LV R&D team and even then only if you are writing pretty much exclusively to VIs that don't link to anything "special" -- by which I mean anything other than another VI. (So no shared variables, libraries, classes, elemental I/O nodes, mathscript files, state charts, xcontrols, properties of xcontrols, xnodes, DLLs, pink hearts, orange stars, green clovers or purple horseshoes.) It exists predominantly to read a VI's existing linker information and then make a few very specific changes to that info and then write it back. It is not a panacea for cross-link repairs, app building or updating relative links.

  12. I've been asked about queues on RT a few times this year and I gave the wrong answer, so I want to correct that here because (a) I don't remember exactly who I was talking to and (b) I don't know who else in the community may have heard my answer from those original people.

    If you call Obtain Queue and give it a maximum size for the queue, on RT the queue will go ahead and allocate its buffer to be the maximum size. I was incorrect that you need to have an initial loop to allocate space in the queue before you use it.

    The "allocate space on RT" behavior goes back to LV 7.0. Only in LV 6.1 did you have to have an initial loop to allocate the buffer.

    I apologize for anyone that I misled.

  13. QUOTE (Mark Yedinak @ Apr 22 2009, 04:58 PM)

    If however you mean taking a single FOR loop and splitting its iterations across cores then I would agree with you that LV does not do this. However this would be a nontrivial task.
    A non-trivial task? Really? So, in other words, you'd be impressed if LabVIEW could do that? We're always looking for features that would impress our customers... I'll let some of my developer buddies know that you'd like to see that in the August 2009 release...

    :ninja:

  14. QUOTE (orko @ Apr 21 2009, 01:18 PM)

    Suppose I have X.lvclass which as a member VI Y.vi. Normally Y.vi takes the class in and does something.

    I now create WrapperY.vi which takes as input an unsigned 32-bit integer (uInt32). On the block diagram of WrapperY.vi, I either

    With the object now in hand, I call Y.vi. If Y.vi passes the modified object out, I store the output back into my LV2-style global or my refnum architecture.

    QUOTE (mesmith @ Apr 21 2009, 02:25 PM)

    Of course, this presumes that class member VIs that don't include class types as arguments can be used as interfaces to DLL's - I don't see why not, but I haven't tried.

    Yes, that works just fine.

    QUOTE (orko @ Apr 21 2009, 03:01 PM)

    Is it me or doesn't this seem like something that would be able to be done programmatically within the App builder? The whole "Build me a DLL from this class" concept.

    If you'll notice, the architectures required to do this vary wildly depending upon requirements and desires. There is not a cannonical solution to this problem. Indeed, the only thing that R&D can assert is what we already assert -- you can't build a DLL with a class directly in the interface. You have to be inventive...

  15. QUOTE (Charles Chickering @ Apr 21 2009, 02:26 PM)
    is there a programmatic equivalent to right clicking my "Power Supply" class and clicking "VI from Dynamic Dispatch Template"? Thanks for your help.
    The post I gave above is the instructions for creating an override VI from an existing dynamic dispatch VI. To make a new VI do dynamic dispatching, you just need the part of the instructions where you change the conpane terminals.

  16. Are you having trouble setting the connector pane to be dynamic input and/or output? Start with VI reference... get the Conpane reference... use the method/property (I don't recall which) on conpane to set the desired terminal to Required/Recommended/Optional/Dynamic. If the input is set to Dynamic, boom, you've got yourself a dynamic dispatching VI. As for how to create the override VI, sorry, but that isn't exposed directly. The long route is to take the source VI, do Save As on it, then Select All on the block diagram, unselect the FPTerminals and delete the remainder. Then replace any Parent class inputs/outputs with Child class. The VIs to do all of this ship with LabVIEW but you'll find that they're private members of a library, so you can't invoke them directly.

  17. You're not going to like these two solutions but I'll mention them anyway...

    1. Any VI that has a class on its FP (as either an input or an output) that you want to expose through the DLL should be wrapped by a VI that takes a cluster instead (as input or output) and creates the class from that cluster (input) or creates the cluster from that class (output). Doesn't work if you were hoping for something that uses different object types for different calls into the API, and you may have to expose more public methods than you would want to. But to get through the DLL layer, you have to shed the class sheild.

    2. Create either

    • an LV2-style global of an "array of object" type that can do get/set on individual indicies of the array
    • or some sort of reference architecture (a la the GOOP Toolkit)

    and any time you would pass an object out to the DLL layer, pass the index into the LV2-global or the refnum out instead. When you make a call back into the API with an object input, pass the previous index/refnum as input. You can use -1 or not a refnum as a sentinel for "create a new default object."

    Those are the best solutions I can offer. It's a hard to manage problem.
×
×
  • Create New...

Important Information

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