Jassert (changeListenerList.isValidMessageListener());


#1

I’ve got a system working where certain data objects are ChangeBroadcasters to notify control elements of their changes. When an element that uses it is created, it is registered with the data by adding itself as a ChangeListener.

I thought i’d be able to have the object check if it had any registered elements (is there a reason why there is no ‘getNumberOfChangeListeners()’ function?).

My main issue at the moment is that the elements automatically remove themselves as listeners from the data (as per my above assumption), but i get assertions at program close because they’re not registered (my guess because the data object has already been deleted? but then how is such a function getting called?) Is this going to be a problem for me? Continuing thru the assertions, there are no memory leaks or errors in the output.


#2

If a broadcaster gets deleted before its listeners, that’s not normally a problem, is it? Is it a juce assertion that’s getting thrown, or one of your own?


#3

it’s a juce assertion, the one in the topic header. I guessed that it’s not a problem if a broadcaster dies before a listener has been removed, and i also presume that in dying, listeners get removed automatically. I was just (1) confused as to how this function could be actually called if the broadcaster was in fact dead, and (2) wondering if there was anything i could do to avoid the assert. I could, of course, not remove the listener FROM the listener, especially as there is no function like the one i described earlier. I guess it doesn’t matter really.


#4

ah, sorry, I didn’t read the topic header! That assertion’s pretty nasty because it means that removeChangeListener() is getting called after the broadcaster’s been deleted… Are your listeners keeping a pointer to the broadcaster, which would become a dangler if you delete broadcaster before the listeners?


#5

do you mean from the broadcaster?

You don’t need to know what, or how many, listeners a broadcaster has to deal with clean-up. Particularly if there is a risk of objects being deleted without interested parties being informed, that information may be meaingless anyway.

A lot of how you would deal with gracefully rolling back listeners depends on the order of destruction. Will listeners die before the broadcaster, or vice-versa. Also if a given listener has a one to one relationship with a data handler, but may need to be reassigned during the life-time of an app, you’ll probably need to have a more structured clean-up.


#6

do you mean from the broadcaster?[/quote]

No, I do mean removing the listener (detaching it from a broadcaster) from within the listener itself [e.g. i am a listener, listening for a broadcaster, but i decide that i want to stop listening to that broadcaster for some reason].

For example, I have a ‘Style’ type, which is a kind of dynamic preset for a Component layout. When you adoptStyle() in a StyleAdopter, it takes a pointer to this ‘current’ style, but also listens to change messages from it; if the Style is altered, any StyleAdopter objects using that style will recieve change messages and be able to updateStyle().

I currently have it set to removeCurrentStyle() in the StyleAdopter destructor (which calls removeChangeListener(this) on the current style. I thought it was only polite to do so, really! I wanted to make it possible to, for example, allow a particular behaviour to occur when a style was not being used, or to be able to determine which is the most used style. I could, of course, just use some kind of counter variable. I could even forget about the ChangeListener approach and make a different kind of system, but the ChangeListeners work nicely enough.


#7

OK.

As it happens, I’m doing something very similar with some data components in an app I’m writing for work.

What I’m doing, which is a little ugly, but at least provides a level of safety, and debugging vectors, is to have my listener class maintain a pointer to the broadcaster class.

So lets say I have a method called ‘setThingICareAbout’, I might do something like:

void setThingICareAbout(BroadcasterClass* broadcasterObject)
{
  if (myBroadcasterPointer != 0) myBroadcasterPointer->removeChangeListener(this);
  myBroadcasterPointer = broadcasterObject;
  if (myBroadcasterPointer != 0) myBroadcasterPointer->addChangeListener(this);
}

Now, as long as I call the listener’s setThingICareAbout method with 0 in the destructor of the object that previously assigned it a BroadcasterClass object, I can be sure that the application will shut down cleanly without dangling references.


#8