Jump to content

Aristos Queue

Members
  • Posts

    3,183
  • Joined

  • Last visited

  • Days Won

    204

Posts posted by Aristos Queue

  1. A cluster is a collection of variables. A collection of variables is not a "constant". Is it within the rights of NI and the LV community at large to assign a different (and contradictory) meaning to a term that has already been well defined in the field of math and sciences for centuries? I would have thought someone at NI would have had a similar concern.

    "The Gravitational Constant is a variable in my equation."

    Variable does not mean necessarily changeable. It can mean just value. A cluster is a collection of values. Those values might not change. If they don't change, they are constants.

  2. I like the sound of this feature being integrated.

    However, it would not help if your constructor required inputs???

    Thinking out loud...

    • Would it be possible to flag a method VI as a constructor and somehow check that there are no constants on the BD (sounds tricky)
    • What about when you drag and drop the class/control onto a BD it could automatically drop the flagged constructor VI instead?

    No go. You need a *constant* value, something that can be set once and only once in the entire run of the app. It cannot take *any* inputs and its only output is the class value. All of this is conception only -- since we started deploying on RT, as I said, I'm not sure that the centralized bottleneck exists that would let us make this work. It's messy even to think about.

    There is one option that hasn't been discussed in this thread: Suppose my parent class has a field "Color" and a "Get Color.vi" and a "Set Color.vi" both of which are dynamic dispatch. The parent class implementation of Get and Set just returns the color field or sets it (respectively). The child class has a boolean field "Has been set?". It overrides "Set Color.vi" to set the boolean to True and then calls the parent version to set the field. The "Get Color.vi" override checks 'has been set?'... if it is True, it calls the parent to retrieve the value. If the value is false, it returns its own local constant value.

    This avoids the need for a constructor, it makes block diagram constants and controls behave exactly as requested in the original post. It is more effort than a programmer might wish to deal with.

  3. The feature requested in the original post does not exist in LabVIEW. We've talked about some sort of specially tagged VI that runs once when the class is reserved to set the default value that will be used for the rest of that run (and which every control/constant that is using the default default value would therefore use), but it hasn't ever been implemented. Since there is no central copy of the default value on RT systems, that would be hard to implement there.

  4. One question remains though why aren’t we allow to do this?

    There are four "interesting" cases of a class containing itself in its private data cluster. The cluster could contain...

    1. ... the class cube directly [this is functionally identical to the class cube inside a nested cluster]
    2. ... the parent class cube directly with the default value set to an instance of the child class
    3. ... the class cube in an array
    4. ... the class cube in a refnum (DVR, Queue, Notifier, Datalog, User Event, User Event Registration)

    If we're talking about direct inclusion (case #1), Daklu got the answer right in his post above. The same infinite allocation that he describes would happen in use case #2.

    So cases 1 & 2 are off the table permanently as "logically impossible to ever implement" (unless LV ever introduced a lazy evaluation language syntax which would be a very different programming model than anything that exists today -- I mention the possibility only so that someone doesn't say something like, "If it is impossible, how does Lisp or Haskell do it?")

    For case #3, if the array is non-empty, you have the same problem as 1 & 2, but if the default value of the array is empty, it would be fine. Case 4 never has to allocate the actual data of the class (it just allocates space for a reference cookie, a cookie whose default value is always Not A Refnum), so it should work. That, I think, is the heart of Mikael's question: Why doesn't this work in LabVIEW?

    What we found is that we could get some significant performance boosts during load, notably dynamic loading into an already running hierarchy, if a class hierarchy has no circular dependencies (meaning it does not reference itself, including indirectly). There's a lot of work to identify which class can instantiate and reserve first. If all the references are changed out for parent class references, users can still write all the functionality (albeit with a slightly modified syntax than they would generally try first) and LV could simplify the load and reserve algorithm considerably. I looked through various lists of recursive data structures. The most common that I saw were composition patterns, such as is in the Graphics shipping example in LV, where Collection inherits from Graphic and includes an array of Graphic. Those are unchanged because they are already including their parents, not themselves. The other class was the linked lists, trees, and graphs. Honestly, I expected most of these to be written once by someone who was an expert in LVOOP and then most users would just use them as libraries. That expectation was predicated on other features of LabVIEW existing which have not come to fruition. Even so, it appears (based on AE reports and my looking at user code when I get a chance to visit customers) that very few LV users ever attempt to build anything recursive, much less a recursive data structure, so I wager most of those who attempt it are people who are power LV users who generally know about LAVA and will post questions (like Mikael's) and find these answers.

    Not true. You can implement the composition pattern. It is perfectly legal for an object to contain instances of itself at runtime. You just can't define a class with a self-reference. Use LVObject as a container and do the downcasting as part of the accessor methods.

    Even better, define a parent class that is not recursive with dynamic dispatch methods for anything that would be recursive, then define a child class that overrides all the necessary VIs. That way you avoid the downcast. As of LV 2010, dyn dispatch is faster than downcast (although the compiler team is working on some new optimizations for future LV versions that may change the balance of power here).

    The <labview>\examples\LVOOP\Graphics\Graphics.lvproj has an example of the composition pattern.

    • Like 1
  5. "Listener framework" == Observable/Observer?
    More of a message passing interface between a server and client, but either one of those parties may essentially implement an events registration mechanism on top of the message passing interface (i.e., I pass you a message that says "next time X happens, let me know." When X happens, you send me a message to that effect.)

    To give you a clue how similar what I've been assembling is to yours, the name of my project file is "Actor Objects.lvproj". :-)

    PS: You clearly have a larger monitor than I do. All the VIs are saved just barely on the screen.

  6. Alpha creates a temporary sync object to pass to Beta (usually a notifier to hold the final sync object reference), starts up Beta, then blocks on the temporary notifier. Beta starts, creates the permanent object which it owns, and signals Alpha using the temporary object, then continues on its way. Meanwhile, Alpha receives the permanent object reference, takes note of it, and continues on it's way, passing signals as appropriate.

    This is exactly what we have thus far. The extra complexity is entirely hidden within the subVI that does the launching, so it doesn't have to be repeated each time.

    In general, we might be ok if Beta misses some signals, but the key signal to Shutdown is one we cannot afford to miss and that's the one most likely to be missed without this set up.

  7. Yes I think i will use an occurence with the OpenG wait with a timeout of 1000 ms, that should do the trick. I am reluctant to give the destroy to the child process since I don't have control over it, and the event registration is created in the main process, and I am a fan of the 'destroy what you create' philosphy.

    Then let me suggest that the wrong process is creating the event refnum. ;-)

    This is a problem that I ran into with a listener framework I've been working on lately. Alpha.VI dynamically launches Beta.vi and then gives Beta.vi a queue refnum so Beta can receive messages from Alpha. We had to turn that around -- Alpha launches Beta and then Beta creates the queue and gives the refnum to Alpha. That way the lifetime of the queue is the same as Beta, not Alpha.

    In your case, it sounds like the correct behavior is for your consumer to create an event refnum and give it to the sender. That way the consumer can dispose the refnum after it handles the event and "destroy what you create" policy is preserved.

    • Like 1
  8. <-- member of LabVIEW R&D shifty.gif
    Man, I hope Todd (the judge) picks my questions to use for the Challenge this year. I submitted a couple really cool (IMHO) ideas.

    For those who weren't there last year, the challenge I submitted was to write a VI that failed at least 10 of the VI Analyzer style tests. It was quite amusing watching programmers have to fight their own tendencies to write good code -- one person kept reflexively fixing the style problem and had to keep putting it back as he worked. :-)

    How much time to guys you make outside of sessions to see everything else (floor expos etc...)?
    I don't sleep that week. Hanging out with Norm and attempting to leech some of his infinite energy is sometimes useful strategy. I've also attempted simultaneous physical manifestations in multiple locations... that works, but the reintegration is a real pain. Reading blogs later for the sessions you miss works better.
    • Like 2
  9. Ok... you cannot have two VIs in memory of the same name, so the manifest VI cannot have the same name in all the LLBs.

    Option 1: What if the manifest VI has the same name as the LLB but with the extension swapped out? That gives you a consistent way to find the manifest VI every time and no risk of collision in memory because each LLB in your directory has to be uniquely named.

    Option 2: Name the manifest VI the same thing every time, but put it in a library that is uniquely named and put the library also in the LLB. I hate this option because it piles hacks upon hacks, generating a second useless file to work around the limitations of the first.

  10. I know it's a older thread but I came across it when researching the Singleton object. My problem with all the implementations of singleton is that I encountered so far is that they also rely non-reentrant VIs to achieve single instance. Is there a good way to implement this using all reentrant VIs.

    Yes, it can be done, but it isn't really a good solution. Why? Because access to a singleton object *must* have some sort of thread protection around it -- that's the entire point.

    If you make it reentrant, then you introduce the need for some sort of single-allocation storage. That moves you to one of these two solutions:

    1. a global VI AND use of the Semaphore palette to protect all accesses to that global VI

    2. an internally allocated Data Value Reference, which works as long as you only have one top level VI referring to the singleton because otherwise you run into lifetime management issues.

    Since singleton access really has to be serialized anyway, it's easiest to just use the non-reentrant VIs. You get zero advantage out of making something reentrant when it has to serialize its access anyway.

  11. Getting to the class by the Name property works, whereas the Path property returns a blank when the class is not saved and the Open VI Reference for the Control returns the error 1004

    The name mashing is still the same as it is still similar to the previous thread.

    I guess it only matters if you are reading the class off disk and not in memory, then it would be saved anyway so use the Path.

    Just noticed this... actually, you would *always* use the Name and never the Path. Why? Because the class name will include its fully qualified name. If the class happens to be a member of a library, it's qualified name is X.lvlib:Y.lvclass, and you need that full qualification when you build X.lvlib:Y.lvclass:Y.ctl or else Open VI Reference by name won't work (or will give you a completely different CTL if there happens to be a plain Y.lvclass in memory at the same time).

  12. But I don't know how to get the whole attribute cluster.
    You don't have a mechanism to do this, and if you find one, it's a bug that should be fixed. The class' data is private. If the class does not provide a mechanism for you to get at all of its fields, you do not have any way to get at all of its fields. This is by design.

    Some folks have figured out ways to take the flattened string for some known cases and manipulate that directly. That's a hack that can be made to work, but there are limitations to that approach.

    The Read All Attribute VIs mechanism that you mention at the start is the right, good and correct way of doing this.

  13. I've reviewed all of the 1140 ideas currently on the LV Idea Exchange. I've picked out 24 ideas that have fewer than 100 Kudos that I think are good ideas that, for whatever reason, have been overlooked by the community. If you have been daunted by the sheer number of ideas, here's a reduced set for you to take a look at and consider kudos'ing. Taking a few minutes to review them might just help your LV experience in the future:

    http://forums.ni.com/t5/LabVIEW/24-Great-Ideas-from-Idea-Exchange-for-you-to-Kudos/m-p/1154123#U1154123

    • Like 1
  14. Everything in parenthesis must be a library, and everything not in parenthesis must be a class.
    At the moment this is true... ideally that would not be true. A class is a library and should be able to contain other classes. There's a technical difficulty we have in LV (dumb design on our part) that keeps that from happening. My hope is that this can be overcome in a couple years when we finish a larger refactoring effort.
    I pulled a Homer with the earlier suggestion of using a tree view to show namespacing. The inheritance dialog box already uses a tree view to show the inheritance hierarchy.
    Yeah, I didn't comment on that earlier. Tst on the NI forums summed up the problem nicely:
    So far, I don't remember placing classes inside .lvlibs, so I can't really comment on this, but I think that if you do it nested it will be confusing, because you're combining the inheritance hierarchy and the ownership hierarchy in the same tree.
  15. I'm guessing this is because the classes aren't smart enough to know (or maybe simply can't know) that the parent's fully qualified name was changed

    This is by design.

    As far as the child classes are concerned, if they inherited from "A.lvclass" and when they load into memory they find "X.lvlib:A.lvclass", well, that's not their parent. You're asking kindergarteners to go home with strangers who happen to share Mommy's name. Won't someone think of the children?! :-)

    If you change the parent's name while the children are in memory, then they'll know about the name change and not load broken. In other words, parents should bring the kids with them to the Justice of the Peace when they get their names changed, so we avoid these socially awkward scenes in the grocery store with the child screaming, "You're not my mother!"

    :-)

    Come to think of it, I don't think your use case *can* be addressed without decoupling libraries and namespaces.
    Bingo. Absolutely correct. Unfortunately, that trick is not on the roadmap at this time.
    What I don't understand is that everything is already in memory so why aren't the parent links automatically updated to reflect the new namespace without using the workaround?
    When you changed the parent's name, did you do File >> Save All on all the children? Or did you exit without saving the children?
    • Like 1
  16. I think that's fine. I hope classes not in .lvlibs appear before or after, not intermingled, though.

    Nope... they'd be part of the alphabetization if I had the lone vote. That's actually kind of key -- you'd look it up by its qualified name. Otherwise things get messy -- would you want all the 2 level names before all the three level names?

    A.lvclass

    B.lvclass

    Z.lvclass

    X.lvlib:C.lvclass

    Y.lvlib:D.lvclass

    X.lvlib:A.lvlib:E.lvclass

    X.lvlib:Z.lvlib:F.lvclass

    Y.lvlib:Z.lvlib:G.lvclass

    That's mighty strange. This is the order I'd want them in:

    A.lvclass

    B.lvclass

    X.lvlib:A.lvlib:E.lvclass

    X.lvlib:C.lvclass

    X.lvlib:Z.lvlib:F.lvclass

    Y.lvlib:D.lvclass

    Y.lvlib:Z.lvlib:G.lvclass

    Z.lvclass

  17. Do you have a personal preference over which display method would be ultimately advantageous - or are you happy from a user perspective of the current implementation?

    Personally? I would prefer the fully qualified name be displayed, as in "X.lvlib:Y.lvclass" and alphabatize the list by the entire string. The dialog is as it is today from feedback from various and sundry when it was created X years ago, where X is receeding further into the depths of memory.

  18. Haha! I was thinking this exact same thing when I posted up the Idea - but I wasn't game enough to write it biggrin.gif

    Kudos for balls! cool.gif

    Yeah, that's the sort of "option" that ultimately makes things less usable -- most people toggle it once if ever, it clutters the screen, taking real estate away from other elements, and it opens a source of bugs for a rarely tested code path. Every usability guide you'll ever read will condem this sort of option, and if you doubt, you can run the usability studies to confirm it. Data presentation in a dialog should be something you commit do and do, not something you waffle over. Even if a few customers find the result less optimal than another option would have been, the net is still more usable than introduction of the option.

    • Like 1
×
×
  • Create New...

Important Information

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