25 |
|
* |
26 |
|
*) |
27 |
|
unit FB30Events; |
28 |
+ |
{$IFDEF MSWINDOWS} |
29 |
+ |
{$DEFINE WINDOWS} |
30 |
+ |
{$ENDIF} |
31 |
|
|
32 |
|
{$IFDEF FPC} |
33 |
< |
{$mode objfpc}{$H+} |
33 |
> |
{$mode delphi} |
34 |
|
{$interfaces COM} |
35 |
|
{$ENDIF} |
36 |
|
|
48 |
|
TEventhandlerInterface = class(Firebird.IEventCallbackImpl) |
49 |
|
private |
50 |
|
FOwner: TFB30Events; |
51 |
< |
FName: string; |
51 |
> |
FName: AnsiString; |
52 |
|
FRef: integer; |
53 |
|
{$IFDEF WINDOWS} |
54 |
|
{Make direct use of Windows API as TEventObject don't seem to work under |
58 |
|
FEventWaiting: TEventObject; |
59 |
|
{$ENDIF} |
60 |
|
public |
61 |
< |
constructor Create(aOwner: TFB30Events; aName: string); |
61 |
> |
constructor Create(aOwner: TFB30Events; aName: AnsiString); |
62 |
|
destructor Destroy; override; |
63 |
|
procedure addRef(); override; |
64 |
|
function release(): Integer; override; |
87 |
|
|
88 |
|
{IEvents} |
89 |
|
procedure WaitForEvent; |
90 |
< |
procedure AsyncWaitForEvent(EventHandler: TEventHandler); |
90 |
> |
procedure AsyncWaitForEvent(EventHandler: TEventHandler); override; |
91 |
|
end; |
92 |
|
|
93 |
|
implementation |
108 |
|
procedure Terminate; |
109 |
|
end; |
110 |
|
|
111 |
< |
constructor TEventhandlerInterface.Create(aOwner: TFB30Events; aName: string); |
111 |
> |
constructor TEventhandlerInterface.Create(aOwner: TFB30Events; aName: AnsiString); |
112 |
|
var |
113 |
|
PSa : PSecurityAttributes; |
114 |
|
{$IFDEF WINDOWS} |
128 |
|
{$ENDIF} |
129 |
|
inherited Create; |
130 |
|
{$IFDEF WINDOWS} |
131 |
< |
FEventHandler := CreateEvent(PSa,false,true,nil); |
131 |
> |
FEventHandler := CreateEvent(PSa,false,false,nil); |
132 |
|
{$ELSE} |
133 |
|
CreateGuid(GUID); |
134 |
|
FEventWaiting := TEventObject.Create(PSa,false,false,GUIDToString(GUID)); |
165 |
|
procedure TEventhandlerInterface.eventCallbackFunction(length: Cardinal; |
166 |
|
events: BytePtr); |
167 |
|
begin |
168 |
+ |
// writeln('TEventhandlerInterface: Event Callback'); |
169 |
|
FOwner.FCriticalSection.Enter; |
170 |
|
try |
171 |
|
if FOwner.FResultBuffer <> nil then |
172 |
< |
Move(events[0], FOwner.FResultBuffer[0], Length); |
169 |
< |
{$IFDEF WINDOWS} |
170 |
< |
SetEvent(FEventHandler); |
171 |
< |
{$ELSE} |
172 |
< |
FEventWaiting.SetEvent; |
173 |
< |
{$ENDIF} |
172 |
> |
Move(events^, FOwner.FResultBuffer^, Length); |
173 |
|
finally |
174 |
|
FOwner.FCriticalSection.Leave |
175 |
|
end; |
176 |
+ |
//writeln('TEventhandlerInterface: Set Event Called'); |
177 |
+ |
{$IFDEF WINDOWS} |
178 |
+ |
SetEvent(FEventHandler); |
179 |
+ |
{$ELSE} |
180 |
+ |
FEventWaiting.SetEvent; |
181 |
+ |
{$ENDIF} |
182 |
|
end; |
183 |
|
|
184 |
|
procedure TEventhandlerInterface.WaitForEvent; |
185 |
|
begin |
186 |
+ |
// writeln('TEventhandlerInterface: Start Event Wait'); |
187 |
|
{$IFDEF WINDOWS} |
188 |
|
WaitForSingleObject(FEventHandler,INFINITE); |
189 |
|
{$ELSE} |
190 |
|
FEventWaiting.WaitFor(INFINITE); |
191 |
|
{$ENDIF} |
192 |
+ |
// writeln('TEventhandlerInterface: Event Wait Ends'); |
193 |
|
end; |
194 |
|
|
195 |
|
procedure TEventhandlerInterface.CancelWait; |
217 |
|
constructor TEventHandlerThread.Create(Owner: TFB30Events; |
218 |
|
EventHandler: TEventhandlerInterface); |
219 |
|
begin |
220 |
< |
inherited Create(true); |
220 |
> |
inherited Create(false); |
221 |
|
FOwner := Owner; |
222 |
|
FEventHandler := EventHandler; |
223 |
|
FreeOnTerminate := true; |
217 |
– |
Start; |
224 |
|
end; |
225 |
|
|
226 |
|
procedure TEventHandlerThread.Terminate; |
264 |
|
if FInWaitState then |
265 |
|
IBError(ibxeInEventWait,[nil]); |
266 |
|
|
261 |
– |
CreateEventBlock; |
267 |
|
FEventHandler := EventHandler; |
268 |
|
ReleaseIntf; |
269 |
|
with Firebird30ClientAPI do |
291 |
|
begin |
292 |
|
inherited Create(DBAttachment,DBAttachment,Events); |
293 |
|
FAttachmentIntf := DBAttachment.AttachmentIntf; |
289 |
– |
FAsyncEventCallback := TEventhandlerInterface.Create(self,'Async'); |
290 |
– |
FEventHandlerThread := TEventHandlerThread.Create(self,FAsyncEventCallback); |
294 |
|
FSyncEventCallback := TEventhandlerInterface.Create(self,'Sync'); |
295 |
|
end; |
296 |
|
|
307 |
|
|
308 |
|
procedure TFB30Events.AsyncWaitForEvent(EventHandler: TEventHandler); |
309 |
|
begin |
310 |
+ |
{Seems like we have to create a new callback object each time to avoid empty events} |
311 |
+ |
if assigned(FEventHandlerThread) then |
312 |
+ |
TEventHandlerThread(FEventHandlerThread).Terminate; |
313 |
+ |
if assigned(FAsyncEventCallback) then TEventhandlerInterface(FAsyncEventCallback).release; |
314 |
+ |
FAsyncEventCallback := TEventhandlerInterface.Create(self,'Async'); |
315 |
+ |
FEventHandlerThread := TEventHandlerThread.Create(self,FAsyncEventCallback); |
316 |
|
InternalAsyncWaitForEvent(EventHandler,FAsyncEventCallback); |
317 |
|
end; |
318 |
|
|