Unit MessageQueues; Interface Uses TalkWithServer, SyncObjs; Type TMessageList = Array Of TMessageToServer; TMessageQueue = Class(TObject) Private FCriticalSection : TCriticalSection; FQueue : TMessageList; FQueueLength : Integer; { Volatile } FOutputStarted : Boolean; FDebugName : String; Public Constructor Create; Destructor Destroy; Override; // These are thread safe. The class maintains one queue. Anyone can // add to it. You grab the entire contents of the queue at once for // peformance reasons. You always want to pack a lot of data into each // netowrk packet. Procedure AddToQueue(Msg : TMessageToServer); Function GetQueue : TMessageList; Property OutputStarted : Boolean Read FOutputStarted Write FOutputStarted; Property DebugName : String Read FDebugName; End; Implementation Uses SysUtils; Var ItemCount : Integer = 0; Constructor TMessageQueue.Create; Begin FCriticalSection := TCriticalSection.Create; FDebugName := IntToStr(ItemCount); Inc(ItemCount) End; Destructor TMessageQueue.Destroy; Begin FCriticalSection.Free End; Procedure TMessageQueue.AddToQueue(Msg : TMessageToServer); Begin FCriticalSection.Enter; Try If FQueueLength = 0 Then SetLength(FQueue, 32) Else If FQueueLength = Length(FQueue) Then SetLength(FQueue, FQueueLength * 2); FQueue[FQueueLength] := Msg; Inc(FQueueLength) Finally FCriticalSection.Leave End End; Function TMessageQueue.GetQueue : TMessageList; Begin FCriticalSection.Enter; Try Result := FQueue; SetLength(FQueue, 0); SetLength(Result, FQueueLength); FQueueLength := 0 Finally FCriticalSection.Leave End End; End.