Allow a gui2 timer delete itself in its callback.

This commit is contained in:
Mark de Wever 2009-12-13 17:46:00 +00:00
parent f5f5dc4aa4
commit 67335b20aa
3 changed files with 55 additions and 2 deletions

View file

@ -3,6 +3,7 @@ Version 1.7.10+svn:
* Updated translations:
* Miscellaneous and bugfixes:
* Scrollbar containers now use the button super class
* Allow a gui2 timer delete itself in its callback
Version 1.7.10-1.8beta3:
* Campaigns:

View file

@ -45,6 +45,45 @@ struct ttimer
/** The active timers. */
static std::map<unsigned long, ttimer> timers;
/** The id of the event being executed, 0 if none. */
static unsigned long executing_id = 0;
/** Did somebody try to remove the timer during its execution? */
static bool executing_id_removed = false;
/**
* Helper to make removing a timer in a callback safe.
*
* Upon creation it sets the executing id and clears the remove request flag.
*
* If an remove_timer() is called for the id being executed it requests a
* remove the timer and exits remove_timer().
*
* Upon destruction it tests whether there was a request to remove the id and
* does so. It also clears the executing id. It leaves the remove request flag
* since the execution function needs to know whether or not the event was
* removed.
*/
class texecutor
{
public:
texecutor(unsigned long id)
{
executing_id = id;
executing_id_removed = false;
}
~texecutor()
{
const unsigned long id = executing_id;
executing_id = 0;
if(executing_id_removed) {
remove_timer(id);
}
}
};
static Uint32 timer_callback(Uint32, void* id)
{
DBG_GUI_E << "Pushing timer event in queue.\n";
@ -115,6 +154,11 @@ remove_timer(const unsigned long id)
return false;
}
if(id == executing_id) {
executing_id_removed = true;
return true;
}
if(!SDL_RemoveTimer(itor->second.sdl_id)) {
/*
* This can happen if the caller of the timer didn't get the event yet
@ -142,8 +186,12 @@ execute_timer(const unsigned long id)
return false;
}
itor->second.callback(id);
if(itor->second.interval == 0) {
{
texecutor executor(id);
itor->second.callback(id);
}
if(!executing_id_removed && itor->second.interval == 0) {
timers.erase(itor);
}
return true;

View file

@ -57,6 +57,10 @@ add_timer(const Uint32 interval
/**
* Removes a timer.
*
* It's save to remove a timer in its own callback, only the value returned
* might not be accurate. The destruction is postponed until the execution is
* finished and the return value is whether the postponing was successful.
*
* @param id The id of the timer to remove, this is the id
* returned by add_timer.
*