Original Post
Ive know spent almost 2 full days debugging an insane problem.
For my game ive been creating a simple window manager, that works similar to the java Swing system.
A weird problem seemed to arise when more than one component with a listener existed. The effect being that *all* buttons reacted to input to any one of them.
The key players in this weird scenario is :
the MListener - a managed pointer to a Listener object
the listener has a managed pointer to the component its associated with(accessed by getComponent member function)
the MPComponent - a managed poiner to a component
(managed pointers are a simple reference counting system)
Each managed pointer has a bypass method that returns an int, the real pointer(not to be used lightly!).
The hashmap in question has as key a MPComponent, and as value a pointer to a vector of MListener(typedef'ed as ListenerVector), ie the associated listeners.
When a listener is to be registered in the window manager, we check to see if the component has any listeners(we get an iterator to it by using find, and then checking that iterator against the iterator gotten by using end().
If these are the same, there is no entry to this component
so we make a new listenervector there, and add the listener to be added to this list.
On the other hand, if there already is an entry, we dereference it and adds the listener to the already existing listenervector.
This is shown below:
(note: listeners is just an alternate access method, allowing one to traverse all listeners regardless of component association)
Anyway, when this code is actually used, it only reaches the else part once, all other calls acts if the hash_map actually had an entry for the MPComponent, and adds the listener to an already existing list(the one associated with the component belonging to the listener that was first added). So all listeners are added to the same ListenerVector associated with *one* component, and the hash_map happily returns this ListenerVector *no* matter what MPComponent you query for(only NULL doesnt). So when later code finds out that one component has been clicked for example, it innocently queries for the listeners associated with that component, gets *all* listeners returned, and continues to inform each and everyone of them that the mouse has been clicked on their target, in effect clicking *all* components on the screen....
I then tried changing the hash_compare method(which shouldnt make any diffence except in speed) to return the real adress of the MPComponent(100% unique naturally), but it still didnt work.
Not trusting the hash_map now, i changed it to a hash_map with an int key, simply using the adress of the component directly instead(in essence, prehashing the key. To my huge surprise this actually *works*!
This code is given below:
If anyone actually bothered to read this, i would be happy to be enlightened about what could cause this weird behavior!(but im sticking to the later version for now, im sick of that code!!!)
Nice to vent some frustration.....
[edited by - ziphnor on July 27, 2002 5:07:15 AM]
[edited by - ziphnor on July 27, 2002 5:09:20 AM]
void addListener(MListener ml)
{
MPComponent m = ml->getComponent();
hash_map<MPComponent, ListenerVector >::iterator list = component_listener.find(m);
hash_map<MPComponent, ListenerVector >::iterator end = component_listener.end();
if(list != end)
{
ListenerVector ls = (*list).second;
ls->push_back(ml);
}
else
{
component_listener[m] = new vector<MListener>();
component_listener[m]->push_back(ml);
}
listeners.push_back(ml);
}
void addListener(MListener ml)
{
MPComponent m = ml->getComponent();
int adress = m.bypass();
hash_map<int, ListenerVector >::iterator list = component_listener.find(adress);
hash_map<int, ListenerVector >::iterator end = component_listener.end();
if(list != end)
{
ListenerVector ls = (*list).second;
ls->push_back(ml);
}
else
{
component_listener[adress] = new vector<MListener>();
component_listener[adress]->push_back(ml);
}
listeners.push_back(ml);
}