Jump to content

Aristos Queue

Members
  • Posts

    3,183
  • Joined

  • Last visited

  • Days Won

    204

Posts posted by Aristos Queue

  1. My guess is that in memory, the computer not only needs to know the value of the 32 bits, but it needs to know the type of data it is as well.

    Actually, it just needs to know the value.... but the value of the number "4"

    • as an integer is binary 00000000000000000000000000000100
    • as a single precision floating point is binary 01000000100000000000000000000000

    The binary is actually different, so code that needs the single-precision float cannot share the memory with code that needs an integer.

  2. It was deprecated, which means we strongly recommend you do not use it at all and it may be removed in the next+1 version of LabVIEW. Generally the context help of the deprecated function describes the intended replacement function or the reason why this functionality is not stable/usable/meaningful in the latest LV version.

  3. Dynamic dispatch means that you don't know at compile time which VI will execute, and it would be impossible to preallocate a clone of an unknown VI.
    We talked about the possibility of cloning *all* of the possible subVIs that you might call -- after all, it is a finite set of VIs that might be invoked -- but ultimately we decided that was very rarely useful, to the point that it was better to just steer everyone into the share clones model. If you need some state for your function stored in an uninit shift register, the recommendation is to put that shift register on a static dispatch VI that calls the dynamic dispatch VI as a subVI.
  4. Can you explain what you mean by 'destroying the data integrity of your D object?' I wired up a simple project to try and follow through the different scenarios you described and I didn't see data internal to D get corrupted or reset.
    You didn't see the data for D change... and *that's* the problem. ;-)

    Let's take a simple case:

    Class A has a private field "numeric" (default value 0)Class B inherits from A and has a private field "numeric2". (default value 0)Class C inherits from B and has a private field "numeric3". (default value 0)Class A implements a static dispatch VI "Get Numeric.vi" that returns the value of its private numeric field.Class A implements a dynamic dispatch VI "Increment.vi" that unbundles Numeric, adds 1, and bundles it back into the object.Class B overrides "Increment.vi" to unbundle Numeric2, add 1, and bundle it back into the object. Then it invokes the Call Parent Method.Class C overrides "Increment.vi" to unbundle Numeric3, add 1, and bundle it back into the object. It DOES NOT invoke Call Parent Method.

    What happens when we call "Increment.vi" and then call "Get Numeric.vi"?

    If the object is of type A, we dispatch to A:Increment.vi, and Get Numeric.vi returns 1.If the object is of type B, we dispatch to B:Increment.vi, call up to A:Increment.vi and Get Numeric.vi returns 1.If the object is of type C, we dispatch to C:Increment.vi, and Get Numeric.vi returns 0.

    Would you agree with me that any time I call "Get Numeric.vi" on a C object that I should get zero as the answer? Since C has overridden Increment, there's no other way for that field to be modified. So one of the invariants of C objects is that Get Numeric always returns zero.

    Now, what happens if, on the diagram of B:Increment.vi, we wire a C object directly to the Call Parent Method node? When we call "Get Numeric.vi" on that C object, we get the answer "1". That violates one of the invariants of C objects. The defined interface of the class is broken. And that's a problem.

    • Like 2
  5. Wow. I think you've created a situation I never expected anyone to construct. The answer to your question is easy, but you make me think we ought to kill the functionality you're taking advantage of. And, more than what we (LV R&D) ought to do about it, I really want to know why the heck you are in this situation!

    Short answer: The Call Parent Method always calls the ancestor implementation of the VI. It does not care about the type of the object on the wire. So Call Parent Method on the block diagram of B:M.vi will always call A:M.vi.

    Long answer: Somehow you have an instance of D on a diagram of B:M.vi and you are passing that D object to the Call Parent Method node. How did you get this instance of D on the diagram of B:M.vi? Here is how I would have expected that it got there:

    1. Top level VI is "Caller.vi"
    2. Caller.vi has an instance of D on its diagram
    3. Caller.vi makes a dynamic dispatch call to M.vi, which dispatches to D:M.vi.
    4. D:M.vi uses the Call Parent Method to invoke C:M.vi.
    5. C:M.vi uses the Call Parent Method to invoke B:M.vi.
    6. And now you are asking what the behavior will be when B:M.vi uses Call Parent Method, and the answer is A:M.vi.

    Now, that's what I would have expected. Your question implies that something like this happened:

    1. Top level VI is "Caller.vi"
    2. Caller.vi has an instance of B on its diagram.
    3. Caller.vi makes a dynamic dispatch call to M.vi, which dispatches to B:M.vi.
    4. On the diagram of B:M.vi, you somehow obtain an object of type D, either from a diagram constant directly on the diagram or retrieving this D object from some data store (global variable, queue, etc, or maybe just by unbundling data stored in the B object).
    5. And now you propose to wire that D object to the Call Parent Method.

    Please tell me that is NOT what you are doing. It sounds like it is, but it shouldn't be happening. There should never be a reason why you would ever want to do this. If you directly pass that D to the Call Parent Method, you are destroying the data integrity of your D object. Any object assumes that if it provides an override of any method then the ancestor method will never act on that object unless it was because the overriding VI used the Call Parent Method to invoke it.

    I and my team never discussed this case. The fix for the LV compiler is obvious and easy -- the dynamic dispatch input terminal of the Call Parent Method should only accept wires that propagate down from the dynamic dispatch input of the invoking VI. In other words, only the wires that have the gray background should be able to wire to the dynamic dispatch input of the Call Parent Method, and the VI should be broken if anything else is wired. That is not enforced today, mostly because it never occurred to anyone that you might ever try something like this.

    I could be completely off base in my understanding of what you're asking. But if I've hit the nail on the head, can you please explain *why* you are passing this D object to the Call Parent Method without climbing up through the hierarchy, starting at D:M.vi? If there's a real-world use case for this, I am going to be absolutely stunned. My bet is that you're just creating a situation in which D is not being updated correctly.

    Now, it is legit to have this situation (steps 1 to 4 are identical to the previous steps):

    1. Top level VI is "Caller.vi"
    2. Caller.vi has an instance of B on its diagram.
    3. Caller.vi makes a dynamic dispatch call to M.vi, which dispatches to B:M.vi.
    4. On the diagram of B:M.vi, you somehow obtain an object of type D, either from a diagram constant directly on the diagram or retrieving this D object from some data store (global variable, queue, etc, or maybe just by unbundling data stored in the B object).
    5. You make a new dynamic dispatch call to M.vi, passing the D object as the dynamic dispatch input. This will call out to D:M.vi and may eventually make a recursive call into B:M.vi, if all of the override VIs keep invoking the Call Parent Method. This eventually results in a recursive call to B:M.vi, which will either panic stop if the VI is not reentrant or will allow the recursion if the VI is reentrant. You'd need in that case to make sure that B:M.vi is written such that infinite recursion does not occur.

    Does this sound more like what you're intending to write?

    • Like 1
  6. I don't think it has anything to do with data copies. I'll bet it is just the time needed to do the thread swapping. If you are "same as caller", then the same execution thread can run the subVI and you can just keep working. If you force a change of execution systems, the VI has to stop, put itself back on the run queue, and wait for a thread from the chosen execution system to come along to execute the subVI. Then it has to go back on to the execution queue to switch back when returning.

  7. "First, you might want to consider using LabVIEW User Events for passing data instead of queues, that way your UI will never be polling"

    ...

    I really like this idea and I am thinking of trying it for new rewrite, I just wondered about people thoughts and comments on this as it is not really a standard design pattern.

    Actually, it is a standard design pattern in LabVIEW. NI has presented it in many places. Most recently, it was in the spring 2009 Developer Days conference presentations for "Design Patterns in LabVIEW." The slides are here.
  8. Who says you can't teach an old dog new tricks!
    You joined at a good time. The whole site crashed last month and had to be rebuilt from backups and along the way got a MAJOR facelift, so everyone on the forums is "finding their way around" right now. So if you find any good tricks that others don't seem to be taking advantage of, do flag them on the Site Feedback forum! We could all use helpful tips in this brave new world. ;-)
  9. As much as I'd like to go I can't afford 40 hrs of lost wages plus the cost of attending the event itself. Such is life as a contractor.
    I thought the whole point of being a contractor is that you could get your assignment and then go off and do it... and if that means writing code while you're sitting in the Austin Convention Center between sessions, so be it. I take it your particular contract precludes such untethered work?
×
×
  • Create New...

Important Information

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