您的位置:首页 > 编程语言 > Delphi

环形缓冲区实现类(Delphi)

2014-04-01 11:35 615 查看
环形缓冲区的用途及原理可以去百度资料狠多的,这里就不介绍了。直接贴代码.代码分别用D7,XE2编译测试

源码下载 http://files.cnblogs.com/lwm8246/uCircleBuffer.rar

//环形缓冲区实现类
//2014-03-20 16:20
//QQ 287413288
unit uCircleBuffer;

interface

uses
Windows,Classes;

type
TCircleBuffer=class
private
FMS:TMemoryStream;
FUserData:Pointer;
function GetMemory: Pointer;
protected
FReadPosition:Integer;
FWritePosition:Integer;
FCanReadCount:Integer;
FCanWrieCount:Integer;
public
constructor Create(const BuffSize:Integer);virtual;
destructor  Destroy();override;
function    Write(const Buffer;Count:Integer):integer;virtual;
function    Read(var Buffer;Count:Integer):Integer;virtual;
public
property ReadPosition:Integer  read FReadPosition;
property WritePosition:Integer read FWritePosition;
property CanReadCount:Integer  read FCanReadCount;
property CanWrieCount:Integer  read FCanWrieCount;
property Memory:Pointer read GetMemory;
property UserData:Pointer read FUserData write FUserData;
end;

//线程安全版本
TCircleBufferThread=class(TCircleBuffer)
private
FCS:TRTLCriticalSection;
function GetReadPosition():Integer;
function GetWritePosition():Integer;
function GetCanReadCount():Integer;
function GetCanWrieCount():Integer;
public
constructor Create(const BuffSize:Integer);override;
destructor  Destroy();override;
function    Write(const Buffer;Count:Integer):integer;override;
function    Read(var Buffer;Count:Integer):Integer;override;
public
property ReadPosition:Integer  read GetReadPosition;
property WritePosition:Integer read GetWritePosition;
property CanReadCount:Integer  read GetCanReadCount;
property CanWrieCount:Integer  read GetCanWrieCount;
end;

implementation

{ TCircleBuffer }

constructor TCircleBuffer.Create(const BuffSize: Integer);
begin
FMS := TMemoryStream.Create();
FMS.Size := BuffSize;
FMS.Position := 0;
FWritePosition := 0;
FReadPosition  := 0;
FCanWrieCount  := BuffSize;
FCanReadCount  := 0;
//\\
ZeroMemory(FMS.Memory,FMS.Size);
end;

destructor TCircleBuffer.Destroy;
begin
inherited;
FMS.Free();
end;

function TCircleBuffer.GetMemory: Pointer;
begin
Result := FMS.Memory;
end;

function TCircleBuffer.Read(var Buffer; Count: Integer): Integer;
var
P:PAnsiChar;
Len,DataLen:Integer;
begin
Result := 0;
//(I)
if FCanReadCount <= 0 then
begin
Exit;
end;

if Count > FCanReadCount then
DataLen := FCanReadCount
else DataLen := Count;

FMS.Position := FReadPosition mod FMS.Size;
Result := FMS.Read(Buffer,DataLen);
Dec(FCanReadCount,Result);
Dec(Count,Result);

//(II)
if (Count > 0) and (FCanReadCount > 0) then //继续读
begin
DataLen := Count;
if DataLen > FCanReadCount then DataLen := FCanReadCount;
FMS.Position := 0;
P := @Buffer;
Inc(P,Result);
Len := FMS.Read(P^,DataLen);
Inc(Result,Len);
Dec(FCanReadCount,Len);
end;

//增加可写字节数
Inc(FCanWrieCount,Result);
if FCanWrieCount > FMS.Size then FCanWrieCount := FMS.Size;

//调整读指针位置
Inc(FReadPosition,Result);
if FReadPosition > FMS.Size then Dec(FReadPosition,FMS.Size);

end;

function TCircleBuffer.Write(const Buffer; Count: Integer): integer;
var
Len,DataLen:Integer;
P:PAnsiChar;
begin
Result := 0;
//(I)
if FCanWrieCount <= 0 then
begin
Exit;
end;

if Count > FCanWrieCount then DataLen := FCanWrieCount else DataLen := Count;
FMS.Position := FWritePosition mod FMS.Size;
P := @Buffer;
Result := FMS.Write(Buffer,DataLen);
P := FMS.Memory;
if P = nil then
Exit;
Dec(Count,Result);
Dec(FCanWrieCount,Result);
if (Count > 0) and (FCanWrieCount > 0) then
begin
//(II)
P := @Buffer;
Inc(P,Result);
Len := FReadPosition  - 0;
if Count > Len then DataLen := Len else DataLen := Count;
FMS.Position := 0;
Len := FMS.Write(P^,DataLen);
Inc(Result,Len);
Dec(FCanWrieCount,Len);
end;

//增加可读字节数
Inc(FCanReadCount,Result);
if FCanReadCount > FMS.Size then FCanReadCount := FMS.Size;

//调整写指针位置
Inc(FWritePosition,Result);
if FWritePosition > FMS.Size then
FWritePosition := FWritePosition - FMS.Size;
end;

{ TCircleBufferThread }

constructor TCircleBufferThread.Create(const BuffSize: Integer);
begin
InitializeCriticalSection(FCS);  //初始化
inherited Create(BuffSize);
end;

destructor TCircleBufferThread.Destroy;
begin
DeleteCriticalSection(FCS);
inherited;
end;

function TCircleBufferThread.GetCanReadCount: Integer;
begin
EnterCriticalSection(FCS);
Result := FCanReadCount;
LeaveCriticalSection(FCS);
end;

function TCircleBufferThread.GetCanWrieCount: Integer;
begin
EnterCriticalSection(FCS);
Result := FCanWrieCount;
LeaveCriticalSection(FCS);
end;

function TCircleBufferThread.GetReadPosition: Integer;
begin
EnterCriticalSection(FCS);
Result := FReadPosition;
LeaveCriticalSection(FCS);
end;

function TCircleBufferThread.GetWritePosition: Integer;
begin
EnterCriticalSection(FCS);
Result := FWritePosition;
LeaveCriticalSection(FCS);
end;

function TCircleBufferThread.Read(var Buffer; Count: Integer): Integer;
begin
EnterCriticalSection(FCS);
try
Result := inherited read(Buffer,Count);
finally
LeaveCriticalSection(FCS);
end;
end;

function TCircleBufferThread.Write(const Buffer; Count: Integer): integer;
begin
EnterCriticalSection(FCS);
try
Result := inherited Write(Buffer,Count);
finally
LeaveCriticalSection(FCS);
end;
end;

end.


测试代码段:

procedure TForm1.btn1Click(Sender: TObject);
var
obj:TCircleBuffer;
TmpStr:AnsiString;
Len:Integer;
Buf:array[1..4096] of AnsiChar;
ASize,APosition:Integer;
P:PAnsiChar;
begin

obj := TCircleBuffer.Create(10);
ZeroMemory(@Buf,SizeOf(Buf));

TmpStr := '0123456789';
Len := obj.Write(TmpStr[1],Length(TmpStr));
P := Obj.Memory;
if P = nil then
Exit;

TmpStr := 'ABCD';
Len := obj.Write(TmpStr[1],Length(TmpStr));
if Len < 0 then
Exit;
P := Obj.Memory;
if P = nil then
Exit;

TmpStr := '0123456789';
Len := obj.Read(Buf,10);
if Len < 0 then
Exit;

P := Obj.Memory;
if P = nil then
Exit;

Len := obj.Read(Buf,10);
if Len < 0 then
Exit;

P := Obj.Memory;
if P = nil then
Exit;

tmpStr := 'ABC';
Len := Obj.Write(TmpStr[1],3);
if Len < 0 then
Exit;

tmpStr := '123456#';
Len := Obj.Write(TmpStr[1],Length(TmpStr));
if Len < 0 then
Exit;

P := Obj.Memory;
if P = nil then
Exit;

FillChar(Buf,SizeOf(Buf),$32);
// ZeroMemory(@Buf,SizeOf(Buf));
Len := obj.Read(Buf,3);
if Len < 0 then
Exit;

ZeroMemory(@Buf,SizeOf(Buf));
Len := obj.Read(Buf,10);
if Len < 0 then
Exit;

P := Obj.Memory;
if P = nil then
Exit;

TmpStr := 'AB';
Len := obj.Write(TmpStr[1],2);
if Len < 0 then
Exit;

P := Obj.Memory;
if P = nil then
Exit;

TmpStr := 'abcdefghijklmnopqrst';
Len := obj.Write(TmpStr[1],Length(TmpStr));
if Len < 0 then
Exit;

ZeroMemory(@Buf,SizeOf(Buf));
Len := obj.Read(Buf,10);
if Len < 0 then
Exit;

if obj <> nil then
obj.Free();

P := Obj.Memory;
if P = nil then
Exit;

end;
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: