1 |
unit UDaemon; |
2 |
(* ?ャ?鴻????????VCL?鴻?????? ?吾??gent *) |
3 |
(* Copyright (c) 2001,2002 hetareprog@hotmail.com *) |
4 |
|
5 |
interface |
6 |
uses |
7 |
Classes, SysUtils, |
8 |
USynchro; |
9 |
|
10 |
type |
11 |
(*-------------------------------------------------------*) |
12 |
TSynchroReq = class(TObject) |
13 |
public |
14 |
procedure Call; virtual; abstract; |
15 |
end; |
16 |
TSynchroCallProcedure = procedure() of object; |
17 |
TSynchroCallReq = class(TSynchroReq) |
18 |
public |
19 |
callProc: TSynchroCallProcedure; |
20 |
constructor Create(sub: TSynchroCallProcedure); |
21 |
procedure Call; override; |
22 |
end; |
23 |
|
24 |
(*-------------------------------------------------------*) |
25 |
TDaemon = class(TThread) |
26 |
private |
27 |
logMutex: THogeMutex; |
28 |
logList: TStringList; |
29 |
savedLogList: TStringList; |
30 |
request: THogeEvent; |
31 |
|
32 |
reqList: TList; |
33 |
savedReqList: TList; |
34 |
procedure SynchroProcess; |
35 |
public |
36 |
constructor Create; |
37 |
destructor Destroy; override; |
38 |
procedure Log(const str: string); |
39 |
procedure Execute; override; |
40 |
procedure LogLock; |
41 |
procedure LogFree; |
42 |
procedure RequestChunk; |
43 |
procedure Post(req: TSynchroReq); overload; |
44 |
procedure Post(proc: TSynchroCallProcedure); overload; |
45 |
end; |
46 |
|
47 |
(*-------------------------------------------------------*) |
48 |
TWaitTimer = class(TThread) |
49 |
private |
50 |
procedure SetInterval(const Value: Cardinal); |
51 |
protected |
52 |
FEnabled: Boolean; |
53 |
FInterval: Cardinal; |
54 |
FOnTimer: TNotifyEvent; |
55 |
FEvent: THogeEvent; |
56 |
FSync: THogeCriticalSection; |
57 |
procedure Execute; override; |
58 |
procedure DoTimer; |
59 |
public |
60 |
constructor Create; reintroduce; |
61 |
destructor Destroy; override; |
62 |
procedure SetBack; |
63 |
procedure Cancel; |
64 |
property Interval: Cardinal read FInterval write SetInterval; |
65 |
property OnTimer: TNotifyEvent read FOnTimer write FOnTimer; |
66 |
end; |
67 |
|
68 |
(*=======================================================*) |
69 |
implementation |
70 |
(*=======================================================*) |
71 |
|
72 |
uses |
73 |
Main; |
74 |
|
75 |
constructor TSynchroCallReq.Create(sub: TSynchroCallProcedure); |
76 |
begin |
77 |
callProc := sub; |
78 |
end; |
79 |
|
80 |
procedure TSynchroCallReq.Call; |
81 |
begin |
82 |
callProc; |
83 |
end; |
84 |
|
85 |
constructor TDaemon.Create; |
86 |
begin |
87 |
self.FreeOnTerminate := false; |
88 |
logMutex := THogeMutex.Create(false); |
89 |
logList := TStringList.Create; |
90 |
savedLogList := TStringList.Create; |
91 |
request := THogeEvent.Create; |
92 |
|
93 |
reqList := TList.Create; |
94 |
savedReqList := TList.Create; |
95 |
inherited Create(false); |
96 |
end; |
97 |
|
98 |
destructor TDaemon.Destroy; |
99 |
begin |
100 |
logMutex.Free; |
101 |
logList.Free; |
102 |
request.Free; |
103 |
reqList.Free; |
104 |
savedReqList.Free; |
105 |
savedLogList.Free; |
106 |
inherited; |
107 |
end; |
108 |
|
109 |
procedure TDaemon.Log(const str: string); |
110 |
begin |
111 |
if logMutex.Wait = WAIT_OBJECT_0 then |
112 |
begin |
113 |
logList.Add(str); |
114 |
logMutex.Release; |
115 |
self.request.SetEvent; |
116 |
end; |
117 |
end; |
118 |
|
119 |
|
120 |
|
121 |
procedure TDaemon.SynchroProcess; |
122 |
procedure ProcessLogger; |
123 |
var |
124 |
tmpList: TStringList; |
125 |
i: integer; |
126 |
begin |
127 |
if logMutex.Wait = WAIT_OBJECT_0 then |
128 |
begin |
129 |
tmpList := self.logList; |
130 |
self.logList := self.savedLogList; |
131 |
self.savedLogList := tmpList; |
132 |
logMutex.Release; |
133 |
end; |
134 |
for i := 0 to savedLogList.Count -1 do |
135 |
MainWnd.WriteLog(savedLogList.Strings[i]); |
136 |
savedLogList.Clear; |
137 |
end; |
138 |
|
139 |
procedure ProcessCaller; |
140 |
var |
141 |
tmpList: TList; |
142 |
i: integer; |
143 |
begin |
144 |
if logMutex.Wait = WAIT_OBJECT_0 then |
145 |
begin |
146 |
tmpList := self.reqList; |
147 |
self.reqList := self.savedReqList; |
148 |
self.savedReqList := tmpList; |
149 |
logMutex.Release; |
150 |
end; |
151 |
for i := 0 to savedReqList.Count -1 do |
152 |
begin |
153 |
TSynchroReq(savedReqList.Items[i]).call; |
154 |
TSynchroReq(savedReqList.Items[i]).Free; |
155 |
end; |
156 |
savedReqList.Clear; |
157 |
end; |
158 |
begin |
159 |
ProcessLogger; |
160 |
ProcessCaller; |
161 |
end; |
162 |
|
163 |
|
164 |
procedure TDaemon.Execute; |
165 |
begin |
166 |
while not Terminated do |
167 |
begin |
168 |
if request.Wait = WAIT_OBJECT_0 then |
169 |
begin |
170 |
if Terminated then |
171 |
break; |
172 |
Synchronize(SynchroProcess); |
173 |
end; |
174 |
end; |
175 |
end; |
176 |
|
177 |
procedure TDaemon.LogLock; |
178 |
begin |
179 |
self.logMutex.Wait; |
180 |
end; |
181 |
|
182 |
procedure TDaemon.LogFree; |
183 |
begin |
184 |
self.logMutex.Release; |
185 |
end; |
186 |
|
187 |
procedure TDaemon.RequestChunk; |
188 |
begin |
189 |
self.request.SetEvent; |
190 |
end; |
191 |
|
192 |
procedure TDaemon.Post(req: TSynchroReq); |
193 |
begin |
194 |
if self.logMutex.Wait = WAIT_OBJECT_0 then |
195 |
begin |
196 |
self.reqList.Add(req); |
197 |
self.logMutex.Release; |
198 |
self.request.SetEvent; |
199 |
end; |
200 |
end; |
201 |
|
202 |
procedure TDaemon.Post(proc: TSynchroCallProcedure); |
203 |
begin |
204 |
if self.logMutex.Wait() = WAIT_OBJECT_0 then |
205 |
begin |
206 |
self.reqList.Add(TSynchroCallReq.Create(proc)); |
207 |
self.logMutex.Release; |
208 |
self.request.SetEvent; |
209 |
end; |
210 |
end; |
211 |
|
212 |
|
213 |
(*=======================================================*) |
214 |
|
215 |
{ TWaitTimer } |
216 |
|
217 |
//?激?違????Reset)緇?????腱???罨<???激?違???????ャ???????ゃ???潟???榊?? |
218 |
|
219 |
constructor TWaitTimer.Create; |
220 |
begin |
221 |
FInterval := 100; |
222 |
FreeOnTerminate := False; |
223 |
FEvent := THogeEvent.Create(False, False, nil); |
224 |
FSync := THogeCriticalSection.Create; |
225 |
inherited Create(False); |
226 |
end; |
227 |
|
228 |
destructor TWaitTimer.Destroy; |
229 |
begin |
230 |
Suspend; |
231 |
Terminate; |
232 |
FEvent.SetEvent; |
233 |
Resume; |
234 |
WaitFor; |
235 |
FSync.Free; |
236 |
FEvent.Free; |
237 |
inherited; |
238 |
end; |
239 |
|
240 |
procedure TWaitTimer.DoTimer; |
241 |
begin |
242 |
if FEnabled and Assigned(FOnTimer) then |
243 |
FOnTimer(Self); |
244 |
end; |
245 |
|
246 |
procedure TWaitTimer.Execute; |
247 |
var |
248 |
WaitResult: Cardinal; |
249 |
CurrentInterval: Cardinal; |
250 |
begin |
251 |
while not Terminated do |
252 |
begin |
253 |
FEvent.Wait; |
254 |
FSync.Enter; |
255 |
CurrentInterval := FInterval; |
256 |
FSync.Leave; |
257 |
WaitResult := WAIT_OBJECT_0; |
258 |
while (not Terminated) and (WaitResult = WAIT_OBJECT_0) do |
259 |
WaitResult :=FEvent.Wait(CurrentInterval); |
260 |
if not Terminated then |
261 |
Synchronize(DoTimer); |
262 |
end; |
263 |
end; |
264 |
|
265 |
procedure TWaitTimer.SetBack; |
266 |
begin |
267 |
FEnabled := True; |
268 |
FEvent.SetEvent; |
269 |
end; |
270 |
|
271 |
procedure TWaitTimer.Cancel; |
272 |
begin |
273 |
FEnabled := False; |
274 |
FEvent.SetEvent; |
275 |
end; |
276 |
|
277 |
|
278 |
procedure TWaitTimer.SetInterval(const Value: Cardinal); |
279 |
begin |
280 |
FSync.Enter; |
281 |
FInterval := Value; |
282 |
FEvent.SetEvent; |
283 |
FSync.Leave; |
284 |
end; |
285 |
|
286 |
|
287 |
end. |