Fix memory leak in GHOST Event Manager.

The events are allocated on the heap, then pushed on a stack. Before
being processed, they are popped from the stack, and deleted after
processing is done. When the manager is destroyed (e.g. application
closing), any remaining event in the stack is detroyed.

Issue is that when the "application closing" event is processed, it is
never freed, because the manager gets destroyed before the call to
`delete` is made and the event is not on the stack anymore.

Now events are left on the stack while they are processed, and only
popped and deleted after processing is done.

As a slight bonus refactor: use void as return type for dispatch events
functions, as no caller is checking the return value, and it is not
clear what it means (suggested by the reviewer).

Reviewers: brecht

Differential Revision: https://developer.blender.org/D1695
This commit is contained in:
Kévin Dietrich 2015-12-27 18:07:38 +01:00
parent a36b522869
commit 3e35e32e9d
7 changed files with 29 additions and 87 deletions

View File

@ -263,9 +263,8 @@ extern int GHOST_ProcessEvents(GHOST_SystemHandle systemhandle, int waitForEvent
/**
* Retrieves events from the queue and send them to the event consumers.
* \param systemhandle The handle to the system
* \return Indication of the presence of events.
*/
extern int GHOST_DispatchEvents(GHOST_SystemHandle systemhandle);
extern void GHOST_DispatchEvents(GHOST_SystemHandle systemhandle);
/**
* Adds the given event consumer to our list.

View File

@ -319,9 +319,8 @@ public:
/**
* Retrieves events from the queue and send them to the event consumers.
* \return Indication of the presence of events.
*/
virtual bool dispatchEvents() = 0;
virtual void dispatchEvents() = 0;
/**
* Adds the given event consumer to our list.

View File

@ -230,11 +230,11 @@ int GHOST_ProcessEvents(GHOST_SystemHandle systemhandle, int waitForEvent)
int GHOST_DispatchEvents(GHOST_SystemHandle systemhandle)
void GHOST_DispatchEvents(GHOST_SystemHandle systemhandle)
{
GHOST_ISystem *system = (GHOST_ISystem *) systemhandle;
return (int) system->dispatchEvents();
system->dispatchEvents();
}

View File

@ -78,16 +78,6 @@ GHOST_TUns32 GHOST_EventManager::getNumEvents(GHOST_TEventType type)
}
GHOST_IEvent *GHOST_EventManager::peekEvent()
{
GHOST_IEvent *event = NULL;
if (m_events.empty() == false) {
event = m_events.back();
}
return event;
}
GHOST_TSuccess GHOST_EventManager::pushEvent(GHOST_IEvent *event)
{
GHOST_TSuccess success;
@ -103,52 +93,36 @@ GHOST_TSuccess GHOST_EventManager::pushEvent(GHOST_IEvent *event)
}
bool GHOST_EventManager::dispatchEvent(GHOST_IEvent *event)
void GHOST_EventManager::dispatchEvent(GHOST_IEvent *event)
{
bool handled;
if (event) {
handled = true;
TConsumerVector::iterator iter;
for (iter = m_consumers.begin(); iter != m_consumers.end(); ++iter) {
if ((*iter)->processEvent(event)) {
handled = false;
}
}
TConsumerVector::iterator iter;
for (iter = m_consumers.begin(); iter != m_consumers.end(); ++iter) {
(*iter)->processEvent(event);
}
else {
handled = false;
}
return handled;
}
bool GHOST_EventManager::dispatchEvent()
void GHOST_EventManager::dispatchEvent()
{
GHOST_IEvent *event = popEvent();
bool handled = false;
if (event) {
handled = dispatchEvent(event);
delete event;
}
return handled;
GHOST_IEvent *event = m_events.back();
dispatchEvent(event);
m_events.pop_back();
delete event;
}
bool GHOST_EventManager::dispatchEvents()
void GHOST_EventManager::dispatchEvents()
{
bool handled;
if (getNumEvents()) {
handled = true;
while (getNumEvents()) {
if (!dispatchEvent()) {
handled = false;
}
}
if (m_events.empty()) {
return;
}
else {
handled = false;
while (!m_events.empty()) {
dispatchEvent();
}
return handled;
}
@ -241,16 +215,6 @@ void GHOST_EventManager::removeTypeEvents(GHOST_TEventType type, GHOST_IWindow *
}
GHOST_IEvent *GHOST_EventManager::popEvent()
{
GHOST_IEvent *event = peekEvent();
if (event) {
m_events.pop_back();
}
return event;
}
void GHOST_EventManager::disposeEvents()
{
while (m_events.empty() == false) {

View File

@ -73,13 +73,6 @@ public:
*/
GHOST_TUns32 getNumEvents(GHOST_TEventType type);
/**
* Return the event at the top of the stack without removal.
* Do not delete the event!
* \return The event at the top of the stack.
*/
GHOST_IEvent *peekEvent();
/**
* Pushes an event on the stack.
* To dispatch it, call dispatchEvent() or dispatchEvents().
@ -90,23 +83,20 @@ public:
/**
* Dispatches the given event directly, bypassing the event stack.
* \return Indication as to whether any of the consumers handled the event.
*/
bool dispatchEvent(GHOST_IEvent *event);
void dispatchEvent(GHOST_IEvent *event);
/**
* Dispatches the event at the back of the stack.
* The event will be removed from the stack.
* \return Indication as to whether any of the consumers handled the event.
*/
bool dispatchEvent();
void dispatchEvent();
/**
* Dispatches all the events on the stack.
* The event stack will be empty afterwards.
* \return Indication as to whether any of the consumers handled the events.
*/
bool dispatchEvents();
void dispatchEvents();
/**
* Adds a consumer to the list of event consumers.
@ -145,12 +135,6 @@ public:
);
protected:
/**
* Returns the event at the top of the stack and removes it.
* Delete the event after use!
* \return The event at the top of the stack.
*/
GHOST_IEvent *popEvent();
/**
* Removes all events from the stack.

View File

@ -214,23 +214,20 @@ bool GHOST_System::getFullScreen(void)
}
bool GHOST_System::dispatchEvents()
void GHOST_System::dispatchEvents()
{
bool handled = false;
#ifdef WITH_INPUT_NDOF
// NDOF Motion event is sent only once per dispatch, so do it now:
if (m_ndofManager) {
handled |= m_ndofManager->sendMotionEvent();
m_ndofManager->sendMotionEvent();
}
#endif
if (m_eventManager) {
handled |= m_eventManager->dispatchEvents();
m_eventManager->dispatchEvents();
}
m_timerManager->fireTimers(getMilliSeconds());
return handled;
}

View File

@ -190,9 +190,8 @@ public:
/**
* Dispatches all the events on the stack.
* The event stack will be empty afterwards.
* \return Indication as to whether any of the consumers handled the events.
*/
bool dispatchEvents();
void dispatchEvents();
/**
* Adds the given event consumer to our list.