source: PinConnection/CommDelay.pas

Last change on this file was 575, checked in by chronos, 5 months ago
  • Modified: Remove U prefix from unit names of PinConnection package.
File size: 4.5 KB
Line 
1unit CommDelay;
2
3interface
4
5uses
6 Classes, SysUtils, CommPin, Threading, SyncObjs, SpecializedList;
7
8type
9 TCommDelay = class;
10
11 { TDelayedPacket }
12
13 TDelayedPacket = class
14 ReceiveTime: TDateTime;
15 Data: TListByte;
16 constructor Create;
17 destructor Destroy; override;
18 end;
19
20 { TCommDelayThread }
21
22 TCommDelayThread = class(TTermThread)
23 Parent: TCommDelay;
24 PacketQueue: TListObject;
25 Pin: TCommPin;
26 Lock: TCriticalSection;
27 procedure Execute; override;
28 end;
29
30 { TCommDelay }
31
32 TCommDelay = class(TCommNode)
33 private
34 FDelay: TDateTime;
35 PacketQueue1: TListObject; // TListObject<TDelayedPacket>
36 PacketQueue2: TListObject; // TListObject<TDelayedPacket>
37 Thread1: TCommDelayThread;
38 Thread2: TCommDelayThread;
39 procedure ReceiveData1(Sender: TCommPin; AStream: TListByte);
40 procedure ReceiveData2(Sender: TCommPin; AStream: TListByte);
41 protected
42 procedure SetActive(const AValue: Boolean); override;
43 public
44 Lock1: TCriticalSection;
45 Lock2: TCriticalSection;
46 Pin1: TCommPin;
47 Pin2: TCommPin;
48 constructor Create(AOwner: TComponent); override;
49 destructor Destroy; override;
50 property Delay: TDateTime read FDelay write FDelay;
51 end;
52
53
54implementation
55
56{ TCommDelayThread }
57
58procedure TCommDelayThread.Execute;
59var
60 I: Integer;
61 CurrentTime: TDateTime;
62 SendData: TListByte;
63 DoSleep: Boolean;
64begin
65 try
66 SendData := TListByte.Create;
67 repeat
68 DoSleep := True;
69 try
70 Lock.Acquire;
71 CurrentTime := Now;
72 I := 0;
73 while (I < PacketQueue.Count) do
74 if TDelayedPacket(PacketQueue[I]).ReceiveTime < (CurrentTime - Parent.Delay) then begin
75 DoSleep := False;
76 SendData.Assign(TDelayedPacket(PacketQueue[I]).Data);
77 PacketQueue.Delete(I);
78 try
79 Lock.Release;
80 Pin.Send(SendData);
81 finally
82 Lock.Acquire;
83 end;
84 end else Inc(I);
85 finally
86 Lock.Release;
87 end;
88 if not Terminated and DoSleep then Sleep(1);
89 until Terminated;
90 finally
91 SendData.Free;
92 end;
93end;
94
95{ TDelayedPacket }
96
97constructor TDelayedPacket.Create;
98begin
99 Data := TListByte.Create;
100end;
101
102destructor TDelayedPacket.Destroy;
103begin
104 FreeAndNil(Data);
105 inherited;
106end;
107
108{ TCommDelay }
109
110procedure TCommDelay.ReceiveData1(Sender: TCommPin; AStream: TListByte);
111begin
112 try
113 Lock2.Acquire;
114 if Delay = 0 then Pin2.Send(AStream)
115 else
116 with TDelayedPacket(PacketQueue2.AddNew(TDelayedPacket.Create)) do begin
117 ReceiveTime := Now;
118 Data.Assign(AStream);
119 end;
120 finally
121 Lock2.Release;
122 end;
123end;
124
125procedure TCommDelay.ReceiveData2(Sender: TCommPin; AStream: TListByte);
126begin
127 try
128 Lock1.Acquire;
129 if Delay = 0 then Pin1.Send(AStream)
130 else
131 with TDelayedPacket(PacketQueue1.AddNew(TDelayedPacket.Create)) do begin
132 ReceiveTime := Now;
133 Data.Assign(AStream);
134 end;
135 finally
136 Lock1.Release;
137 end;
138end;
139
140procedure TCommDelay.SetActive(const AValue: Boolean);
141begin
142 if FActive = AValue then Exit;
143 FActive := AValue;
144 if AValue then begin
145 Thread1 := TCommDelayThread.Create(True);
146 Thread1.FreeOnTerminate := False;
147 Thread1.Parent := Self;
148 Thread1.Name := 'CommDelay1';
149 Thread1.PacketQueue := PacketQueue1;
150 Thread1.Pin := Pin1;
151 Thread1.Lock := Lock1;
152 Thread1.Start;
153
154 Thread2 := TCommDelayThread.Create(True);
155 Thread2.FreeOnTerminate := False;
156 Thread2.Parent := Self;
157 Thread2.Name := 'CommDelay2';
158 Thread2.PacketQueue := PacketQueue2;
159 Thread2.Pin := Pin2;
160 Thread2.Lock := Lock2;
161 Thread2.Start;
162 end else begin
163 FreeAndNil(Thread1);
164 FreeAndNil(Thread2);
165 end;
166 inherited;
167end;
168
169constructor TCommDelay.Create(AOwner: TComponent);
170begin
171 inherited;
172 Lock1 := TCriticalSection.Create;
173 Lock2 := TCriticalSection.Create;
174 PacketQueue1 := TListObject.Create;
175 PacketQueue2 := TListObject.Create;
176 Pin1 := TCommPin.Create;
177 Pin1.OnReceive := ReceiveData1;
178 Pin1.Node := Self;
179 Pin2 := TCommPin.Create;
180 Pin2.OnReceive := ReceiveData2;
181 Pin2.Node := Self;
182end;
183
184destructor TCommDelay.Destroy;
185begin
186 Active := False;
187 FreeAndNil(Pin2);
188 FreeAndNil(Pin1);
189 FreeAndNil(PacketQueue1);
190 FreeAndNil(PacketQueue2);
191 FreeAndNil(Lock1);
192 FreeAndNil(Lock2);
193 inherited;
194end;
195
196end.
197
Note: See TracBrowser for help on using the repository browser.