Processing Lists
Jul 18, 2010 at 1:19am UTC
In my game I'm taking a list of function pointers that are called within a loop to get everything processed correctly. My problem occurs when a function calls for itself to be removed during the loop. The iterator goes to increment itself when it's pointing to a no-longer-existent part of the list making it impossible to increment. My solution comes as this:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33
static std::list<void (*)()> CallbackList;
typedef std::list<void (*)()>::iterator FuncIter;
static FuncIter* LoopIter = NULL;
FuncIter AddProcess ( void (*callback)() )
{
CallbackList.push_back ( callback );
return --(CallbackList.end());
}
void RemoveProcess ( FuncIter Pos )
{
if ( LoopIter != NULL )
{
if ( *LoopIter == --(CallbackList.end()) )
*LoopIter--;
else
*LoopIter++;
}
CallbackList.erase ( Pos );
}
void ProcessEverything ( )
{
FuncIter iter = CallbackList.begin ( );
LoopIter = &iter;
while ( iter != CallbackList.end ( ) )
{
(**iter)();
iter++;
}
}
That code may not be 100% correct, I just typed out a quick example, but you get the basic idea of what I'm doing to avoid that problem. Is there some other, more elegant solution to this problem?
Last edited on Jul 18, 2010 at 1:20am UTC
Jul 18, 2010 at 1:40am UTC
Probably something like this:
1 2 3 4 5 6 7
void RemoveProcess ( FuncIter Pos )
{
if ( LoopIter != NULL )
{
*LoopIter = CallbackList.erase ( Pos );
}
}
erase() returns an iterator pointing to the element
after the one removed, or end().
Jul 18, 2010 at 1:42am UTC
Derp. Did not know that.
In this case, I'd also need to decrement the loop iterator if it was the last element, but thanks for letting me know.
Jul 18, 2010 at 3:25am UTC
What you could do is set your list element to a null function pointer, rather than erasing it in RemoveProcess(), then in your ProcessEverything() function you could erase the null function pointers:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54
#include <list>
#include <iostream>
static std::list<void (*)()> CallbackList;
typedef std::list<void (*)()>::iterator FuncIter;
void funcA() { std::cout << "A" ; }
void funcB() { std::cout << "B" ; }
void func0() {} // null function
FuncIter AddProcess ( void (*callback)() )
{
CallbackList.push_back ( callback );
return --(CallbackList.end());
}
void RemoveProcess ( FuncIter& Pos )
{
*Pos = &func0; // mark for removal
}
void ProcessEverything ( )
{
FuncIter iter = CallbackList.begin ( );
while ( iter != CallbackList.end ( ) )
{
if (*iter == &func0)
{
iter = CallbackList.erase(iter); // remove keeping iter valid
}
else
{
(*iter)();
iter++;
}
}
}
int main()
{
AddProcess(&funcA);
AddProcess(&funcB);
AddProcess(&funcA);
ProcessEverything();
std::cout << " " << CallbackList.size() << std::endl;
RemoveProcess(++CallbackList.begin());
ProcessEverything();
std::cout << " " << CallbackList.size() << std::endl;
return 0;
}
ABA 3
AA 2
Last edited on Jul 18, 2010 at 3:27am UTC
Topic archived. No new replies allowed.