From: Andreas H. <ah...@us...> - 2005-11-27 10:57:54
|
Update of /cvsroot/jvcl/dev/JVCL3/run In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv3753/run Modified Files: JvChangeNotify.pas Log Message: New implementation of bugfix Mantis #3301: Memory loss and crashes in JvChangeNotify Index: JvChangeNotify.pas =================================================================== RCS file: /cvsroot/jvcl/dev/JVCL3/run/JvChangeNotify.pas,v retrieving revision 1.40 retrieving revision 1.41 diff -C2 -d -r1.40 -r1.41 *** JvChangeNotify.pas 22 Nov 2005 11:47:15 -0000 1.40 --- JvChangeNotify.pas 27 Nov 2005 10:57:46 -0000 1.41 *************** *** 101,104 **** --- 101,107 ---- end; + { WARNING: Do not call Thread.Terminate from user code. This will leave a + dangling TJvChangeNotify.FThread reference which will cause an access + violation at the next TJvChangeNotify.SetActive call. } TJvChangeThread = class(TThread) private *************** *** 113,117 **** public constructor Create(NotifyArray: TJvNotifyArray; Count, Interval: Integer; AFreeOnTerminate: Boolean); - destructor Destroy; override; property OnChangeNotify: TJvThreadNotifyEvent read FNotify write FNotify; end; --- 116,119 ---- *************** *** 132,136 **** procedure NotifyError(const Msg: string); procedure DoThreadChangeNotify(Sender: TObject; Index: Integer); ! procedure DoThreadTerminate(Sender: TObject); protected procedure Change(Item: TJvChangeItem); virtual; --- 134,138 ---- procedure NotifyError(const Msg: string); procedure DoThreadChangeNotify(Sender: TObject; Index: Integer); ! procedure SetFreeOnTerminate(const Value: Boolean); protected procedure Change(Item: TJvChangeItem); virtual; *************** *** 144,149 **** property CheckInterval: Integer read FInterval write SetInterval default 100; // Set FreeOnTerminate to True if you want to be able to change the Active property ! // in the OnChangeNotify event. NOTE: FreeOnTerminate should be changed when Active := False ! property FreeOnTerminate: Boolean read FFreeOnTerminate write FFreeOnTerminate default True; property OnChangeNotify: TJvNotifyEvent read FNotify write FNotify; end; --- 146,151 ---- property CheckInterval: Integer read FInterval write SetInterval default 100; // Set FreeOnTerminate to True if you want to be able to change the Active property ! // in the OnChangeNotify event. ! property FreeOnTerminate: Boolean read FFreeOnTerminate write SetFreeOnTerminate default True; property OnChangeNotify: TJvNotifyEvent read FNotify write FNotify; end; *************** *** 312,315 **** --- 314,320 ---- destructor TJvChangeNotify.Destroy; begin + if Assigned(FThread) then + FThread.FreeOnTerminate := False; + FFreeOnTerminate := False; // do not call SetFreeOnTerminate here Active := False; FCollection.Free; *************** *** 377,389 **** end; - procedure TJvChangeNotify.DoThreadTerminate(Sender: TObject); - begin - { FThread must be set to NIL only if the calling thread is still assigned - to the FThread field. If this is not so, another thread was started and - this thread was terminated by SetActive(). } - if TThread(Sender).FreeOnTerminate and (FThread = Sender) then - FThread := nil; - end; - procedure TJvChangeNotify.SetActive(const Value: Boolean); const --- 382,385 ---- *************** *** 398,402 **** S: string; begin ! if (FActive <> Value) then begin FActive := Value; --- 394,398 ---- S: string; begin ! if FActive <> Value then begin FActive := Value; *************** *** 414,418 **** {$IFDEF CLR} for I := 0 to High(FNotifyArray) do ! FNotifyArray[I] := INVALID_HANDLE_VALUE; {$ELSE} FillChar(FNotifyArray, SizeOf(TJvNotifyArray), INVALID_HANDLE_VALUE); --- 410,414 ---- {$IFDEF CLR} for I := 0 to High(FNotifyArray) do ! FNotifyArray[I] := INVALID_HANDLE_VALUE; {$ELSE} FillChar(FNotifyArray, SizeOf(TJvNotifyArray), INVALID_HANDLE_VALUE); *************** *** 440,454 **** if FThread <> nil then begin ! if FreeOnTerminate then ! FThread.FreeOnTerminate := False; FThread.Terminate; if FThread.Suspended then FThread.Resume; ! FThread.WaitFor; ! FreeAndNil(FThread); end; FThread := TJvChangeThread.Create(FNotifyArray, FCollection.Count, FInterval, FFreeOnTerminate); FThread.OnChangeNotify := DoThreadChangeNotify; - FThread.OnTerminate := DoThreadTerminate; FThread.Resume; end --- 436,453 ---- if FThread <> nil then begin ! FThread.OnChangeNotify := nil; FThread.Terminate; if FThread.Suspended then FThread.Resume; ! if FreeOnTerminate then ! FThread := nil ! else ! begin ! FThread.WaitFor; ! FreeAndNil(FThread); ! end; end; FThread := TJvChangeThread.Create(FNotifyArray, FCollection.Count, FInterval, FFreeOnTerminate); FThread.OnChangeNotify := DoThreadChangeNotify; FThread.Resume; end *************** *** 456,466 **** if FThread <> nil then begin ! if FreeOnTerminate then ! FThread.FreeOnTerminate := False; FThread.Terminate; if FThread.Suspended then FThread.Resume; ! FThread.WaitFor; ! FreeAndNil(FThread); end; --- 455,469 ---- if FThread <> nil then begin ! FThread.OnChangeNotify := nil; FThread.Terminate; if FThread.Suspended then FThread.Resume; ! if FreeOnTerminate then ! FThread := nil ! else ! begin ! FThread.WaitFor; ! FreeAndNil(FThread); ! end; end; *************** *** 496,499 **** --- 499,520 ---- end; + procedure TJvChangeNotify.SetFreeOnTerminate(const Value: Boolean); + var + State: Boolean; + begin + if csLoading in ComponentState then + FFreeOnTerminate := Value + else + begin + State := Active; + try + Active := False; + FFreeOnTerminate := Value; + finally + Active := State; + end; + end; + end; + //=== { TJvChangeThread } ==================================================== *************** *** 516,524 **** end; - destructor TJvChangeThread.Destroy; - begin - inherited Destroy; - end; - procedure TJvChangeThread.Execute; var --- 537,540 ---- *************** *** 536,540 **** {$ENDIF CLR} False, FInterval); ! if (I >= 0) and (I < FCount) then begin try --- 552,556 ---- {$ENDIF CLR} False, FInterval); ! if (I >= 0) and (I < FCount) and not Terminated then begin try *************** *** 567,570 **** --- 583,587 ---- {$IFDEF UNITVERSIONING} + initialization RegisterUnitVersion(HInstance, UnitVersioning); |