Archive for the ‘Class Helpers’ Category.

TThreadedQueue: interesting, but incomplete

I mentioned the new generic collection TThreadedQueue<T> in my First Look at Delphi XE. I decided to play around with it a little recently.  It’s useful for passing data between one thread that produces output and another that consumes it, keeping the two in step by blocking if the consumer tries to pop from the queue while it’s empty.

The first thread goes through and pushes data into the queue however it wants to.  The second has it easy; all it has to do is loop endlessly until the queue is shut down.  And we all know how to do that:

for value in queue do
  process(value);

Except that if you try to do that, the compiler will complain at you.  There’s no enumerator.  For some strange reason, out of all the collections in Generics.Collections, TThreadedQueue<T> alone does not descend from TEnumerable<T>.

Oh well.  It’s not all that hard to add an enumerator to a class that doesn’t have one.  Just use a class helper.

TThreadedQueueEnumerator<T> = class
  private
    FQueue: TThreadedQueue<T>;
    FCurrent: T;
    function GetCurrent: T;
  public
    constructor Create(queue: TThreadedQueue<T>);
    property Current: T read GetCurrent;
    function MoveNext: Boolean;
  end;

  TThreadedQueueHelper<T> = class helper for TThreadedQueue<T>
  public
    function GetEnumerator: TThreadedQueueEnumerator<T>;
  end;

implementation

{ TThreadedQueueEnumerator<T> }

constructor TThreadedQueueEnumerator<T>.Create(queue: TThreadedQueue<T>);
begin
  FQueue := queue;
end;

function TThreadedQueueEnumerator<T>.GetCurrent: T;
begin
  result:= FCurrent;
end;

function TThreadedQueueEnumerator<T>.MoveNext: Boolean;
begin
  result := FQueue.PopItem(FCurrent) = wrSignaled;
end;

{ TThreadedQueueHelper<T> }

function TThreadedQueueHelper<T>.GetEnumerator: TThreadedQueueEnumerator<T>;
begin
  result := TThreadedQueueEnumerator.Create(self);
end;

Well, that was easy.  That’s probably the simplest enumerator I’ve ever written, because of the way the queue’s design makes it easy to implement MoveNext.  Except… that doesn’t compile either.  Apparently you can’t put generic type parameters on a class helper, which means that as far as I can tell, you can’t apply a class helper to a generic class at all.

I suppose I could subclass it and add the enumerator that way, but TEnumerableThreadedQueue<T> is a bit of a bulky name, don’t you think?  I have to wonder why the enumerator was left off of this collection, though, especially since the standard enumerator pattern is basically the only reasonable way to use a class like this…

Asking the impossible

On TVTropes, one of my favorite websites, there’s a phrase that’s only invoked when an author writes about something real, but uses it in a way that’s impossible and completely contrary to its nature: “X does not work that way.”  For example, if a sci-fi show features space fighters dogfighting and making turns that would only be possible with atmospheric friction against the hull, or gradually drifting to a stop if the engines stop thrusting, that might get listed under “Space does not work that way.”

What does this have to do with Delphi programming?  Bear with me.  Continue reading ‘Asking the impossible’ »