⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 u_share_ringbuffer.pas

📁 楠楠写的DBiocp例子都是源码
💻 PAS
📖 第 1 页 / 共 2 页
字号:
unit u_Share_RingBuffer;

interface
  uses Windows;
const
  MAX_BUFFER_LEN = 4096;
type
  //环形缓冲区类--可变数组缓冲区类
  TRingBuffer = class(TObject)
  private
    FBuffer : array of Char; //缓冲区
    FBufferLen : Longint; //缓冲区长度
    FisWrap : Boolean; //是否返回头部
    FCritical : TRTLCriticalSection; //临界区
    FIsCritical : Boolean; //是否需要临界区
    procedure Require(); //共享锁内存
    procedure Release(); //共享解锁
    function GetEmptyCount():Longint; //剩余空白数据量
  public
    FReadPos : LongInt; //读取点
    FWritePos : LongInt; //写入点
    function GetDataCount():Longint; //取得可用数据量
    function Readbuffer(var Buffer; Count: Longint):Longint; //读取数据
    function WriteBuffer(const Buffer; Count: Longint):Longint; //写入数据
    function CopyBuffer(var Buffer; Count: Longint):Longint; //复制数据
    function ResizeBuffer(ABufferLen:Longint):Boolean; //更改缓冲区大小
    function ReSet():Boolean; //复位缓冲区
    constructor Create(ABufferLen:Longint);
    destructor Destory();
  published
    property BufferLen: Longint read FBufferLen; //缓冲区总小小
    property IsCritical:Boolean read FIsCritical write FIsCritical; //多线程情况下需要考虑互斥访问共享缓冲区时使用
  end;
  //环形缓冲类–阻塞(同步)模式读写–继承自TRingBuffer
  //适合于多线程读写
  TRingBufferSyn = class(TRingBuffer)
  private
    FSynEvent : THandle; //同步读写事件句柄
  public
    function ReadbufferSyn(var Buffer; Count: Longint;TimeOut:Longint):Integer; //读取数据
    function WriteBufferSyn(const Buffer; Count: Longint;TimeOut:Longint):Integer; //写入数据
    constructor Create(ABufferLen:Longint);
    destructor Destory();
  end;
implementation
{ TRingBuffer }
constructor TRingBuffer.Create(ABufferLen:Longint);
begin
  inherited Create();
  FBufferLen := ABufferLen;
  SetLength( FBuffer,ABufferLen );
  FReadPos := 0;
  FWritePos := 0;
  FIsCritical := False;
  FisWrap := False; //是否返回头部
  InitializeCriticalSection(FCritical);
end;

destructor TRingBuffer.Destory;
begin
  DeleteCriticalSection(FCritical);
  inherited Destroy;
end;

procedure TRingBuffer.Require();
begin
  if FIsCritical then
  begin
    EnterCriticalSection(FCritical);
  end;
end;

procedure TRingBuffer.Release();
begin
  if FIsCritical then
  begin
    LeaveCriticalSection(FCritical);
  end;
end;

function TRingBuffer.CopyBuffer(var Buffer; Count: Longint):Longint; //复制数据
var
  Li_RemainCount,Litemp : Integer;
  tempbuf:array[0..MAX_BUFFER_LEN] of Char;
  Datacount:Integer;
begin
  try
    Result := 0;
    Require();
    Datacount := GetDataCount(); //获取实际数据量
    if (Datacount <= 0) or ( Count = 0 ) then //无数据可读的情况
    begin
      Result := 0;
      Exit;
    end;

    FillChar(tempbuf,MAX_BUFFER_LEN-1,0);
    if Datacount >= Count then //有足够数据可读
    begin
      if FWritePos > FReadPos then
      begin
        Move(FBuffer[FReadPos],Buffer,Count);
        Result := Count;
        FisWrap := false;
      end
      else
      begin
        //先判断尾部剩余空间有多少可读数据
        Li_RemainCount := FBufferLen - FReadPos; //到缓冲区尾部还剩的缓冲量
        if Count > Li_RemainCount then //尾部剩余数据都可读,把尾部数据全部读出
        begin
          Move(FBuffer[FReadPos],tempbuf,Li_RemainCount); //暂存数据到临时buf
          Litemp := Count - Li_RemainCount; //剩余要读的数据
          Move(FBuffer[0],tempbuf[Li_RemainCount],Litemp); //从头部读取剩余数据
          Move(tempbuf,Buffer,Count);
          Result := Count;
          FisWrap := false;
        end
        else
        begin //当可用数据不到尾部,则直接读取
          Move(FBuffer[FReadPos],tempbuf,Count); //暂存数据到临时buf
          Move(tempbuf,Buffer,Count);
          Result := Count;
          FisWrap := True;
        end;
      end;
    end else begin //无足够数据可读,可读取剩余数据
      if FWritePos > FReadPos then
      begin
        Move(FBuffer[FReadPos],Buffer,Datacount); //暂存数据到临时buf
        Result := Datacount;
        FisWrap := false;
      end
      else
      begin
        //先判断尾部剩余空间有多少可读数据
        Li_RemainCount := FBufferLen - FReadPos; //到缓冲区尾部还剩的缓冲量
        FillChar(tempbuf,MAX_BUFFER_LEN-1,0);
        Move(FBuffer[FReadPos],tempbuf,Li_RemainCount); //暂存数据到临时buf
        Litemp := Datacount - Li_RemainCount; //剩余要读的数据
        Move(FBuffer[0],tempbuf[Li_RemainCount],Litemp);
        Move(tempbuf,Buffer,Datacount);
        Result := Datacount;
        FisWrap := false;
      end;
    end;
  finally
    Release();
  end;
end;

function TRingBuffer.ReSet():Boolean;
begin
  FReadPos := 0;
  FWritePos := 0;
  FIsCritical := False;
  FisWrap := False; //是否返回头部
  fillchar(FBuffer[0],FBufferLen-1,0);
  Result := True;
end;



{——————————————————————————-
过程名: Readbuffer
作者: 黄健
日期: 2007.08.25
参数: var Buffer 需要返回的数据;
Count: Integer 需要读取的数据
返回值: Longint类型, 返回实际读取的数据量 <=0 表示读取错误或缓冲区空
——————————————————————————-}
function TRingBuffer.Readbuffer(var Buffer; Count: Integer): Longint;
var
  Li_RemainCount,Litemp : Integer;
  tempbuf:array[0..MAX_BUFFER_LEN] of Char;
  Datacount:Integer;
begin
  try
    Result := -1;
    Require();
    //if (Count < 0) or (Count > FBufferLen) then Exit;
    Datacount := GetDataCount(); //获取实际数据量
    if (Datacount <= 0) or ( Count = 0 ) then //无数据可读的情况
    begin
      Result := 0;
      Exit;
    end;

    FillChar(tempbuf,MAX_BUFFER_LEN-1,0);
    if Datacount >= Count then //有足够数据可读
    begin
      if FWritePos > FReadPos then
      begin
        Move(FBuffer[FReadPos],Buffer,Count);
        Inc(FReadPos,Count);
        Result := Count;
        FisWrap := false;
      end
      else
      begin
        //先判断尾部剩余空间有多少可读数据
        Li_RemainCount := FBufferLen - FReadPos; //到缓冲区尾部还剩的缓冲量
        if Count > Li_RemainCount then //尾部剩余数据都可读,把尾部数据全部读出
        begin
          Move(FBuffer[FReadPos],tempbuf,Li_RemainCount); //暂存数据到临时buf
          Litemp := Count - Li_RemainCount; //剩余要读的数据
          Move(FBuffer[0],tempbuf[Li_RemainCount],Litemp); //从头部读取剩余数据
          FReadPos := Litemp;
          Move(tempbuf,Buffer,Count);
          Result := Count;
          FisWrap := false;
        end
        else
        begin //当可用数据不到尾部,则直接读取
          Move(FBuffer[FReadPos],tempbuf,Count); //暂存数据到临时buf
          Inc(FReadPos,Count);
          Move(tempbuf,Buffer,Count);
          Result := Count;
          FisWrap := True;
        end;
      end;

    end
    else
    begin //无足够数据可读,可读取剩余数据
        if FWritePos > FReadPos then
        begin
          Move(FBuffer[FReadPos],Buffer,Datacount); //暂存数据到临时buf
          Inc(FReadPos,Datacount);
          Result := Datacount;
          FisWrap := false;
        end
        else
        begin
          //先判断尾部剩余空间有多少可读数据
          Li_RemainCount := FBufferLen - FReadPos; //到缓冲区尾部还剩的缓冲量
          FillChar(tempbuf,MAX_BUFFER_LEN-1,0);
          Move(FBuffer[FReadPos],tempbuf,Li_RemainCount); //暂存数据到临时buf
          Litemp := Datacount - Li_RemainCount; //剩余要读的数据
          Move(FBuffer[0],tempbuf[Li_RemainCount],Litemp);
          FReadPos := Litemp;
          Move(tempbuf,Buffer,Datacount);
          Result := Datacount;
          FisWrap := false;
        end;
    end;
  finally
    Release();
  end;
end;
{——————————————————————————-
过程名: WriteBuffer
作者: 黄健
日期: 2007.08.25
参数: const Buffer; 要写入的数据
Count: Integer 要写入数据大小
返回值: Longint 返回实际写入的数据量,<=0 表示写入错误或缓冲区满
——————————————————————————-}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -