Ignore:
Timestamp:
Nov 15, 2011, 8:39:23 AM (13 years ago)
Author:
george
Message:
  • Modified: CommProtocol remote buffer now have own class for handling filling of communication buffer in remote device.
  • Fixed: Do not try to retransmit data for not prepared or finished session.
File:
1 edited

Legend:

Unmodified
Added
Removed
  • PinConnection/UCommProtocol.pas

    r283 r294  
    3333  public
    3434    Lock: TCriticalSection;
     35    Enabled: Boolean;
    3536    SequenceNumber: Integer;
    3637    ResponseCode: Integer;
     
    5152  public
    5253    SequenceNumber: integer;
     54    MaxSequenceNumber: integer;
     55    MaxSessionCount: integer;
    5356    Parent: TCommProtocol;
    5457    Lock: TCriticalSection;
     
    5861    constructor Create;
    5962    destructor Destroy; override;
     63    procedure Assign(Source: TListObject);
    6064  end;
    6165
     
    6670  { TRetransmitCheckThread }
    6771
    68   TRetransmitCheckThread = class(TListedThread)
     72  TRetransmitCheckThread = class(TTermThread)
    6973  public
    7074    Parent: TCommProtocol;
    7175    CheckPeriod: Integer;
    7276    procedure Execute; override;
     77  end;
     78
     79  { TRemoteBuffer }
     80
     81  TRemoteBuffer = class
     82    Lock: TCriticalSection;
     83    Size: Integer;
     84    Used: Integer;
     85    procedure Allocate(AValue: Integer);
     86    procedure Release(AValue: Integer);
     87    procedure Assign(Source: TRemoteBuffer);
     88    constructor Create;
     89    destructor Destroy; override;
    7390  end;
    7491
     
    89106    RetransmitRepeatCount: integer;
    90107    RetransmitTotalCount: integer;
    91     MaxSequenceNumber: integer;
    92     MaxSessionCount: integer;
    93     RemoteBufferSize: Integer;
    94     RemoteBufferUsed: Integer;
     108    RemoteBuffer: TRemoteBuffer;
    95109    WrongSequenceCount: integer;
    96110    Sessions: TDeviceProtocolSessionList;
     
    98112    LastCommandResponseTime: TDateTime;
    99113    LastLatency: TDateTime;
     114    Lock: TCriticalSection;
    100115    procedure DataReceive(Sender: TCommPin; Stream: TStream); virtual;
    101116    procedure SendCommand(Command: array of integer;
     
    112127
    113128resourcestring
     129  SRemoteBufferInconsistency = 'Remote buffer inconsistency';
    114130  SResponseError = 'Command %0:s response error %1:s';
    115131  SResponseTimeout = 'Response timeout';
     
    120136
    121137implementation
     138
     139{ TRemoteBuffer }
     140
     141procedure TRemoteBuffer.Allocate(AValue: Integer);
     142begin
     143  try
     144    Lock.Acquire;
     145
     146    // Wait for free remote buffer
     147    while (Used + AValue) > Size do
     148    try
     149      Lock.Release;
     150      Sleep(1);
     151    finally
     152      Lock.Acquire;
     153    end;
     154    Used := Used + AValue;
     155  finally
     156    Lock.Release;
     157  end;
     158end;
     159
     160procedure TRemoteBuffer.Release(AValue: Integer);
     161begin
     162  try
     163    Lock.Acquire;
     164    Used := Used - AValue;
     165    if Used < 0 then
     166      raise Exception.Create(SRemoteBufferInconsistency);
     167  finally
     168    Lock.Release;
     169  end;
     170end;
     171
     172procedure TRemoteBuffer.Assign(Source: TRemoteBuffer);
     173begin
     174  Used := Source.Used;
     175  Size := Source.Size;
     176end;
     177
     178constructor TRemoteBuffer.Create;
     179begin
     180  Lock := TCriticalSection.Create;
     181  Size := 127;
     182  Used := 0;
     183end;
     184
     185destructor TRemoteBuffer.Destroy;
     186begin
     187  Lock.Free;
     188  inherited Destroy;
     189end;
    122190
    123191
     
    159227                  else CommandError := 0;
    160228                Latency := Now - TransmitTime;
     229                Enabled := False;
    161230                ReceiveEvent.SetEvent;
    162231              finally
     
    253322
    254323procedure TCommProtocol.SetActive(const AValue: Boolean);
    255 var
    256   SessionCount: Integer;
    257324begin
    258325  if FActive = AValue then Exit;
     
    269336  end else begin
    270337    // Wait for empty session list
    271     repeat
     338    try
     339      Sessions.Lock.Acquire;
     340      while Sessions.Count > 0 do
    272341      try
     342        Sessions.Lock.Release;
     343        Sleep(1);
     344      finally
    273345        Sessions.Lock.Acquire;
    274         SessionCount := Sessions.Count;
    275       finally
    276         Sessions.Lock.Release;
    277346      end;
    278       Sleep(1);
    279     until SessionCount = 0;
    280 
     347    finally
     348      Sessions.Lock.Release;
     349    end;
    281350    FreeAndNil(RetransmitThread);
    282351  end;
     
    292361  if FActive then begin
    293362  try
     363    //Lock.Acquire;
    294364    Session := TDeviceProtocolSession.Create;
    295365    Sessions.Add(Session);
     
    313383        NewRequest.WriteToStream(Request);
    314384
    315         // Wait for free remote buffer
    316         while (RemoteBufferUsed + Request.Size) > RemoteBufferSize do
    317           Sleep(1);
     385        RemoteBuffer.Allocate(Request.Size);
    318386
    319387        //StopWatch.Start;
    320388        TransmitTime := Now;
    321389        Pin.Send(Request);
     390        Enabled := True;
    322391      finally
    323392        Lock.Release;
    324393      end;
    325394      try
    326         try
    327           Sessions.Lock.Acquire;
    328           RemoteBufferUsed := RemoteBufferUsed + Request.Size;
    329         finally
    330           Sessions.Lock.Release;
    331         end;
    332         while ReceiveEvent.WaitFor(10) = wrTimeout do begin
     395        while ReceiveEvent.WaitFor(1) = wrTimeout do begin
    333396          if Timeouted then
    334397            raise ECommTimeout.Create(SResponseTimeout);
     
    342405        LastLatency := Latency;
    343406      finally
    344         try
    345           Sessions.Lock.Acquire;
    346           RemoteBufferUsed := RemoteBufferUsed - Session.Request.Size;
    347           if RemoteBufferUsed < 0 then RemoteBufferUsed := 0;
    348         finally
    349           Sessions.Lock.Release;
    350         end;
     407        RemoteBuffer.Release(Session.Request.Size);
    351408        Sessions.Remove(Session);
    352409      end;
     
    354411  finally
    355412    NewRequest.Free;
     413    //Lock.Free;
    356414  end;
    357415  end else raise ENotActive.Create(SProtocolNotActive);
     
    360418constructor TCommProtocol.Create;
    361419begin
     420  RemoteBuffer := TRemoteBuffer.Create;
     421  Lock := TCriticalSection.Create;
    362422  Pin := TCommPin.Create;
    363423  Pin.OnReceive := DataReceive;
    364424  Sessions := TDeviceProtocolSessionList.Create;
    365425  Sessions.Parent := Self;
    366   MaxSessionCount := 10;
    367   MaxSequenceNumber := 127;
    368   RetransmitTimeout := 2 * OneSecond;
     426  RetransmitTimeout := 3 * OneSecond;
    369427  RetransmitRepeatCount := 3;
    370428  RetransmitTotalCount := 0;
    371   RemoteBufferSize := 127;
    372429end;
    373430
     
    377434  Sessions.Free;
    378435  Pin.Free;
    379   inherited Destroy;
     436  Lock.Free;
     437  RemoteBuffer.Free;
     438  inherited;
    380439end;
    381440
     
    384443  LastCommandResponseTime := Source.LastCommandResponseTime;
    385444  LastLatency := Source.LastLatency;
    386   MaxSequenceNumber := Source.MaxSequenceNumber;
    387   MaxSessionCount := Source.MaxSessionCount;
    388   RemoteBufferSize := Source.RemoteBufferSize;
    389   RemoteBufferUsed := Source.RemoteBufferUsed;
     445  RemoteBuffer.Assign(Source.RemoteBuffer);
    390446  WrongSequenceCount := Source.WrongSequenceCount;
    391447  RetransmitTimeout := Source.RetransmitTimeout;
     
    396452  OnAfterRequest := Source.OnAfterRequest;
    397453  OnDebugLog := Source.OnDebugLog;
     454  Sessions.Assign(Source.Sessions);
    398455  Active := Source.Active;
    399456end;
     
    431488    Lock.Acquire;
    432489    Session.SequenceNumber := GetSequenceNumber;
    433     while Count >= Parent.MaxSessionCount do
     490    while Count >= MaxSessionCount do
    434491    begin
    435492      try
     
    474531  inherited Create;
    475532  Lock := TCriticalSection.Create;
     533  MaxSessionCount := 100;
     534  MaxSequenceNumber := 127;
    476535end;
    477536
     
    491550end;
    492551
     552procedure TDeviceProtocolSessionList.Assign(Source: TListObject);
     553begin
     554  MaxSequenceNumber := TDeviceProtocolSessionList(Source).MaxSequenceNumber;
     555  MaxSessionCount := TDeviceProtocolSessionList(Source).MaxSessionCount;
     556  SequenceNumber := TDeviceProtocolSessionList(Source).SequenceNumber;
     557
     558  inherited;
     559end;
     560
    493561function TDeviceProtocolSessionList.GetSequenceNumber: Integer;
    494562begin
    495   Inc(SequenceNumber);
    496   if SequenceNumber > Parent.MaxSequenceNumber then
    497     SequenceNumber := 0;
    498   Result := SequenceNumber;
     563  try
     564    //Lock.Acquire;
     565    Inc(SequenceNumber);
     566    if SequenceNumber > MaxSequenceNumber then
     567      SequenceNumber := 0;
     568    Result := SequenceNumber;
     569  finally
     570    //Lock.Release;
     571  end;
    499572end;
    500573
     
    514587      while I < Sessions.Count do begin
    515588        Session := TDeviceProtocolSession(Sessions[I]);
    516         with TDeviceProtocolSession(Sessions[I]) do begin
     589        with Session do
     590        if Enabled then begin
    517591          try
    518592            Session.Lock.Acquire;
Note: See TracChangeset for help on using the changeset viewer.