A bit of code is worth a thousand words. I have attached the templates I use to create a standard reference object. These are written in LabVIEW 7.1. Use the In Place element to access the data elements if you have LabVIEW 8.5+. The code does not answer all your questions, however.- Setting the size does give you a bit of an optimization due to all element allocation occurring at queue initialization. However, in practice, this is meaningless if you always use only one element. I set the size to one element to make the object as robust as possible. I write infrastructure code that is used by programmers of many experience levels, so try to make things as easy as I can. It also helps keep me honest :smileyvery-happy:
- See the attached code for a write (I call it a "set"). It is guaranteed to be atomic because nothing else can access the data since it is temporarily out of the queue.
- I have always used infinite timeouts for the queues. I can easily envision situations where you would not want to do that, but have never run into one. Note that the destroy VI does a force destroy, causing all get/set VIs which are waiting on data to immediately run with an error. If your program is designed well, either this will not happen or the program will expect the error and use it to take appropriate action (e.g. exit, abort, &c.).
- If you fail to enqueue after a dequeue, it will cause a hang/timeout the next time an enqueue is requested. The easiest way to deal with this problem is to directly connect the error wire from the dequeue into the enqueue. Placing anything else between them will cause problems. You can combine errors at the end of the VI. I often isolate the error in/out of the enqueue/dequeue from the rest of the error flow until the end of the containing VI.
- If the dequeue produces an error, it did not dequeue data (you get a default data set). I can not think of any situation where you would want to enqueue data under that situation. A bad queue reference will simply produce another error. An input error to the dequeue means the data was not dequeued, so an enqueue will hang/timeout or cause a pending operation elsewhere to hang/timeout. A force quit will cause the dequeue to error, but there is no queue any more, so an enqueue is pointless. Run the error wire directly from the dequeue to the enqueue and it will automatically take care of most circumstances. Note you should only enqueue if the dequeue did not time out.
- Notifiers always make a copy for every reader and do not guarantee delivery. As implemented, with infinite timeouts, once the queue is empty, all other readers will wait until the enqueue occurs. No matter how long it takes, the process is atomic. Data copies are up to the programmer. Once the data is dequeued, it is possible to make many copies before passing one back to the enqueue. As mentioned above, the In Place element helps, but users of pre-8.5 LabVIEW can use the cluster "magic pattern" to reduce copies. Despite what the buffer viewer says, there really is no copy made when dequeueing the data. This is why the queue is such a good reference object.
Hopefully I answered your questions. If not, let me know...
VI Reference Class.zip:
http://forums.ni.com/attachments/ni/170/345908/1/VI Reference Class.zip