Jump to content

Dynamic dispatch & Shared reentrancy


Recommended Posts

Like I said, I rarely use queues by name, but that will certainly break the existing behavior where LV can keep the queue alive in different hierarchies because it has separate references. Doesn't sound like progress to me. If all you care about is cleaning up, why not just use the force destroy input?

I have a solution. It works. It even worked  when the force destroy was just reserved for future use in 2009 (although you still seem to be missing the leaking point). As I said previously. We didn't used to have to worry about memory management until queues et. al were introduced - which is where we started with this little rabbit hole..

Edited by ShaunR
Link to post

 Amen. But I would argue they are not exceptions. The maxim is "never use re-entrant memory storage" and all those you describe are not re-entrant (well, FPGA might be-I don't really know what you are referring to there). I wouldn't go as far as say "never store state in a VI" otherwise you are back to global and local variables and those you list were invented to address the issues with those memory storage methods.

For FPGA most everything is reentrant but really I'm referring to things like delay, rising edge, etc. functions which store previous state in a feedback node. This would cause a problem if you made any such function non-reentrant but this isn't the default.

But...I actually do mean going to the extreme of never storing state in a VI except in these special cases -- with DVRs I don't think an uninitialized shift register is really appropriate anymore. For the analysis functions I don't think there was ever a need to store state inside--they're math functions!

 

Sure. Obtain returns the actual queue reference rather than a copy.

Or they could go even further and make any branch perform a ref count, then deallocate the refs as soon as the last calling VI with that branch of the wire goes idle...you know like when it frees all that memory in your 5M element array ;)

Link to post

Or they could go even further and make any branch perform a ref count, then deallocate the refs as soon as the last calling VI with that branch of the wire goes idle...you know like when it frees all that memory in your 5M element array ;)

make-it-so_2.jpg

  • Like 1
Link to post

Sure. Obtain returns the actual queue reference rather than a copy.

 

I don't care so much about the separate references (I assume that while you have no desire to leak four bytes, that's not the major concern), but I do want LV to nicely and automatically manage the memory. I expect that the most likely action that NI would take in this area would be to relax the "owning hierarchy" rule and to add internal refcounting so that resources are not released when their creating hierarchy goes idle, but when the last hierarchy using them goes idle. I'm not sure if this will or will not help with your dissatisfaction here. It would mean you don't have to worry about it, but it probably means there are more chances for stuff to stay allocated because LV will now require more things to happen before it destroys them automatically.

Link to post

Only if you store state inside of your VIs, which I personally think is a bad idea with a few exceptions (FPGA, action engine operating on a singleton resource, etc). Pure math functions are certainly not on the list.

 

I actually do mean going to the extreme of never storing state in a VI except in these special cases -- with DVRs I don't think an uninitialized shift register is really appropriate anymore. For the analysis functions I don't think there was ever a need to store state inside--they're math functions!

 

Why do so many NI signal processing VIs use uninit shift register so ?

 

 That's why  this is such a problem for people. Re-entrancy is meant for non-blocking parallel execution. Using it as a memory storage method is just an abuse of its apparent behaviour.

 

I agree with you ShaunR, more than 100% !!!

 

In my code I relatively rarely need parallel execution and more commonly want copies which will maintain state (some dynamic and some static). Classic preallocate reentrancy does that (with some exceptions). Both use cases are valid.

 

The use case might be valid or functionnal, it doesn't justify that it is a proper way to do or a good design pattern. I completely disagree with you about this question : reentrancy is made for parallel execution not storage. I have never seen any other programming language which promotes storage in static variables inside functions.

 

Unfortunately in case of LVPOO preallocated reentrancy is not allowed, so not valid for me.

Link to post

Why do so many NI signal processing VIs use uninit shift register so ?

 

Because they were written when it was the only way to do this kind of thing. Remember. It is only a problem with Shared re-entrant just don't set your methods to shared re-entrant and it will work as expected. The easy way out for NI is for LabVIEW to break the VI if you try and set shared clones when calling a pre-allocated re-entrant VI the same as they do with subroutines.

Link to post

reentrancy is made for parallel execution not storage.

 

Again, citation needed. If you're going to claim a certain feature was designed for purpose X, show it. Like I said, even if you do show it, that doesn't negate the usefulness of storing state.

 

There are many many cases of where state is useful in a reentrant VI. For example, a value changed? VI is useful - you feed it a value and if it changed from the last run, it will output true. Any kind of actor requires state to be stored somewhere and actors are often reentrant, because you can multiple actors of the same type. For those applications, you want state, which means preallocation. That's my primary use case for reentrancy. The VIs may execute in parallel (actors/daemons certainly tend to, since they're long running), but they also need state.

 

If you do this, you do need to be aware of how preallocated clones are actually allocated, because otherwise, you can get shared instances where you expected to have separate ones, as I mentioned before.

Edited by Yair
Link to post

Again, citation needed. If you're going to claim a certain feature was designed for purpose X, show it. Like I said, even if you do show it, that doesn't negate the usefulness of storing state.

 

In computing, a computer program or subroutine is called reentrant if it can be interrupted in the middle of its execution and then safely called again ("re-entered") before its previous invocations complete execution.

 

Rules for reentrancy:

Reentrant code may not hold any static (or global) non-constant data.

Reentrant code may not modify its own code.

Reentrant code may not call non-reentrant computer programs or routines.

 

Citaton given. Can we please move on now?

Edited by ShaunR
  • Like 1
Link to post

Citaton given. Can we please move on now?

 

Sure. All that tells me is that the definition of reentrant in LV is different from what's used in that context, so it's even less relevant than I thought (and to be clear, I don't think it's particularly relevant, because what's important is functionality, not original intent or terminology. You are those who insist that "reentrancy is for concurrency", which is a word which in that article is only mentioned once, to demonstrate a race condition with global data, which doesn't apply to local state in any way).

Link to post

Rules for reentrancy:

Reentrant code may not hold any static (or global) non-constant data.

I think the “static†data they are referring to there is accessible from every call to the function, thus it would not be safe reentrantly call the function.  But LabVIEW reentrant have separate data spaces, and don’t share data between reentrant calls.

Link to post

Because they were written when it was the only way to do this kind of thing. Remember. It is only a problem with Shared re-entrant just don't set your methods to shared re-entrant and it will work as expected.

 

Because I am not all of NI...I'm not even in R&D. :)

 

Off course smithd I know. My sentence was more a question asking for any explanations from a NI / official person. I'm pretty much young user of Labview. I haven't been lucky to experience the first versions of LV.

 

Based on what I can read, the main reason seems to be that it would be a long and hudge pain to change everything now. Just to let you know guys, I have received an information from the Sound and Vibration toolkit development team. This update is only about embedded subpalette of the toolkit, but maybe we can expect (or hope) that the initiative will go up to update the whole toolkit and all (or most) the signal processing VIs ?!

 

 

In SVMS 2015 this feature was added in response to requests from Systems Engineering. For a subset of functionality found in the Embedded Monitoring subpalette, the SV Dev team addressed advanced usage in OOP applications by adding instances of analysis VIs that pass state (including initial and final conditions) through the VI. These (* With IC) instances are safe to call in Shared Clone Reentrant VIs (such as those required by Dynamic Dispatch VIs in LabVIEW

 

 

There are many many cases of where state is useful in a reentrant VI.

 

Yeah sure it is usefull and fast code. But I think the problem is this "easy to use" feature is not all the time compatible with complex systems.

 

If you do this, you do need to be aware of how preallocated clones are actually allocated, because otherwise, you can get shared instances where you expected to have separate ones, as I mentioned before.

 

I'm aware, but Labview doesn't allow any other possibility if I use POO & Dynamic Dispatch. So I consider both incompatibles.

Link to post

Yeah sure it is usefull and fast code. But I think the problem is this "easy to use" feature is not all the time compatible with complex systems.

 

So you're basically saying "complexity is complex". LV does a fairly good job of allowing you to write parallel code which at least doesn't crash and has all the safety mutexes. It doesn't guarantee that every piece of code you write will function correctly. For that, you have to work within the rules of the system and sometimes those rules have odd corners. Sometimes this is by design ("that's the best we can do"), sometimes by accident ("oops, we didn't think of that" or "there are two separate rule systems and now that they interact they produce a weird result").

 

 

I'm aware, but Labview doesn't allow any other possibility if I use POO & Dynamic Dispatch. So I consider both incompatibles.

 

I'm not sure if it was strictly necessary to forbid preac clones for DD. Maybe it would have been possible to say "each class will get its own instance of the clone at run time". Maybe NI didn't do it because they considered it to be too confusing or because it would have been too much work or because they didn't have time before release or because they thought that the need for it would be minimal or because there are bugs in there which I didn't think of. The bottom line is that they made their choice and the result is that you can't correctly use static preac VIs which hold state in DD VIs which don't run over a long time. In that sense, yes, they are incompatible.

Link to post

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

×
×
  • Create New...

Important Information

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