Jump to content

Pass the Ref or pass the name?


Recommended Posts

I have a lot of code where I pass the Reference to the top level VI and many Queues, Notifiers, etc down to many sub VIs so they can interact with these elements.

I use the VI ref of the top caller to position dialog windows on top of the caller UI.

I use queues to pass data between parallel threads in producer/consumer architectures.

I also use singel element queues to store 'global' data and status so it can be used in many places.

For most of these, I do not name my queues/notifiers but instead create them in the top caller at init time and then pass the ref by wire to the sub vis. When all subvis are done and the top caller is exiting, I clean up all the refs before quitting.

Is this a smart way to do this? Another option is to give everything a name and then pass the names to the subvis instead. Then each sub-vi would have to do it's own 'obtain/open/etc' on the name to get the reference and the use it. Each sub-vi would also have to clean up it own copy of the ref before returning.

The plus is I would not be copiing the ref value each time I branch a wire and also each sub-vi would have it's own private copy of the ref instead of everyone using the same ref number for the underlying queue/VI/notifier/etc.

The minus is I would have to incure the cost of calling all the optain/open and release/close operations in every VI.

The reason I am considering this is due to a garbage collection/race condition bug in 8.5.1 that is causing a reference to be destoryed (rarely) when some instances of reentrant clones and copies of templates (VIT) are leaving memory.

I'm just wondering what the 'best practices' approach is to passing references and if I am going in the right direction.

Thanks for your ideas and opinions...

-John

Link to comment

QUOTE (jlokanis @ Jan 6 2009, 02:15 PM)

I don't think there's are true right and wrong way, but if you create all those objects at the top level and pass them down, you end up with an awful lot of wires.

On our team we use mostly named Qs/Ns so that they are globally available, and use unnamed objects only when necessary. We wrap the obtain (open) function in a subvi so that the name and the data type are only in one place. We only use a few of those, and many subvis take the Q/N reference as an input. Whether to pass with a wire or use the open function is mostly a judgment call.

QUOTE (jlokanis @ Jan 6 2009, 02:15 PM)

The plus is I would not be copiing the ref value each time I branch a wire and also each sub-vi would have it's own private copy of the ref instead of everyone using the same ref number for the underlying queue/VI/notifier/etc.

The minus is I would have to incure the cost of calling all the optain/open and release/close operations in every VI.

Honestly I don't think either of these matter at all. Copies of references are cheap and fast, and cleaning them up is easy. Obtaining a new reference is slower, but as long as you're not doing it in a tight loop, it's not a big deal. It's much more important to keep your code bug free (maintainable) and memory leak free (close all your references) than to worry about the performance of these references.

Link to comment

John,

I agree with jdunham - use named queues and notifiers. The overhead of getting/releasing references hasn't caused any problems for me (as long as I remember to close the ref nums - on a long running app you can leak a lot of memory a few bytes at a time :oops: ). I contributed some thoughts on this thread about why I like named queues. -they can really make your code very modular.

http://forums.lavag.org/VI-communication-b...&hl=mesmith

Mark

Link to comment

Thanks for the feedback. It sounds like the pass by name method might be more robust, if a slight bit slower.

Currently, I pass these refs to the sub vis inside a big typedef cluster. So, now I need to change all the data types to strings. As was pointed out in the linked thread above, there are lots of issue with reentrant VIs to worry about. I am alreayd looking at ways to make unique names for these items. The best way so far is to namespace them with the caller's VI Name (clone name).

-John

Link to comment

Note that you don't need to pass the names. You can just use the same logic to generate the name in each VI (or use constant names). If you're passing something, you might as well keep doing what you're doing now.

As the others suggested, I also prefer using a simple FGV to obtain references to shared resources. Essentially, the Get action usually checks the reference and if it's invalid closes and opens it again. Just note that if you're using dynamic VI calls you need to make sure that you create the reference in a hierarchy which will not be unloaded.

Link to comment

In my case, every hiarchy is dynamically created from the same template, so I still need to pass down the name of the VI created from the template as the 'namespace' so each obtain call can use that to generate the queue/notifier name.

A FGV would not work well in this case, but some sort of daemon that opens and maintains the queue's exisitance might work. This would mean I would have to call it to clean up when each hiarchy completed and was closing. This gets complicated if there are many different datatypes for each queue/notifier...

Leaving it as is (passing the actual reference) is not an option due to the bug in LV's garbage collection routine. So, untill that is fixed, I need to find a reasonable workaround.

-John

Link to comment

QUOTE (Ton @ Jan 7 2009, 12:42 PM)

please enlighten me on that.

Sure.

I spawn many VIs from a VIT and then inside of each of these VIs I create many queues and pass their refs to many reentrant sub-vis (obviously all VIs must be reentrant or each spawned VI from the VIT will block each other).

Then I run these VIs for a long time (days).

When one or more of them complete their work and close (even though I clean up all my refs on the way out) sometimes (1 out of 50-100x) the LV garbage collection will "accidentally" destroy one of the queue references in one of the other VIs spawned from the VIT that is still running.

I do not know if this is an issue due to the fact that the VI was spawned from a VIT or the fact that the sub-VIs are reentrant, but setting all the reentrant VIs to the shared clone mode exacerbates the problem.

This is a confirmed bug by NI support but it is very hard to reproduce so I do not know when it will be fixed. I have been working with NI on this for several months. I have seen it in both 8.5 and 8.5.1, under both the DEV and Runtime environments. I have not tried 8.6 yet.

-John

Link to comment

QUOTE (jlokanis @ Jan 7 2009, 08:41 PM)

A FGV would not work well in this case, but some sort of daemon that opens and maintains the queue's exisitance might work. This would mean I would have to call it to clean up when each hiarchy completed and was closing. This gets complicated if there are many different datatypes for each queue/notifier...

Use only one type of queues/notifieres - variant. You get additional opportunities with variant attributes.

Link to comment

QUOTE (jlokanis @ Jan 6 2009, 10:15 PM)

I'm just wondering what the 'best practices' approach is to passing references and if I am going in the right direction.

Thanks for your ideas and opinions...

-John

My 2c:

I am more inclined to create queues by name at the top then obtain the ref by name in the lower VI's delete each when done.

This is especially needed (I believe) when the VI is run using RUN method and waitfin set false.

I never create queues without names unless it is created and discarded inside the same VI.

ALthough it has not happened to me lately I do remember seeing behavior like you descrivbe in some of your earlier posts.

It seems to work fine as long as the top VI stays active.

As far as best practices I am not sure if it is or not.

end my 2c

Link to comment

QUOTE (vugie @ Jan 8 2009, 03:04 PM)

And performance issues (memory copies) and you lose the strict typing, so it's not as convenient and has more chance for bugs. I generally only use variants when I need to transfer different data types on the same wire.

QUOTE (TG @ Jan 8 2009, 08:17 PM)

I do remember seeing behavior like you descrivbe in some of your earlier posts.

It seems to work fine as long as the top VI stays active.

From the second sentence, I'm guessing you simply ran into the standard LabVIEW behavior regarding reference - a reference is automatically destroyed when the top level VI in the hierarchy where it was first created stops executing. In the case of named queues, each obtain is considered as a separate reference and the queue itself is not destroyed until all the references are destroyed.

Link to comment

QUOTE (Yair @ Jan 8 2009, 09:20 PM)

And performance issues (memory copies) and you lose the strict typing, so it's not as convenient and has more chance for bugs. I generally only use variants when I need to transfer different data types on the same wire.

Depends what kind of data is passed with q/n. But in general in fact it would be better to use FGV to store q/n references flattened to variant (to avoid many kinds of them).

Link to comment

If you're only storing the references as variants, then at least you don't have serious memory issues, but you still need to convert each variant to the proper type before using it and I find it to be too complicated unless the FGV code is really complex and you don't want to duplicate it for every data type. In that case, you can place a wrapper around it for each data type, but you will still have some performance issues.

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
Unfortunately, your content contains terms that we do not allow. Please edit your content to remove the highlighted words below.
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.