unit _DIMQ; // DIM Queue library. See http://dim.web.cern.ch on DIM.

{$IFDEF FPC}{$mode objfpc}{$ENDIF}{$H+}

interface

uses windows,messages,sysutils,classes,math,_dim;

 ////////////
 // TDimQueue
 ////////////
type
 TDimQueue = class(TObject)
 private
  FList : TStringList;
  FCrit : TRTLCriticalSection;
 protected
  procedure Lock;
  procedure UnLock;
 public
  function  Put(Tag:TDimLong; Buffer:Pointer; Size:Integer):Boolean;
  function  Get(var Tag:TDimLong; var Data:String):Boolean;
 public
  constructor Create;
  destructor  Destroy; override;
 end;
 
procedure TestDimQueue;

implementation

 ////////////
 // TDimQueue
 ////////////

procedure TDimQueue.Lock;
begin
 EnterCriticalSection(FCrit);
end;

procedure TDimQueue.UnLock;
begin
 LeaveCriticalSection(FCrit);
end;

function TDimQueue.Put(Tag:TDimLong; Buffer:Pointer; Size:Integer):Boolean;
var S:String; P:PChar;
begin
 Result:=False;
 if (Self=nil) then Exit;
 if (Buffer=nil) then Exit;
 if (Size<=0) then Exit;
 if (Tag=0) then Exit;
 Lock;
 try
  SetLength(S,SizeOf(Tag)+Size);
  P:=PChar(S);
  Move(Tag,P^,SizeOf(Tag));
  Move(Buffer^,(P+SizeOf(Tag))^,Size);
  FList.Add(S);
  Result:=True;
 finally
  Unlock;
 end;
end;

function TDimQueue.Get(var Tag:TDimLong; var Data:String):Boolean;
var S:String; P:PChar;
begin
 Result:=False;
 Tag:=0; Data:='';
 if (Self=nil) then Exit;
 Lock;
 try
  if FList.Count>0 then begin
   S:=FList.Strings[0];
   FList.Delete(0);
   if Length(S)>SizeOf(Tag) then begin
    P:=PChar(S);
    Move(P^,Tag,SizeOf(Tag));
    Data:=Copy(S,1+SizeOf(Tag),Length(S)-SizeOf(Tag));
    Result:=True;
   end;
  end;
 finally
  UnLock;
 end;
end;

constructor TDimQueue.Create;
begin
 inherited Create;
 InitializeCriticalSection(FCrit);
 FList:=TStringList.Create;
end;

destructor TDimQueue.Destroy;
begin
 FList.Free;
 DeleteCriticalSection(FCrit);
 inherited Destroy;
end;

procedure TestDimQueue;
var DQueue:TDimQueue; i,Tag:Integer; S:String;
begin
 DQueue:=TDimQueue.Create;
 try
  // Push data to queue
  for i:=1 to 10 do begin
   Tag:=i; S:=Format('Data[%d]',[i]);
   DQueue.Put(Tag,PChar(S),Length(s));
  end;
  // Extract data from queue
  while DQueue.Get(Tag,S) do begin
   writeln(Tag:2,' ',S);
  end;
 finally
  DQueue.Free;
 end;
end;

end.
