MATLAB Answers

royk
0

How can I find all object of a certain handle class?

Asked by royk
on 5 Aug 2019
Latest activity Commented on by royk
on 7 Aug 2019
I need to find all current object memory instances of a certain handle class "MyClass".
I cannot use "findobj" because I do not have a "seed" handle.
using "whos" is also problematic because: (a) different variables can in fact point to the exact same object; (b) objects may exist without any variable poitnitng to them (for example objects that are pointed to from a "UserData" of a figure); (c) handles to soem objects may be held in persitence variables of a static method of the class.
is there a generic way to find all the objects of MyClass despites these listed difficulties?

  7 Comments

MATLAB keeps internal counts of the number of references, but does not provide any nice way to access the counts. I believe that some mex code can return the current count for a given handle.
I do not know of any mechanism to notify when a reference count changes. If it exists then it would have to fire every time you passed the handle into a function. You would also get into a number of quality of implementation questions, such as:
f(Obj) + g(Obj)
Does the reference count increase in preparation for calling f then decrease upon the return from f, then increase in preparation for calling g, then decrease after g? Or does the reference count increase once as the handle is recorded internally and the recorded handle is passed to f and then g, and then decreased again? If there were another term after that g(Obj) then would the reference count decrease upon encountering the last reference in the expression or upon the end of the expression?
thnaks muhc
any idea/links/suggestions as to how a MEX code might be able to get the Matlab internal count of number of references to an object ?

Sign in to comment.

Products


Release

R2019a

1 Answer

Answer by Guillaume
on 5 Aug 2019
 Accepted Answer

I don't think there's any way to track down instances after the fact.
You could however track the creation and deletion of all instances of any handle class, without changing the class code, with meta.class and the events InstanceCreated and InstanceDestroyed. The whole thing is badly documented but the 2nd argument of the event is of type ClassInstance whose one of the property is the object created/destroyed.
Unfortunately, for the Destroyed case, the handle is no longer valid by the time you get it (since the object has been destroyed), so overall, I'm not sure it's that useful. Still, you could keep a reference count of object creation and destruction to know how many are in memory.

  7 Comments

that's what i ahve now. it is a bit messy and inherently slow.
I am thinking anohter possibility is to have all objects listen to a "SaveFiles" event from the central object
Yes, this is something that is cleanly implemented with events and listener.
You could have the command carried out by each object individually (they receive the command when the event is triggered) or report back to the controller which carry the command on each. I'm allowing both methods here.
First, the event arguments:
classdef (ConstructOnLoad) HasCommandEventArgs < event.EventData
properties (SetAccess = private)
Command; %The actual command to carry out. Handle to a function with one input: the class instance that the command applies to
CommandArgs; %Arguments to send to the controller when reporting back.
end
methods
function this = HasCommandEventArgs(command, args)
this.Command = command;
this.CommandArgs = args;
end
end
end
Then, the controller:
classdef MasterController < handle
events
HasCommand;
end
methods (Access = ?MyClass)
function this = MasterController()
end
%Function called by each instance once the event has been raised.
%Each instance reports back and the master controller can do whatever it wants sinc it gets the instance and the command arguments
function CheckIn(this, instance, commandargs)
fprintf('\nInstance %s reported back with command args: %s\n\n', instance.Name, commandargs);
end
end
methods (Access = public)
function SendCommand(this)
%basic command here, just ask the instances to disp themselves, and command arg is just a UUID
%you could tell the objects to save themselves, or pass a filename as argument and they'll report back with that filename for the controller to save them
uid = java.util.UUID.randomUUID;
notify(this, 'HasCommand', HasCommandEventArgs(@disp, uid));
end
end
end
And finally, the class to track:
classdef MyClass < handle
properties (SetAccess = private)
Name;
end
properties (Access = private)
controllerlistener;
end
methods (Static)
%Singleton controller for the whole class.
function controller = getController()
persistent mc;
if isempty(mc)
mc = MasterController;
end
controller = mc;
end
end
methods
%When the object is created, it listens for the controller HasCommand event
%Note that when the instance is destroyed, so is the listener
function this = MyClass(name)
this.Name = name;
controller = this.getController();
this.controllerlistener = event.listener(controller, 'HasCommand', @this.DoCommand);
end
end
methods (Access = private)
function DoCommand(this, source, eventargs)
command = eventargs.Command;
command(this);
source.CheckIn(this, eventargs.CommandArgs);
end
end
end
And simple usage example:
>> mc = MyClass.getController;
>> a = MyClass('A');
>> b = MyClass('B');
>> mc.SendCommand
MyClass with properties:
Name: 'B'
Instance B reported back with command args: 4284ae7d-d68a-4fdd-8294-4a8b63a11a12
MyClass with properties:
Name: 'A'
Instance A reported back with command args: 4284ae7d-d68a-4fdd-8294-4a8b63a11a12
Very nice implementation!
probem solved. much thanks
one suggestion: the handle of MyClass to the controller can be a Constant property of MyClass. this makes it all more elegant avoiding the need for the getController function and the persistence variable

Sign in to comment.