unit BiDirBuf;
 
{Martin Harvey 7/5/2000}
 
interface
 
uses BoundedBuf;
 
type
 TBufferSide = (bsSideA, bsSideB);
 TBufferOp = (boWriting, boReading);
 
 TBiDirBuf = class
 private
 FAtoBBuf, FBtoABuf: TBoundedBuffer;
 protected
 function GetBuf(Side: TBufferSide; Op: TBufferOp): TBoundedBuffer;
 function GetSize: integer;
 procedure SetSize(NewSize: integer);
 public
 constructor Create;
 destructor Destroy; override;
 procedure ResetState;
 function PutItem(Side: TBufferSide; Item: pointer): boolean;
 function GetItem(Side: TBufferSide): pointer;
 { Entries used function peeks buffer one is reading from, and
 Entried free function peeks buffer one is writing to. It seems
 a bit useless to allow the other two operations: why worry about
 your neighbour when you have plenty else to worry about? }
 function GetEntriesUsed(Side: TBufferSide; var Used: integer): boolean;
 function GetEntriesFree(Side: TBufferSide; var Free: integer): boolean;
 published
 property Size: integer read GetSize write SetSize;
 end;
 
implementation
 
{ TBiDirBuf }
 
constructor TBiDirBuf.Create;
begin
 inherited Create;
 FAToBBuf := TBoundedBuffer.Create;
 FBToABuf := TBoundedBuffer.Create;
end;
 
destructor TBiDirBuf.Destroy;
begin
 FAToBBuf.Free;
 FBToABuf.Free;
 inherited Destroy;
end;
 
procedure TBiDirBuf.ResetState;
begin
 FAToBBuf.ResetState;
 FBToABuf.ResetState;
end;
 
function TBiDirBuf.GetBuf(Side: TBufferSide; Op: TBufferOp): TBoundedBuffer;
begin
 if ((Side = bsSideA) and (Op = boWriting))
 or ((Side = bsSideB) and (Op = boReading)) then
 result := FAToBBuf
 else if ((Side = bsSideA) and (Op = boReading))
 or ((Side = bsSideB) and (Op = boWriting)) then
 result := FBToABuf
 else
 begin
 result := FAToBBuf;
 Assert(false);
 end;
end;
 
function TBidirBuf.GetSize: integer;
begin
 Assert(FAToBBuf.Size = FBToABuf.Size);
 result := FAToBBuf.Size;
end;
 
procedure TBiDirBuf.SetSize(NewSize: integer);
begin
 FAToBBuf.Size := NewSize;
 FBToABuf.Size := NewSize;
 Assert(FAToBBuf.Size = FBToABuf.Size);
end;
 
function TBiDirBuf.PutItem(Side: TBufferSide; Item: Pointer): boolean;
begin
 result := GetBuf(Side, boWriting).PutItem(Item);
end;
 
function TBiDirBuf.GetItem(Side: TBufferSide): Pointer;
begin
 result := GetBuf(Side, boReading).GetItem;
end;
 
function TBiDirBuf.GetEntriesUsed(Side: TBufferSide; var Used: integer): boolean;
begin
 result := GetBuf(Side, boReading).GetEntriesUsed(Used);
end;
 
function TBiDirBuf.GetEntriesFree(Side: TBufferSide; var Free: integer): boolean;
begin
 result := GetBuf(Side, boWriting).GetEntriesFree(Free);
end;
 
end.