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

45 views (last 30 days)
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
royk
royk on 6 Aug 2019
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.

Accepted Answer

Guillaume
Guillaume on 5 Aug 2019
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
Guillaume
Guillaume on 7 Aug 2019
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
royk
royk on 7 Aug 2019
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.

More Answers (0)

Categories

Find more on Migrate GUIDE Apps in Help Center and File Exchange

Products


Release

R2019a

Community Treasure Hunt

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

Start Hunting!