Jump to content

Terminate and Stay Resident


Recommended Posts

I have a VI which is an "action engine", i.e., it contains LV2 style global variables in uninitialized shift registers. The VI works fine unless I decide to load it dynamically using the VI server. Unfortunately it also dynamically unloads the VI when it finishes. Thus its memory is destroyed. Is there any way to load a vi with the VI server and keep it in memory when it is done? To make LV treat it as if it had been placed on a diagram as a regular sub-vi (called or not)? I do notice that the VI server will call execute and return from my vi with everything working fine and retaining the global memory, if I also have the vi loaded statically as a sub vi somewhere.

Link to comment

If I recall correctly, you need to have the dynamically called vi call a reference to itself (and don't close that reference until you don't need the vi in memory). That will keep it in memory even if it finishes execution and the front panel closes (or is never opened)

Link to comment
I have a VI which is an "action engine", i.e., it contains LV2 style global variables in uninitialized shift registers. The VI works fine unless I decide to load it dynamically using the VI server. Unfortunately it also dynamically unloads the VI when it finishes. Thus its memory is destroyed. Is there any way to load a vi with the VI server and keep it in memory when it is done? To make LV treat it as if it had been placed on a diagram as a regular sub-vi (called or not)?  I do notice that the VI server will call execute and return from my vi with everything working fine and retaining the global memory, if I also have the vi loaded statically as a sub vi somewhere.

4697[/snapback]

i do the following (e.g. when working with subpanels):

in the calling vi i open references to the dynamically loaded vis and collect them into an array of vi-references.

i call the dynamiv VIs via the "run vi" method, not via the "call by reference node". they terminate themselfes or are terminated by an occurrence.

at the "run vi" method i choose "auto dispose refnums" = FALSE, because i close the refnums at the end of the calling vi.

that works fine 4 me !?

best regards,

cb

Link to comment

:headbang:

dear mesmith.

I tried making a reference to the called vi from within the called vi. LV complains about doing recursive calls. I don't think making the VI reentrant will work as a LV2 style global. I tried passing in the reference from the calling vi and stashing that in an unitialized shift register, but that doesn't work either.

:headbang:

dear cb,

I tried that too but when the calling VI stops its execution (stops running), the called VI is dynamically, immediately and most decidedly unloaded. The uninitialized shift registers in it instantly forget that they ever had anything in them.

Any other suggestions? Anybody want me to post a simple example of what doesn't work?

ConawayNY

Link to comment
  • 4 weeks later...
:headbang:

dear mesmith.

I tried making a reference to the called vi from within the called vi. LV complains about doing recursive calls. I don't think making the VI reentrant will work as a LV2 style global. I tried passing in the reference from the calling vi and stashing that in an unitialized shift register, but that doesn't work either.

:headbang:

dear cb,

I tried that too but when the calling VI stops its execution (stops running), the called VI is dynamically, immediately  and most decidedly unloaded. The uninitialized shift registers in it instantly forget that they ever had anything in them.

Any other suggestions?  Anybody want me to post a simple example of what doesn't work?

ConawayNY

4733[/snapback]

Create a reference to itself by using 'Open VI Reference" with 'Current VI's Path' wired into the 'VI Path' terminal. Store the generated reference in a shift register until you're ready to close it.

Sparc

Link to comment

post-1941-1117558290.jpg?width=400

post-1941-1117559275.jpg?width=400

dear Sparc,

That doesn't really work.

Beware when you reference the VI!

If you use a "Static VI Reference" from the Application Control Palette

that is just the same as if you had laid down the icon to the VI itself.

That is a static reference. It loads the target vi when the caller loads.

What you probably miss is the true dynamic nature of what we have been attempting,

and that is to choose which of several similar Action Engine vis with the same type to use.

Instead of the static vi reference, use just a "type specifier VI Refnum (for type only)"

as shown in the attached .jpg clip.

You will find it won't work. Nice try though.

Paul

4900[/snapback]

Download File:post-1232-1118091909.zip

Show me where I said "Use a 'Static VI Reference'" and I'll show you your mistake.

Take the example .zip, only open "exe.vi" and run it. You'll see the counter increment. Close the VI. Re-open it and re-run it, you find that the counter is still incrementing.

It's left as a task to the reader to implement a clean way of shutting down the tsr.vi. :)

Sparc

Link to comment

Sparc,

Well I'll be durned! It does work just as you suggest. But I see that the TSR part never does the T. It keeps running continuously. As soon as it quits executing, it is unloaded from the allocation heap and every shift register it contained is silently flushed down the bit bucket. Furthermore the response time of your TSR is of course linked to the loop cycle time. To be a good well behaved action engine, or a LV2 style functional global, I think it might be nice to just let it stay resident (the SR) in memory and only execute it when needed. [the original problem]

Another clue is that queues (or notifiers etc.) have no life outside of some executing vi. One cannot put something into a queue then stop execution, and expect that something to be there later on. Some VI containing the queue must be executing continuously to keep it alive. The queue does not need to be accessed, just present in an executing VI.

There is one obvious way to get around all this, and it may have some usefulness. That is to go ahead and build the action engine, but don't use a "run once" while loop with uninitialized shift registers. Simply use normal (LV6) style globals for any data retention across time. Then the VI can be dynamically called when needed, and unloaded when finished. The only requirement for this is that the global VI, the VI defining all the global variables, must be statically loaded. For example one of the global variables must be accessed in a top level VI. The memory cost for keeping a handful of variables around is only a small fraction of what would be needed for the dynamically loaded VI. And neither the caller nor the called VI need to stay running.

Paul

Link to comment

The example wasn't meant to be a perfect implementation of your Action Engine, just an example that a VI could be loaded in to memory, without a Front Panel and you could access it remotely. No, it doesn't truely terminate and given the constraints of LabVIEW, it never will and keep the behaviour you want.

Do note that a VI ca run to termination and not unload as long as something has an open reference to it.

Also, a loop that is waiting on a queue element, notification, or an occurance consumes almost no CPU cycles.

Maybe, with a little revision, you can use these ideas to make your Action Engine.

Sparc

Link to comment

Sparc,

Yes, I played around with several architectures before I came to the realization that VI server puts its stuff in a different place than the regular load and run VIs. The "action engine" design pattern served a useful purpose for the problem for which it was made to solve. When I took it and tried to extend it to Dynamic loading, that is where it all fell apart. Like you say it can't be done. But all this mental exercise is fun none the less. I know I could do something like it using Forth, but my boss would just choke if I suggested we put in a Commodore 64 or a CoCo into a new test fixture. :)

Thanks for the conversations,

Paul

Link to comment

Franz,

I opened your examples, converted them to Version 7.1 and ran them.

Main1 and Main2 exhibit the behaviors I would expect.

Main3 does not seem to act any better.

For the time while Main 3 is executing, Resident USR is in memory and functioning. USR Hook however does not seem to have been called. It does not show up on the Profile VI table as being in memory at any rate. I only see Main3.vi and Resident USR.vi. Hence as soon as Main3 stops execution, Resident USR.vi goes away.

Well, now I take that back. I put a breakpoint inside the part that launches USR Hook. That hit as expected. I took the breakpoint out and tried it all again from a clean launch of LV. Now it works as advertised. Both Resident USR.vi and USR Hook.vi are loaded and appear in the VI Profile list. They stay around even if I stop Main3

or abort Main3 or even close Main3. This is the action I was looking for. (I wonder why it didn't work on my first try?)

Thanks

Paul

Link to comment

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.