Clearing handle subclasses with timer objects

5 visualizzazioni (ultimi 30 giorni)
Save this class:
classdef test_class < handle
methods
function this = test_class()
fprintf('Hello world\n');
%timer('TimerFcn', @(a,b) fprintf('I''m alive\n'), 'Period', 1, 'ExecutionMode', 'fixedSpacing');
end
function delete(this)
fprintf('Goodbye world\n');
end
end
end
Now run this:
h = test_class(); clear;
Now uncomment the commented tine in test class and do the same again. You'll see that the delete() method isn't being called, though it should. Why?
Now call:
delete(timerfindall);
and the delete() method will be called. How can I get the delete method to be called when the handle to the object, as opposed to the timer (or the last of the two), is cleared?
I'm using R2012a on Windows 7 64-bit.
Since the documentation says: "If you call clear on all handle variables that refer to the same handle object, then you have lost access to the object and MATLAB destroys the object. That is, when there are no references to an object, the object ceases to exist." I believe what I'm seeing is a bug. The timer certainly shouldn't be creating a copy of the handle to the object.

Risposta accettata

per isakson
per isakson il 30 Mag 2012
My mental model says that "@(a,b)" contains a snapshot of the scope in which it was created. That snapshot includes "this". Thus, there is a reference to the object in the timer object.

Più risposte (1)

Oliver Woodford
Oliver Woodford il 1 Giu 2012
per isakson is right, but I'll add more info here:
The anonymous function does save a reference to class object. This in itself is not a problem, but the full issue is explained by TMW, who also answered this in a service request:
"MATLAB's life cycle management algorithm traverses the object graph and if it determines that an object is no longer referenced externally it will invoke the delete method on that object. An object can be referenced but still get deleted if the references to the object are all cyclic references. For the algorithm to work it must be able to traverse the whole object graph. If the object graph contains java objects then the algorithm will not work because MATLAB does not know how to access a java object.
For the example case there is a cyclic reference from the java timer object to the anonymous function handle which has a reference to the test_class object and back to the java timer object. MATLAB's life cycle management code could not look through the java timer object, therefore could not determine if it contains a cyclic reference to the test_class object. So the delete method was never called on the test_class object. In fact all the objects in the cycle are leaked.
To avoid this problem the callback function to the timer object should not be a nested or anonymous function handle. A local or global function handle should be used instead."
So this works well:
classdef test_class < handle
properties
tmr;
end
methods
function this = test_class()
fprintf('Hello world\n');
this.tmr = timer('TimerFcn', @test_class.timer_callback, 'Period', 1, 'ExecutionMode', 'fixedSpacing');
set(this.tmr, 'UserData', 'I''m alive!');
start(this.tmr);
end
function delete(this)
stop(this.tmr);
delete(this.tmr);
fprintf('Goodbye world\n');
end
function change_text(this, str)
set(this.tmr, 'UserData', str);
end
end
methods (Static)
function timer_callback(h, e)
fprintf('%s\n', get(h, 'UserData'));
end
end
end
Calling it as follows:
h = test_class;
pause(3);
change_text(h, 'But not for long :(');
pause(3);
clear;
  1 Commento
Wilco Pancras
Wilco Pancras il 8 Lug 2022
Note that this is also true for value classes that own an onCleanup object.

Accedi per commentare.

Categorie

Scopri di più su Class File Organization in Help Center e File Exchange

Community Treasure Hunt

Find the treasures in MATLAB Central and discover how the community can help you!

Start Hunting!

Translated by