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

📄 iggclientpool.pas

📁 通信控件
💻 PAS
📖 第 1 页 / 共 5 页
字号:
    procedure Exchange(Index1, Index2: Integer);
    function Expand: TIStreamPool;
    function First: TIStreamItem;
    function IndexOf(ID: DWORD): Integer;
    procedure Insert(Index: Integer; var Item: TIStreamItem);
    function Last: TIStreamItem;
    procedure Move(CurIndex, NewIndex: Integer);
    function Remove(ID: DWORD): Integer;
    procedure Pack;
    
    property Count: Integer read FCount write SetCount;
    property Items[Index: Integer]: TIStreamItem read Get write Put; default;
    property Enable: Boolean read FEnable;
  end;

function ElapsedSec(V: Integer): Integer;
function GetSec(): Integer;

implementation

function ElapsedSec(V: Integer): Integer;
var
  SysTime: SYSTEMTIME;
begin
  GetLocalTime(SysTime);
  Result := (SysTime.wHour*3600 + SysTime.wMinute*60 + SysTime.wSecond) - V;
  if Result < 0 then Result := 0;
end;

function GetSec(): Integer;
var
  SysTime: SYSTEMTIME;
begin
  GetLocalTime(SysTime);
  Result := (SysTime.wHour*3600 + SysTime.wMinute*60 + SysTime.wSecond);
end;

  { TIBuffer }
  
constructor TIBuffer.Create();
begin
end;

constructor TIBuffer.Create(AID, ASelfID, AAttachID: DWORD; AData: PChar; ADataSize: Integer;
  AWrite: Boolean; ABlockSize: Integer);
begin
  Init();
  SetPara(AID, ASelfID, AAttachID, AData, ADataSize, AWrite, ABlockSize);
end;

destructor TIBuffer.Destroy();
begin
  Clear();
end;

procedure TIBuffer.Init;
begin
  FEnable  := FALSE;
  FWrite   := TRUE;
  FSecTime := GetSec;
end;

procedure TIBuffer.Clear;
begin
  try
    if Assigned(FData) then
      FreeMem(FData);
  except end;
  try
    if Assigned(FBlock) then
      FreeMem(FBlock);
  except end;
  
  FBlock := nil;
  FData := nil;
  FEnable := FALSE;
end;

procedure TIBuffer.SetPara(AID, ASelfID, AAttachID: DWORD; AData: PChar; ADataSize: Integer;
  AWrite: Boolean; ABlockSize: Integer);
begin
  FID        := AID;
  FSelfID    := ASelfID;
  FAttachID  := AAttachID;
  FDataSize  := ADataSize;
  FBlockSize := ABlockSize;
  FWrite     := AWrite;
  FPosition  := 0;
  FStatus    := BUF_RECORD;
  FRetry     := 6;
  FEnable    := TRUE;
  
  try
    FData  := AllocMem(FDataSize);
    FBlock := AllocMem(FBlockSize);
    if (AData <> nil) then
      Move(AData^, FData^, ADataSize);
  except FEnable := FALSE; end;
end;

procedure TIBuffer.SetEnable(const Value: Boolean);
begin
  FEnable := Value;
end;

function TIBuffer.CheckProcess(Position: Integer; SubSize: Integer): Integer;
begin
  Result := -2;
  if FWrite and ((FStatus = BUF_DATA) or (FStatus = BUF_RECORD)) then
  begin
    if Position = FPosition then
    begin
      Result := FDataSize - (Position + SubSize);
      if Result > 0 then Result := 1;
      if Result < 0 then Result := -1;
    end;
  end else if ((FStatus = BUF_DATA) or (FStatus = BUF_RECORD)) then
  begin
    Result := FDataSize - (Position + SubSize);
    if Result > 0 then Result := 1;
    if Result < 0 then Result := -1;
  end;

  if Result = -1 then
    FErrCode := beBlockPosErr;
end;

function TIBuffer.CheckWork(): Integer;
begin
  Result := 0;
  if (FStatus = BUF_RECORD) then
    Result := 1
  else if (FStatus = BUF_DATA) then
    Result := 2;
end;

procedure TIBuffer.SetStatus(Status: Word; Para1: Word; Para2: Integer; Send: Boolean);

  procedure SendCmd(Cmd: Word; Para1: Word; Para2: Integer);
  var
    BufferCmd: TIBufferCmd;
  begin
    FillChar(BufferCmd, SizeOf(BufferCmd), 0);
    BufferCmd.ID       := FID;
    BufferCmd.SelfID   := FSelfID;
    BufferCmd.Command  := Cmd;
    BufferCmd.Para1    := Para1;
    BufferCmd.Para2    := Para2;
    if FWrite then  Cmd := 4  else  Cmd := 5;

    try
      if Assigned(FCallback) then
        FCallback(FAttachID, BufferCmd, SizeOf(BufferCmd), nil, 0, Cmd);
    except end;
  end;

var
  Cmd: Word;  
begin
  Cmd := BUF_STOP;
  try
    case Status of
      BUF_DATA, BUF_RECORD:
      begin
        FSecTime := GetSec();
        if (Para1 > 0) then FRetry := Para1;
      end;
      BUF_TIMEOUT, BUF_FAIL, BUF_STOP, BUF_COMPLETE:
      begin
        if Send then
          SendCmd(Status, Para1, Para2);
        Status := BUF_DESTROY;
      end;
    end;
  finally
    FStatus := Status;
  end;
end;

procedure TIBuffer.Command(Cmd: Word; Para1: Word; Para2: Integer);
begin
  if (Cmd = BUF_COMPLETE) then
    FPosition := FDataSize;
  SetStatus(Cmd, Para1, Para2, FALSE);
end;

procedure TIBuffer.AutoAdjust(Reserved: Integer);
var
  SecondV: Integer;
begin
  SecondV := ElapsedSec(FSecTime);
  case FStatus of
    BUF_RECORD: begin
      if (FRetry > 0) and (SecondV >= 15) then
      begin
        if FWrite then begin
          if WriteREQ() >= 0 then
            SetStatus(BUF_DATA, 3);
        end else  begin
          ReadREQ();
        end;
        Dec(FRetry);
      end else if (FRetry <= 0) then begin
        SetStatus(BUF_TIMEOUT, 0, 0, TRUE);
      end;
    end;
    BUF_DATA: begin
      if (FRetry > 0) and (SecondV >= 15) then
      begin
        if FWrite then begin
          if WriteREQ() < 0 then
            SetStatus(BUF_FAIL, 0, 0, TRUE);
        end;
        Dec(FRetry);
      end else if (FRetry <= 0) then begin
        SetStatus(BUF_TIMEOUT, 0, 0, TRUE);
      end;
    end;
  end;
end;

function TIBuffer.Query(var Res: Integer; PRec: Pointer; Cmd: DWORD): Integer;
begin
  Res := 0;  Result := 0;
  try
    AutoAdjust;
    Result := FPosition - FDataSize;
    if (FStatus = BUF_DESTROY) then
    begin
       Res := -1;
    end;
  except end;
end;

function TIBuffer.ReadREQ(): Integer;
var
  DataREQ: TIBufferAttr;
begin
  Result := 0;
  try
    Result := CheckProcess(FPosition, 0);
    if (Result > 0) then
    begin
      //SetStatus(BUF_DATA);
      FillChar(DataREQ, SizeOf(DataREQ), 0);
      DataREQ.ID       := FID;
      DataREQ.SelfID   := FSelfID;
      DataREQ.AttachID := FAttachID;
      DataREQ.DataSize := FDataSize;
      StrLCopy(DataREQ.NameID, PChar(FNameID), Length(FNameID));
      StrLCopy(DataREQ.Hash, PChar(FHash), BUFFER_HASH_SIZE-1);
      if Assigned(FCallback) then
        FCallback(FAttachID, DataREQ, SizeOf(DataREQ), nil, 0, 1);
    end;
  except Result := -1; end;
  //if (CheckV < 0) then
  //  SetStatus(BUF_FAIL, 0, 0, TRUE);
end;

function TIBuffer.Read(var DataREQ: PIBufferDataREQ): Integer;
var
  DataSEQU: TIBufferDataSEQU;  CheckV: Integer;
begin
  Result := 0; CheckV := 0;
  try
    CheckV := CheckProcess(DataREQ.Position, DataREQ.ReadSize);
    if (CheckV >= 0) then
    begin
      SetStatus(BUF_DATA, 3);
      
      Move((FData+DataREQ.Position)^, FBlock^, DataREQ.ReadSize);
      FillChar(DataSEQU, SizeOf(DataSEQU), 0);
      DataSEQU.ID       := FID;
      DataSEQU.SelfID   := FSelfID;
      DataSEQU.Position := DataREQ.Position;
      DataSEQU.ReadSize := DataREQ.ReadSize;
      FPosition := DataREQ.Position;
      if Assigned(FCallback) then
        FCallback(FAttachID, DataSEQU, SizeOf(DataSEQU), FBlock, DataREQ.ReadSize, 2);
      Result := DataREQ.ReadSize;
    end;
  except Result := -1; end;
  if CheckV < 0 then
    SetStatus(BUF_FAIL, 0, 0, TRUE);
end;

function TIBuffer.WriteREQ(): Integer;
var
  DataREQ: TIBufferDataREQ;
begin
  try
    Result := CheckProcess(FPosition, 0);
    if (Result > 0) then
    begin
      //SetStatus(BUF_DATA);
      FillChar(DataREQ, SizeOf(DataREQ), 0);
      DataREQ.ID       := FID;
      DataREQ.SelfID   := FSelfID;
      DataREQ.Position := FPosition;
      if (FPosition + FBlockSize > FDataSize) then
        FBlockSize := FDataSize - FPosition;
      DataREQ.ReadSize := FBlockSize;
      if Assigned(FCallback) then
        FCallback(FAttachID, DataREQ, SizeOf(DataREQ), nil, 0, 3);
    end;
  except Result := -1 end;
  //if (CheckV < 0) then
  //  SetStatus(BUF_FAIL, 0, 0, TRUE);
end;

function TIBuffer.Write(var DataSEQU: PIBufferDataSEQU; PData: Pointer; DataSize: Integer): Integer;
var
  DataREQ: TIBufferDataREQ; CheckV: Integer;
  Data: PChar;
begin
  Result := 0;
  try
    CheckV := CheckProcess(DataSEQU.Position, DataSEQU.ReadSize);
    if (CheckV >= 0) then
    begin
      SetStatus(BUF_DATA, 3);
      Data := PChar(DataSEQU)+SizeOf(TIBufferDataSEQU);
      Move(Data^, (FData+FPosition)^, DataSEQU.ReadSize);
      Inc(FPosition, DataSEQU.ReadSize);
      if (FPosition + FBlockSize > FDataSize) then
        FBlockSize := FDataSize - FPosition;

      if CheckV > 0 then begin
        FillChar(DataREQ, SizeOf(DataREQ), 0);
        DataREQ.ID       := FID;
        DataREQ.SelfID   := FSelfID;
        DataREQ.Position := FPosition;
        DataREQ.ReadSize := FBlockSize;
        if Assigned(FCallback) then
          FCallback(FAttachID, DataREQ, SizeOf(DataREQ), nil, 0, 3);
        Result := DataSEQU.ReadSize;
      end else if CheckV = 0 then begin
        FPosition := FDataSize;
        SetStatus(BUF_COMPLETE, 0, 0, TRUE);
      end;
    end;
  except  Result := -1; end;
  
  if (CheckV < 0) then
    SetStatus(BUF_FAIL, 0, 0, TRUE);
end;

  {TIBufferPool }

constructor TIBufferPool.Create(ACapacity: Integer);
begin
  Init();
  SetCapacity(ACapacity);
end;

destructor TIBufferPool.Destroy();
begin
  Clear;
end;

procedure TIBufferPool.Init;
begin
  FCount := 0;
  FCapacity := 0;
  SetLength(FList, 0);
end;

procedure TIBufferPool.Clear;
begin
  try
    //Clear FList....
    FCount := 0;
    FCapacity := 0;
    SetLength(FList, 0);
  except end;  
end;

procedure TIBufferPool.SetCapacity(const Value: Integer);
begin
  if (Value > 0) and (Value < 50) and (Value <> FCapacity) then
  begin
    SetLength(FList, Value);
    FCapacity := Value;
  end;
end;

function TIBufferPool.IdleSlot(): Integer;
begin
  if (FCount < FCapacity) then
    Result := FCount;
end;

function TIBufferPool.IndexOf(const IBuffer: TIBuffer): Integer;
var
  I: Integer;
begin
  Result := -1;
  for I := 0 to FCount-1 do begin
    if (FList[I] = IBuffer) then begin
      Result := I; Break;
    end;
  end;
end;

function TIBufferPool.IndexOf(const ID: DWORD): Integer;
var
  I: Integer;
begin
  Result := -1;
  for I := 0 to FCount-1 do begin
    if (FList[I].ID = ID) then begin
      Result := I;  Break;
    end;
  end;
end;

procedure TIBufferPool.Put(Index: Integer; IBuffer: TIBuffer);
begin
  if Index <= FCount then begin
    FList[Index] := IBuffer;
  end;
end;

function TIBufferPool.Add(IBuffer: TIBuffer): Integer;
begin
  Result := IdleSlot();
  if (Result > -1) then begin
    Put(Result, IBuffer);
    Inc(FCount);
  end;
end;

procedure TIBufferPool.Delete(const Index: Integer);
begin
  if (Index >= 0) and (Index < FCount) then
  begin
    Dec(FCount);
    FList[Index] := FList[FCount];
    FList[FCount] := nil;
  end;
end;

procedure TIBufferPool.Remove(const ID: DWORD);
var
  Index: Integer;
begin
  Index := IndexOf(ID);
  if (Index > -1) then
    Delete(Index);
end;

function TIBufferPool.Get(const ID: DWORD): TIBuffer;
var
  Index: Integer;
begin
  Result := nil;
  Index := IndexOf(ID);
  if (Index >= 0) then
    Result := FList[Index];
end;

function TIBufferPool.SearchIn(const Index: Integer): TIBuffer;
begin
  Result := nil;
  if (Index >= 0) and (Index < FCount) then
  begin
    Result := FList[Index];
  end;
end;

class procedure TIBufferPool.Delete(var IBuffer: TIBuffer);
begin
  try
    if Assigned(IBuffer) then
      IBuffer.Free;
  except end;
  IBuffer := nil;
end;

////////////////////////////////////////////////////////////////////////////////
 { TGGOutPool }

constructor TGGOutPool.Create;
begin
  FLock := TCriticalSection.Create;
  Init;
end;

destructor TGGOutPool.Destroy;
begin
  Clear;
  FLock.Free;
end;

procedure TGGOutPool.Init;
var
  PItem: POutItem;
  I: Integer;
  Ok: Boolean;
begin
  Ok := TRUE;
  FEnable := FALSE;
  FLock.Enter;
  try
    for I := 0 to MAX_BLOCK_POOL-1 do begin
      try
        New(PItem);
        FillChar(PItem^, SizeOf(TOutItem), 0);
        if Assigned(PItem) then
          Reset(PItem^);
       FList[I] := PItem;
      except
        Ok := FALSE;
      end;
    end;
  finally
    FCount := 0;
    FBlockID := 0;
    if (Ok) then FEnable := TRUE;
    FLock.Leave;
  end;
end;

procedure TGGOutPool.Clear(FreeData: Boolean);
var
  I: Integer;
  PItem: POutItem;
begin
  FLock.Enter;

⌨️ 快捷键说明

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