Delphi 2009 : TQueue<T>.Dequeue vs TObjectQueue<T>.Dequeue

I was poking around inside Generics.Collections the other day while writing some code for a future post on pooling, and I came up against something puzzling.

Generics.Collections has a class called TQueue<T>, which is a generic version of the classic first-in-first-out datastructure. The nice thing of course is that it can now be made type-safe by specifying a type parameter. If you’ve ever looked at a queue, such as the non-generic one that ships with Delphi already, or even thought about a queue datastructure, looking at TQueue<T> will not hold many surprises.

Generics.Collections also has a class called TObjectQueue<T>, which descends from TQueue<T> and adds object ownership (ie. the queue will destroy any objects it holds when you destroy it). This is implemented using an interesting looking notification process that probably deserves investigation in a future post, but again, the object ownership concept should be one many Delphi developers would be familiar with from TObjectList, etc, in previous versions of Delphi.

TQueue<T> has a function called Dequeue which returns the front item off the queue. The signature looks like this:

However, when I came to use TObjectQueue<T> its Dequeue method looks like this:


That’s right, a procedure. Internally it still takes the front item off the queue, in fact all it does is call the inherited TQueue<T>.Dequeue, but it doesn’t give it back to you.

I have to admit, my initial reaction to this was to assume I’d navigated to the wrong class so I went back to the starting point and walked my way through it again. Nope, still a procedure. No matter how I navigated to it, it wouldn’t turn into a function.

At this point I took the dogs for a walk and thought about it some more. When I got back, unfortunately, it was still a procedure. Further, after working through the notification code a little, it turns out that not only does TObjectQueue<T>.Dequeue take the front item off the queue and not give it back to you, it also Frees the item.

Now, I’d love to tell you that after careful examination of the rest of the code I discovered what was going on but that would be complete bollocks. Instead, I dashed off an email to Barry Kelly.

The answer comes down to the fact that because TObjectQueue<T> owns the objects, you need the ability to do two different things:

  • Remove the front item from the queue and have it automatically destroyed by its owner, the queue. Maybe this is after you’ve looked at it using Peek and decided you don’t want it. This is what TObjectQueue<T>.Dequeue is for.
  • Remove the front item from the queue, and have it returned to you. Part of this is that it will be removed from the queue’s ownership and it becomes your responsibility to free. This is what the method Extract is for, which to be honest I didn’t notice was there, and is in fact defined up on the TQueue<T> as well.

If you think about the names Dequeue vs Extract, this kind of makes sense. Some small part of me still finds it a little disconcerting that a function turns into a procedure between TQueue<T> and TObjectQueue<T>, but I’m mostly over it by now. Chances are if I’d stumbled upon Extract before Dequeue, none of this would have occurred. Anyway, I changed my pool code to use Extract instead of Dequeue, all my unit tests passed and I was free to go watch the Brisbane Broncos get robbed of a spot in the Rugby League finals.

Anyway, I hope this will help some future poor soul googling away to try and find out why Dequeue changes from a function to a procedure.


Join the Discussion

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code class="" title="" data-url=""> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong> <pre class="" title="" data-url=""> <span class="" title="" data-url="">