Jump to content

mje

Members
  • Posts

    1,068
  • Joined

  • Last visited

  • Days Won

    48

Everything posted by mje

  1. Thanks, I'll see what I can do. I think I'm working with a different problem as the property names or VI names most definitely had not changed. Something else is amok here...
  2. Resurrecting this thread... I've managed to capture a case where the problem I described happened. This is the aftermath of it: I was working on a child class when a base class method (above) broke because of a property node. I had been making several changes to the child, so while I don't think anything in the base class was explictly operated on, I could be wrong. The property node methods definitely were not touched. The node just...broke, taking all my class implementations along with it. The node magically fixes itself if I open the VI that defines the read method and force a recompilation by swapping a connector terminal back and forth, for example. I'm wondering if I can possibly get this code to NI to evaluate if this is indeed the same problem addressed in CAR 248637? Mr Mike perhaps?
  3. First, neat trick AQ! I'd have never thought of that, especially since the behavior of that loop is usually the exact opposite of what is needed. Don't know how many bugs I've tracked down to not having shifters on a for loop... Valid questions. Also note I said I *think* I need something like this. I still haven't wrapped my brain around how to get around my problem. I was still trying to distill the situation to its fundamentals and decided to try to "talk" this through. Thanks by the way for paying attention to this wingnut idea, I realize how stupid it looks (and consequently how foolish I likely appear). The lock on the refnum which is required to invoke the dynamic dispatch (since it must operate on a value not a refnum) is causing me issues due to some circular references. The original post above allows me to decouple the lock needed to invoke the parent implementations from that of a given class implementation. ObjectA contains a reference to ObjectB, and vice versa. The ObjectA refnum is locked to invoke a dynamic dispatch method. The method locks the ObjectB refnum so it can operate on ObjectB. ObjectB can no longer operate on ObjectA... What I've come to realize during the last few hours is that I went about this entirely wrong. What I really ought to be doing is changing the order of operations such that ObjectB does not need to operate on ObjectA.
  4. So I've run into a use case where I can't think of a way out of my problem without having some sort of DVR-based inheritance mechanism. The problem being of course, that dynamic dispatches don't work with DVRs. Then it dawned on me I already have working code that does exactly what I need to do using a trick like so: Class A defines a method which takes a Class A DVR Refnum in and out, and a Class A value which the dynamic dispatch is based off of. Like so: The Type value is never actually operated on, it's only used to invoke the dynamic dispatch mechanism. Inheriting classes then implement the same interface, but are required to do some extra work before they can operate on data: The situation that needs dealing with is the DVR terminal remains a Class A DVR refnum, so it must be explicitly cast to a Class B DVR refnum before it can be operated on in a Class B context. As a courtesy, Class A also defines a helper method to invoke the dynamic methods: Over all the implementation is definitely more messy, but as far as I can tell it works. Of course there are people here far more learned in the art of LabVIEW OOPs than I, so I figured I'd post to see if I'm missing something entirely obvious. A few notes: The helper method (third image, Class A: Initialize Object.vi) retrieves a default value for the class to avoid making possible copies of large data sets. Think arrays etc, only the static size of the default value (usually quite small) ever gets duplicated... Casting the DVR does require a lock to be momentarily obtained on the refnum. Probably not important for most implementations, but I've been bitten by that in other parts of my code. This pattern requires the class which defines the interface to implement two methods: one at the DVR level and one at the by-value level. Descendant classes only need to worry about the by-value method, but do require a bit of extra work. Strictly speaking, the DVR method isn't required in the base, but it makes using the class much easier due to the behavior of DVR refnums... A BIG WARNING, is that this pattern breaks the atomic nature of the dynamic dispatch call chain. Take a careful look at the second screen shot, the parent implementation is called, after which anything can happen to the DVR before the Class B implementation gets a crack at operating on the data. This is exactly why I think I need the implementation to work this way, but could seriously break applications which require the entire call chain to be acted on atomically. Code (LV2010) attached: DDDVRs.zip Thoughts? -m
  5. This came by and bit me in the behind again: Basically, that the Not A Refnum primitive returns true for non "native" types of refnums even if they are valid refnums. Why does this primitive even allow refnums to be used when the behavior is at best inconsistent? I swear it should either behave properly or be removed from the palette. Sorry, venting. I know this is a well documented bug feature, has been so for some time, and the "proper" way of dealing with these refnums is using the Not A X Refnum.vi methods, but seriously? This primitive ends up more often being a source of bugs for me than not. I guess the C-style programmer in me just can't stop thinking of code such as: if (pRefnum){ // Operate}else{ // Panic!} Sigh... -m
  6. mje

    CAR Numbers

    Hah, good idea. I saw that in my RSS a few days ago but hadn't gotten around to reading it. Nice. Love it, laughed pretty hard at that.
  7. Easy question that I've not been able to figure out over the years. Say I have an NI CAR number for an issue, what do I do with it? Is there a database over at ni.com I can use to keep tabs on it? I mean other than crawling the forums for specific threads about the issue, if it can even be found (since "car" has an obvious other context, google isn't always friendly...).
  8. Right, I know what you're talking about. This is most definitely not the case for the behavior I was referring to. Specifically, I've had property nodes break in a VI which is a member of the class being operated on: the class method should have access to the private methods since it is the same class.
  9. This seems unintended. You can access private data of other classes in the inheritance hierarchy? If so then the property node implementation is flat out broken. That said, I have had a lot of problems with property nodes for class DVRs too. I have not abandoned them, but I have abandoned the plans to release a public library which makes extensive use of class DVRs until I can hammer out what is causing the problems I've seen. Identifying a use case which reliably produces the odd behaviors I've seen has eluded me so far though. In particular, my VIs using property nodes of class DVRs will often break because somehow a property node "blacks" out. What I mean by this is the property node text will be black, and it will be impossible to wire up anything to the value part of the node. I'll have to go back to the VIs that define the property node, force some kind of recompilation (usually by swapping connector pane terminals back and forth), which will then usually allow the property node to work. I've had methods in library classes break because of the property nodes used in their methods when working on child classes, forcing me to go in and re-compile the library VIs when nothing in the base class has changed. This can get particularly infuriating with complex hierarchies... I have not done any evaluation in the run time engine, I can only hope that the run time behavior is consistent with the IDE. The problems I've been having are always at design time. Crashes and errors a plenty in the IDE, but run time behavior seems solid (when things compile).
  10. Yes, that's exactly what I'm looking for.
  11. I see where you're coming from. Agreed. When I open up the VI with the generic control ref, I'd expect it to only know about the generic control ref. That's the interface the VI has set by virtue of its connector pane. What would be ideal though is if the VI had some way of recording continuity between the input and output. This facility does exist in LabVIEW, for example with dynamic dispatch method for classes it is indeed required. I have no idea how this gets sorted out for static methods given that the same requirement is not in place (maybe internally the compiler is still aware of in/out continuity?). It would be nice if refnum in/outs had the same functionality, or you could have another type of in/out connector that mimics the behavior of classes for refnums, such that explicit coercion does not happen when passing child refnums to parent methods. I suspect though that the details lay in how refnums are actually implemented. Something tells me we are not dealing with a strict inheritance implementation which will always force a coercion: there is no actual polymorphism happening with refnums (or dynamic dispatching in LabVIEW language). It's probably the same fundamental difference which results in the limitations imposed on class DVRs which prevent dynamic dispatching. Now that I've thought this through, I suppose it makes sense why it is the way it is. I still don't like it though...
  12. Right! But it would be good if the compiler were smart enough to know not to coerce it, just as it does for classes.
  13. Exactly, François, I think you did a better job explaining what I was trying to say.
  14. Are you sure about that memory leak? I thought one should only close refnums which you explicitly open? Haven't played with the desktop execution toolkit yet... Also, with regards to Shaun's questions, first please see the screenshot. Code used to generate it is also attached. I'm actually looking for the opposite of run-time polymorphism. I'd like a way for static compile time info to somehow be propagated. Take for example how you can wire up a parent method of an OOP class in the middle of a child class wire, without the wire being coerced to a parent class (shown in the bottom of the screenshot). LabVIEW is smart enough with objects to be able to figure out when type information can be propagated through a VI call with objects at compile time, it would be wonderful if that could also apply to refnums... Is that more clear? I'll point out that this is more of an "I wish it existed" post than "Is there a way to do it?" post... RefnumDemo.zip
  15. Is there any sort of LabVIEW voodoo that allows you to propagate type information for a refnum through a VI? I have VIs which take generic Control Refnums in then out, but the problem is the output always looses it's type info. So I can't ever use the output to wire up to another VI which operates on a more specific class, even if I supplied that class to the input. Example, this little bit of code I've been using for ages which defers panel updates which I'm sure many of us can relate to in one form or another: I have VIs that operate on refnums of one type or another (especially XML) that I'd really like to not have to always "branch off" the refnums to be able to operate on them. Is there a way to do this, sort of similar to how type info is propagated for LabVIEW objects? I'll add I'm aware I can just make a ton of polymorphic VIs. I've even done as much. But it's kind of kludgy, and requires an implementation for every kind of refnum...
  16. For things like setting the symbol and color of cells, I'd expect a list box to be about the same since you still need to always set the active cell then the color for each cell? I can give it a whirl, if it is indeed faster I can kill the tree.
  17. There is the possibility for update requests to pile up pretty quick. If for example a user holds down the increment/decrement button on a numeric control, dozens of value change events can get generated in a second, each of which will require an update to the tree, which seems to take on the order of a half second. I also like the idea of tinkering during timeouts. I suppose the other way of doing things is have the tree update be entirely asynchronous. Just keep it notifier based, or something such that multiple requests don't pile up if they are generated faster than they can be consumed. As an aside, I still can't believe tree controls are this busted. Changing UI properties for non-displayed items should be near instantaneous. If NI won't implement it, I wish they'd expose more events such that we could apply updates more intelligently. And for the non-believers, if I disable all the tree operations in the screenshot I posted above and instead blindly operate on all elements in my variant/hashtable, my updates happen in mere microseconds, so it's not my interaction with the variant or my subVI that was choking things off. Once I get an initial code out there that works, I might tinker with dropping a custom .NET control into there or something that...works.
  18. Ah right. Forgot to mention that. Yes, the code is wrapped between a set of defer update property sets.
  19. He said "poll". BURN HIM! In all seriousness, that could work though. Or implement something like that in response to all possible events that could change what is displayed.
  20. So I have a tree control with hundreds of items in it. I need to update the status of these items quite regularly based off input from other controls. The problem is updating all items produces a noticeable delay which I don't like. So I implemented my update code to only work on the currently visible items: The problem I'm left with is what happens when the user interacts with the scrollbar and new items are shown? My current idea is to implement a series of cludgy events such as mouse down, up, drag, value change (for keyboard interaction), etc...but there's got to be a better way?
  21. mje

    dB Qs

    I prefer MySQL over MSSQL as well. Never tried Postgre, and have been impressed with SQLite, though it's of course local only. Been at least 6 years since I've done anything with DBs, and never in a LabVIEW context, so take my experience with a grain of aged salt. I think both the MSSQL/MySQL flavors offer similar package as far as foreign key enforcement, triggers, views, etc. The one thing I found desperately lacking in MSSQL though back in the day was the lack of any ability to directly limit results to subsets. If I wanted to return rows 10001-10050 of a large data set, I had to get creative with my queries or just brute force through the result set. MySQL allowed me to easily specify that I want only those 50 records with a simple LIMIT statement, no fuss, no sorting games or anything.
  22. Oh boy, I remember those commercials from when I was a kid. That was an excellent parody...
  23. They had a little booth at NI Week and it looked pretty slick. Beyond that I haven't had time to look into it. The fellow at the booth mentioned it was new to 2010.
  24. Yes, good point, ned. Now I think I might be a little obsessive. But here's some data. Method A: This is a slightly modified version of the first method I put up in my original post. Concatenation in loop. (Method B is not worthy of mention it's so slow, it's the second one in my original post) Method C: Modified to pre-allocate the intersection array, then trim it as necessary. Method D: Re-uses one of the input arrays, then trims it as necessary. I'd expect that this has an implicit allocation though if the compiler decides that the VI can't operate in place on the caller's data (not verified). The metrics are that for sets where the intersection is very small compared to the input (say 2 elements out of 10 000), method A is fastest, but not by much. Note this is my typical use case. A: 561 C: 655 D: 624 When the intersection is larger, say 2500 out of 10 000 elements, method A starts to show its limits due to in-loop concatenation. Method D works out to be fastest. A: 1326 C: 780 D: 608 I'm surprised A doesn't show more of an improvement in small intersections. Given that find, I think D is the clear winner. Still trying to wrap my brain around if this could be done more intelligently by applying binary type searching rather than indexing, but I think I'm satisfied enough for now. I'll add that given the poor performance of B, I didn't even explore parallelism. Yet to look into the derivative methods, but I suspect they'll be quite slow given that for no other reason the data needs to be cast to arrays of doubles, but I expect the differential function to be the real bottleneck, never mind a linear iteration still needs to be done to build the intersection array. Might explore after getting some sleep.
  25. First yes, intersection is the element present in both arrays. Of course, there's no need to do the concatenation. However my use case has the input arrays potentially being orders of magnitude larger than the intersections, I really don't want to do an allocation like that if I don't have to. Plus, NI has some really good optimizations for array sizes. Tests I've done earlier implied when arrays are allocated, a chunk of memory larger than the array size is used, allowing the array to grow without reallocations. I believe it seemed that reallocations only happened every time the array doubled in size or so (within reason, I'm sure larger arrays work off fixed size padding, possibly small ones too). With those considerations, I left the concatenation operation in the loop. For the record, I think there are three things that can be done with the arrays: Operate in place on one of the input arrays (that is overwriting it as you go). Trim it when finished. This implies the VI will have to always copy its inputs as not to alter data on the calling VIs wires. Pre-allocate an intersection array sized to the smaller of the two inputs. Trim when finished. Concatenate within a loop. Again, I'm banking on compiler optimizations and my use case that #3 is fastest. I'll have to look into ShaunR's idea, not sure how fast it will run (don't know much about that function). Also completely forgot about possibly parallelizing. Good idea!
×
×
  • Create New...

Important Information

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