-
Posts
1,824 -
Joined
-
Last visited
-
Days Won
83
Content Type
Profiles
Forums
Downloads
Gallery
Everything posted by Daklu
-
Non-zero default values for reference types
Daklu replied to Tomi Maila's topic in Object-Oriented Programming
Nope, but let me emphasize vaguely. I could be imagining it. Yes, but not without changing the current behavior and potentially breaking lots of customer applications. Currently, as near as I can tell, there's not much reason to wire to the dynamic events terminal on the right side of the structure for normal use cases. You don't need to wire it up after dynamically registering or unregistering an event. This code works. Should it work? Probably not, according to data flow rules. The event reg refnum value just inside the while loop is zero when the vi is started. After the event is registered it is magically given a valid refnum value in clear violation of data flow. How does it work? I'm not sure. Maybe there is some invisible wiring going on behind the scenes. There's definitely weird things happening. For example adding this event handler doesn't affect the behavior. But changing it to this prevents the refnum at the left side event terminal input from changing to a valid refnum, even though this event isn't invoked... ...unless I add shift registers, which fixes the behavior again. And through all of these changes the event reg refnum here was never wired through. --------------------- To add a little more to this puzzle, I created a typedef for the event reg refnum and this code follows data flow rules. Refnums 1, 3, and 4 match and remain constant. Refnum 2 changes every time the vi is run. Unfortunately, making the same change in the Event accessor didn't change the behavior you're seeing in Main VI. Event Registration Test.zip -
Non-zero default values for reference types
Daklu replied to Tomi Maila's topic in Object-Oriented Programming
Here's another quick test I did illustrating the global-ish nature of Event Registration Refnums: Refnum 3 and Refnum 4 match the value of Refnum 2, even though there's no reason -- according to ordinary data flow rules -- for that to occur. Now that I think about it I understand why this is happening. My guess is that it's an unintended consequence of making it easier to use dynamic event registration. When we have an event structure with a dynamic events terminal, we don't have to propogate the event reg refnum wire through all the event cases. We only need to wire it up when dynamically registering/unregistering an event. For that to work the event reg refnum wire *has* to violate normal data flow rules. In essence, the refnum has to behave like a global, at least on any single block diagram. I vaguely recall someone mentioning that event reg refnums are intended to be used only on block diagrams that service the event. That's part of the reason I gave up on them in my frameworks. -
Non-zero default values for reference types
Daklu replied to Tomi Maila's topic in Object-Oriented Programming
For some reason the event reg refnum control is being treated as a global. That's why the constant doesn't appear to be constant. I ran this block diagram with Retain Wire Values turned on. After execution finished, I removed and reprobed one of the class constant wires. The refnum value changed to the value output by the Reg Events prim. This is definitely a case of a downstream operation changing an upstream value. (FWIW I had all sorts of problems a while back when I was exploring using user events as an integral part of application architectures. Eventually I gave up and switched to using queues almost exclusively.) -
I wouldn't think talking about existing bugs meets the definition of "disparaging," but I'm not a lawyer so I can't say. Anyway, I don't think they have a legal basis to prevent anyone from linking to their website, regardless of the link source's content.
-
Several of the posters appeared to be college-aged kids and, like nearly all college-aged kids, possess an abundance of ideology and a noticable lack of real world experience. Perhaps someday they'll understand the "real programming" != "imperative programming." Most industry vets I encounter readily acknowledge that each language has domains it works well in and domains it doesn't work well in, even though almost everyone has a preference.
-
I'm assuming "edited during load" and "tagged dirty" are interchangable. Are there cases where there are not? Will do. Thanks for the feedback.
-
-
Thanks Stephen! That really helps fill in the missing pieces. (I've never seen this information in a white paper. Do you know if one exists?) Say you're editing a typedef cluster and all the dependent LC blocks are loaded, but their FP/BD's are not. When the typedef's changes are applied, LV finds all the dependent vis, loads the block diagrams, and makes the necessary edits transparently to the user. (i.e. Without opening windows to the block diagrams.) Since the dependent vis are now dirty their FPs are also loaded into memory, forcing data copies for those FP controls when the app is executed, even though the FP windows aren't open, right? Does this behavior change when separating compiled code in LV10? My initial thought is that LV ought to be able to recompile the dependent vi's source code and remove the FP/BD from memory without marking them dirty, and simply wait until the user opens that vi before giving it a dirty dot. But that could lead to confusing behavior when multiple typedef changes are applied sequentially (like what happens when a vi's LC block isn't loaded when changes are applied) so I'm guessing no. The one open question I still don't have an answer to is why does the FP have to be loaded when the BD loaded? My previous explanation got blown away and now I'm really curious. I created a flow chart to graphically represent what you described. If it's accurate enough I'll throw it up on the wiki. (OpenOffice source file attached in case anyone wants to edit it.) LoadingLabviewVI.zip
-
Okay, I need to have a long talk with Evil AQ again...
-
[CR] By Ref Active Object Framework
Daklu replied to Kurt Friday's topic in Code Repository (Certified)
Kurt has been MIA for quite some time, so while I wouldn't presume to speak for him I'll take a stab at answering your questions. Probably not, but for the sake of simplicity lots of error checking and whatnot is usually left out of code when the purpose is to illustrate a specific concept. Hmm... can't really answer that without defining what the system behavior should be when the Pump Volume button is pressed while the pump is running. Should the button tell the system that regardless of where it is or what it's doing now, it should pump x additional volume then stop (restarting the process with the new endpoint), or should it overwrite the current Volume to Pump value (continuing the same process but replacing the endpoint), or should it ignore the message altogether? You can get part of the way towards the first definition by removing the state boolean check inside the 'pumpvol' case, though that single change causes the Volume Pumped indicator to reset, so there's more work that needs to be done. I didn't explore implementing the other definitions. In general terms your question is 'how do we make sure the system remains robust when it receives unexpected messages?' Disabling front panel controls to prevent messages from being sent is one way to approach it, though I don't particularly like that technique. IMO it's much better to build message filtering into the system itself rather than require the clients to pre-filter the messages before sending them. But this question is not really related to Kurt's framework, so if you want to discuss it more it would be better to start a new topic. -
Ahh... that explains a lot of my confusion with load behavior over the years. Thanks. (Just to clarify, we are talking about the source code block, right?)
-
Here's some grist for the rumor mill... Somewhere along the line, possibly when installing LV10, I saw a reference to Microsoft Silverlight. It might have been a EULA. I didn't think too much about it at the time, but at our local user group meeting last week the sales rep mentioned R&D is working on some sort of Silverlight integration for a future Labview release. I'm sure it's at least a couple versions down the road, but it's nice to hear NI is trying to address the UI problems.
-
What a coincidence--I've recently been wondering about the cost of boxing/unboxing native types in classes versus clusters. Thanks for reviving the thread and the update on the bug. This comment brings to mind a couple questions... 1. My understanding was that, in memory, a vi's code exists in the front panel and the block diagram is simply a visual representation of the code. That's why we can't close the front panel window but keep the block diagram open. In other words, having the vi loaded by definition means the front panel is loaded. If the accessor method is being used in the test code, isn't it loaded into memory regardless of whether the front panel is open? 2. I take it Save All does a memory sweep and removes those things that are not needed at the moment? Would we get a different outcome if we were to save (not Save All) and close the front panel of each vi individually? Is it valid to consider Save All as a 'soft reset' of sorts, meaning it puts the dev environment memory in the same state as if we had closed LV and reopened it with all the same FPs and BDs visible? (I'm thinking of memory state as what is loaded, not where it is loaded, which obviously would probably change if LV were restarted.) Does Save All behave have a different effect if selected from the project window versus an individual vi? (I'd assume not, but you never know...)
-
Re-use and hierarchy strategy
Daklu replied to InsaneObject's topic in Application Design & Architecture
I'll second what Jason and JG said. Package your reusable code in VIPM packages and distribute it to yourself. You'll save yourself headaches in the future. A couple other thoughts... -I put all my reusable code in lvlibs. It makes the whole process much easier. -Keep the public api simple. Avoid the urge to include every feature someone might want to use. That makes the api harder to understand and use. Instead, try to give users the ability to create the functionality they might need, within the scope of what the library addresses. It's much easier to add to an api than it is to subtract from it. -Figure out how you're going to manage changes that break backwards compatibility. (Yes, the golden rule is "never break backwards compatibility," but that rule ignores other real world issues.) If you give the breaking changes a new namespace (for instance, renaming the containing lvlib as v2) then upgrading an app from v1 to v2 is kind of a pain, but you have the advantage of being able to have both versions installed at the same time. If you don't give it a new namespace you have to choose one or the other and run the risk of accidentally editing a project that is supposed to use v1 when you actually have v2 installed in your dev environment. Each has it's advantages, the choice is yours. -Once you release a library you're committed to supporting it. I give my reuse libraries "trial runs" via copy and paste in a couple different projects before I create packages for it. This gives me an opportunity to see how well it works under slightly different user scenarios. I almost never get the api right the first time and the trial runs highlight problems with the initial api design and gives me the opportunity to improve it. Nothing is worse than issuing a release then discovering a use case you can't address without breaking backwards compatibility. -
Consequences of unreliable run method
Daklu replied to Mads's topic in Application Design & Architecture
I wasn't aware of this issue. Thanks for pointing it out! Have a round of on me! I've noticed the unresponsiveness before but never understood why it was happening. I'm not that familiar with OS technology but I guess I'm a little surprised the OS as a whole is either in kernal mode or user mode. I would have thought that would be defined by each process. -
Long range shooting interests me but currently my only long guns are a pair of .22 rifles. (Marlin 795 and Henry lever action youth.) Needless to say, they're not allowed on the 600 yard range at my club. I've been leaning towards a bolt action .223, mainly because ammo is relatively inexpensive and it has a pretty flat trajectory. I don't plan on doing any deer hunting, but I'd like to do some varminting. (Probably ground squirrels and the like.) Do you have any thoughts on a decent gun for someone new to distance shooting?
-
Touche! But I don't think that works. The substitution is only valid if the set of people who are alright is equal to the set of people who are from Australia. JG's comment doesn't say 'Australians are the only people who are alright.' It says, 'people from Australia are alright,' implying Australians are a fully contained subset of all the people who are alright. According the premise, it's possible to be alright and not be Australian. But that doesn't satisfy my wish. My wish is to be Australian. Being alright is just a fortunate side effect of being Australian.
-
Yeah, my response wasn't very clear. Reading it this morning it took me a few minutes to figure out what I was talking about. It must have been after the stupid hour when I posted that. I meant to say that in the case of a stateless, non-inheritable class, leaving the class terminals in place could be more more confusing that not having any class terminals on the methods, because of the inherent expectation of class state. Using a project library is obviously preferable, but if changing the namespace introduces too much risk I wouldn't feel bad about using that particular shortcut. FWIW, when I do have public, non-overridable class methods that don't use the class data, I'll tag the terminal "Recommended." The terminals are there simply to help keep the wiring clean. I reserve "Optional" for 'special case' inputs that are rarely needed. I'm not sure if I've had public methods without class terminals. If so it doesn't occur often. Protected or community methods without class terminals is much more common. (And private, but that's hardly even worth parenthetically mentioning.) For example, sometimes I have a predefined set of error codes/descriptions that I want to make available to child classes. To do that I create a protected RaiseError.vi with a connector pane similar to Error Cluster From Error Code.vi. This doesn't apply to Jack's question since he specified no inheritance, but I brought it up to illustrate there are valid use cases for methods without class terminals.
-
What if we just wish we grew up or lived in Australia?
-
Wow. That's really... creepy.
-
Good news for .223 fans who worry about rampaging mobs of angry books that line up in neat rows. In my experience book mobs rarely line up for a convenient multi-kill shot--they tend to flop around flapping their covers trying to make as much noise as possible. Maybe they behave differently on your side of the country. Mythbusters had an episode recently where they were testing to see if they could create an armored car using phone books. Putting a sheet of glass in front of the books makes them much more effective as stopping bullets. So if you're going to the library and are concerned about armed lunatics, take a piece of tempered glass with you. It might just save your life.
-
Personally... no. I typically know going into my design whether some chunk of related functions is going to be a class or a library. I read the question as, "If I leave it as a class but don't need state data or inheritance, is it inelegant or misleading to have class terminals on the methods?" To that I'd answer it's probably inelegant but not necessarily misleading. It could be *more* misleading to use class terminals with an object that doesn't maintain state data. A lot of it depends on the class name, the methods' names, documentation, etc. I have implemented class methods that simply pass class data through untouched as well as methods that don't have class terminals on them. In any event, it sounds like you made the right decision.
-
You mentioned "demoting," implying you have already implemented the classes. In that case, I probably wouldn't bother converting them to a lvlib unless there are specific performance issues you are concerned about. If it's not buying you anything, don't spend time on it. Just make a mental note for future dev work. Felix raised a good point. There's no inheritance now, but what about in the future? If you can envision a scenario where you might want to override a function in the library, it may be better to leave it as a class even if there's no state data associated with it.
-
My bad LV habits acknowledged, a short list
Daklu replied to MoldySpaghetti's topic in LabVIEW General
Only 6 db? Over the ear muffs and in-canal plugs each typically offer ~20 db reduction don't they? Silence is impossible, so I use background noise to drown out distractions. Usually it's music, but I also have a generator that produces various continuous sounds designed to sooth: Ocean waves, babbling brook, gentle rain shower, Nascar racing, power drills, crying babies... stuff like that.