nicolasB Posted March 20, 2009 Report Share Posted March 20, 2009 I created a queue somewhere in my code and in a subvi somewhere else in my code I want to access this queue by its name (obtain queue.vi with Create if not found = False). This proceeding causes a memory leak. I know, that it's better programming style to wire the queue reference but the parameter Create if not found indicates that it should work. Attached is a small example which demonstrates the problem: Run both the AppWired.exe and the AppCreateIfNotFoundEqFalse.exe and control the memory usage in the task manager. Nicolas Quote Link to comment
jdunham Posted March 20, 2009 Report Share Posted March 20, 2009 QUOTE (nicolasB @ Mar 19 2009, 01:05 AM) I created a queue somewhere in my code and in a subvi somewhere else in my code I want to access this queue by its name (obtain queue.vi with Create if not found = False).This proceeding causes a memory leak. Well what causes the memory leak is that you keep obtaining new references to the queue and you never release them. It's perfectly acceptable to look up a queue by name. It's not as fast, of course, but if the wire is unavailable, then by all means use the name, and it's still pretty darn fast. But when you are done, you need to release the reference. The queue itself will not be destroyed until all its references have been released (or until your top-level VI stops executing). Your code should generally have a Release Queue call for every Obtain Queue. Quote Link to comment
ooth Posted March 20, 2009 Report Share Posted March 20, 2009 QUOTE (jdunham @ Mar 19 2009, 05:49 AM) Your code should generally have a Release Queue call for every Obtain Queue. Does this also apply to Notifiers? Quote Link to comment
LAVA 1.0 Content Posted March 20, 2009 Report Share Posted March 20, 2009 QUOTE (ooth @ Mar 19 2009, 12:39 PM) Does this also apply to Notifiers? Yes. And for Rendezvous and semaphore. Ton Quote Link to comment
Ale914 Posted March 20, 2009 Report Share Posted March 20, 2009 yes true i know very well this behaviour but from my point of view is a mess i mean if i say Create if not found = False is pretty clear that i want the reference of the queue having a certain name i was supposing that Obtain queue have an access to a sort of reference repository and search and return the ref. by name or create a new one if Create if not found = True. I really don't understand the value of this behaviour. Quote Link to comment
jdunham Posted March 20, 2009 Report Share Posted March 20, 2009 QUOTE (Ale914 @ Mar 19 2009, 05:34 AM) yes true i know very well this behaviour but from my point of view is a mess i mean if i say Create if not found = False is pretty clear that i want the reference of the queue having a certain name i was supposing that Obtain queue have an access to a sort of reference repository and search and return the ref. by name or create a new one if Create if not found = True.I really don't understand the value of this behaviour. Well first off, I want to say that after having used queues and notifiers in a lot of different ways, I came to realize that the design of Obtain Queue is excellent. Its behavior makes a lot of different use cases possible, though I don't really have time to write more now. Maybe if I ever start that blog... What you have to understand is that a queue reference is different than a queue. A queue is a by-reference object, so that it doesn't get copied for every branch of its wire, which would be a nightmare. But the wire has to have some contents, which is a reference (a 'pointer' inasmuch as LabVIEW has pointers, which it doesn't) to the actual queue. So the Obtain function returns a queue reference. It also has automatic behavior that if the queue itself doesn't exist, it's automatically created. Occasionally you don't want that automatic behavior, so "Create if not found"=F lets you turn that off. So any time you open/obtain reference to a named queue, you get a different by-value copy of the reference which points to the same queue. The queue has the neat but sensible property that when all references to it have been release, the queue itself is destroyed. This is usually called reference-counting. Of course the Force Destroy? input is a way to get around that and destroy the queue without cleaning up all the open references. You should only use Force Destroy=T if you have a good reason. It's cool because the reference which first creates the queue doesn't have to be the one that cleans it up. The queue will exist as long as any caller needs it, and it will clean itself up automatically when the reference counting system detects that any interested callers have lost interest. So I guess what I'm saying is that Ale914 is totally right, and I tried to explain why he's right and why it's not a problem, and I'm not sure whether I've succeeded, because I don't fully understand the confusion. EDIT: So the fact that you can look up queues by name (which is useful) has almost nothing to do with the fact that there's a reference-counting system (which is also useful). The lookup system works as you'd expect, and the reference-counting is supposed to be an internal implementation detail which you never worry about and which always works as long as you always call Release once for every time you call Obtain. Even that rule can be ignored as long as you don't call the Obtain function a kajillion times without releasing (which is what the OP did). For the original poster, you probably don't need to obtain a queue reference on every call or every time through the loop. Often you can obtain the queue reference just once per thread and stuff it in a shift register (or feedback node, same thing), and then it is always available where you need it. It's still good style to close it, but even without doing so you probably wouldn't be leaking memory. Quote Link to comment
nicolasB Posted March 21, 2009 Author Report Share Posted March 21, 2009 QUOTE (jdunham @ Mar 19 2009, 10:49 AM) Well what causes the memory leak is that you keep obtaining new references to the queue and you never release them. It's perfectly acceptable to look up a queue by name. It's not as fast, of course, but if the wire is unavailable, then by all means use the name, and it's still pretty darn fast. But when you are done, you need to release the reference. The queue itself will not be destroyed until all its references have been released (or until your top-level VI stops executing). Your code should generally have a Release Queue call for every Obtain Queue. Hi jdunham, thanks for the explanation. With this knowledge it makes sense and could be a useful functionality! regards, Nicolas Quote Link to comment
Recommended Posts
Join the conversation
You can post now and register later. If you have an account, sign in now to post with your account.