98 lines
2.2 KiB
ObjectPascal
Executable File
98 lines
2.2 KiB
ObjectPascal
Executable File
unit circularBuffer;
|
|
|
|
{$MODE Delphi}
|
|
|
|
{
|
|
Circular buffer for only 1 writer and 1 reader thread
|
|
Do not use with multiple writers or multiple readers (or at least protect the read and write yourself then)
|
|
}
|
|
|
|
interface
|
|
|
|
uses
|
|
{$ifdef darwin}macport,{$endif}
|
|
{$ifdef windows}windows,{$endif}
|
|
LCLIntf, syncobjs,classes, sysutils;
|
|
|
|
type TCircularObjectBuffer=class
|
|
private
|
|
buffer: array of TObject;
|
|
ReadIndex: integer;
|
|
WriteIndex: integer;
|
|
maxTimeout: integer;
|
|
hasData: Tevent;
|
|
hasSpace: TEvent;
|
|
function getCount: integer;
|
|
public
|
|
function Write(o: TObject): boolean;
|
|
function Read: TObject;
|
|
constructor create(InitialSize, maxTimeout: integer);
|
|
destructor destroy; override;
|
|
property count: integer read getCount;
|
|
end;
|
|
|
|
implementation
|
|
|
|
constructor TCircularObjectBuffer.create(InitialSize, maxTimeout: integer);
|
|
begin
|
|
setlength(buffer,initialsize);
|
|
ReadIndex:=0;
|
|
WriteIndex:=0;
|
|
HasData:=Tevent.create(nil,false,false,'');
|
|
HasSpace:=Tevent.create(nil,false,true,'');
|
|
self.maxTimeout:=MaxTimeout;
|
|
end;
|
|
|
|
destructor TCircularObjectBuffer.destroy;
|
|
begin
|
|
setlength(buffer,0);
|
|
if HasData<>nil then
|
|
HasData.Free;
|
|
|
|
if HasSpace<>nil then
|
|
HasSpace.Free;
|
|
end;
|
|
|
|
function TCircularObjectBuffer.getCount: integer;
|
|
begin
|
|
if ReadIndex=WriteIndex then
|
|
result:=0
|
|
else
|
|
if ReadIndex<WriteIndex then
|
|
result:=WriteIndex-ReadIndex
|
|
else
|
|
result:=(length(buffer)-ReadIndex)+WriteIndex;
|
|
end;
|
|
|
|
function TCircularObjectBuffer.Write(o: TObject): boolean;
|
|
var nextwriteindex: integer;
|
|
begin
|
|
result:=false;
|
|
nextwriteindex:=(WriteIndex+1) mod length(buffer);
|
|
if (nextwriteindex=ReadIndex) then
|
|
begin
|
|
//buffer full
|
|
sleep(5000);
|
|
if (hasspace.WaitFor(maxTimeout)<>wrsignaled) then exit;
|
|
end;
|
|
|
|
buffer[WriteIndex]:=o;
|
|
writeindex:=nextwriteindex;
|
|
HasData.SetEvent;
|
|
|
|
result:=true;
|
|
end;
|
|
|
|
function TCircularObjectBuffer.Read: TObject;
|
|
begin
|
|
result:=nil;
|
|
if (readindex=writeindex) and (hasdata.WaitFor(MaxTimeout)<>wrSignaled) then exit;
|
|
|
|
result:=Buffer[ReadIndex];
|
|
ReadIndex:=(readindex+1) mod length(buffer);
|
|
|
|
HasSpace.SetEvent;
|
|
end;
|
|
|
|
end.
|