Hello,
> My generic scope guard, however, is easily portable using anonymous > methods: > > [...]
damn - I forgot to call FExitProc :)
Of course this call complicates the situation a bit:
// ----- uses SysUtils;
type TScopeGuard = record private FGuard: IInterface; FVMT: Pointer; FExitProc: TProc; public constructor Create (InitProc, ExitProc: TProc); end;
function NopQueryInterface (Self: Pointer; const iid: TGUID; out Obj): HRESULT; stdcall; begin Pointer (Obj) := nil; Result := E_NOINTERFACE; end; procedure NopAddRef (Self: Pointer); stdcall; begin end; procedure ScopeGuardRelease (Self: Pointer); stdcall; type PScopeGuard = ^TScopeGuard; begin Self := PByte (Self) - SizeOf (IInterface); if Assigned (PScopeGuard (Self).FExitProc) then PScopeGuard (Self).FExitProc (); end;
constructor TScopeGuard.Create (InitProc, ExitProc: TProc); const VMT: array[0..2] of Pointer = ( @NopQueryinterface, @NopAddRef, @ScopeGuardRelease ); begin InitProc; FVMT := @VMT; Pointer (FGuard) := @FVMT; FExitProc := ExitProc; end; // -----
Note that I'm using nasty hacks to avoid allocating another object. To see how to do it cleanly, read Barry's blog. Also, I guess in reality you would use Barry's one-liner anyway. This is just to fix my broken example.
-- Moritz
"Hey, it compiles! Ship it!"