Home » Community » Forums » » Using Function Pointers
  Intel sponsors gamedev.net search:   
[Control Panel] [Register] [Bookmarks] [Who's Online] [Active Topics] [Stats] [FAQ] [Search]

Add Forum to Favorites |  Send Topic To a Friend | View Forum FAQ | Track this topic

Page:   1 2 »»

 Last Thread Next Thread 
 Using Function Pointers
Post Reply 
The Draw pointer-to-member is defined as a member variable, but is then used as if it were a non-member. Correct syntax would have been (turret.*(turret.Draw))(angle);

Using typedefs for the function types would have been a good idea.

So would have been pointing out that you cannot manipulate bound pointers-to-members (particularly, you can't store them).

 User Rating: 2027   |  Rate This User  Send Private MessageView Profile Report this Post to a Moderator | Link

Instead of using a series of if() statements, a single switch() statement would be better, for both code simplicity and performance:

   void SetState(int nNewState)
   {
      nState = nNewState;

      switch(nState)
      {
      case STATE_START:   Execute = Startup; break;
      case STATE_TITLE:   Execute = TitleScreen; break;
      case STATE_MMENU:   Execute = MainMenu; break;
      case STATE_RUNGM:   Execute = RunGame; break;

      // And just in case something goes wrong:
      default:            Execute = Abort; break;
      }
   }



Dirge of the Derelict
[Work - Egosoft] [Epoch Language] [Journal - Peek into my shattered mind]


 User Rating: 1950   |  Rate This User  Send Private MessageView ProfileView Journal Report this Post to a Moderator | Link

and i would rather use enums instead of defines when writing c++ code :) (which you are, while using classes)

m.

 User Rating: 1015    Report this Post to a Moderator | Link

Sweet sweet article. that was exactly what I wanted to hear. I was having questions about void pointers, and this saved me a trip to the forums. thanks!

 User Rating: 1260   |  Rate This User  Send Private MessageView Profile Report this Post to a Moderator | Link

cool article. although i think there would be absolutely no performance increase (i mean cmon, its an if statement man), i DO see how this makes things more readable, and more elegant.

Quote:
Original post by Fruny
So would have been pointing out that you cannot manipulate bound pointers-to-members (particularly, you can't store them).


could you explain this more? i dont understand what your talking about =)

 User Rating: 1321   |  Rate This User  Send Private MessageView ProfileView GD Showcase Entries Report this Post to a Moderator | Link

What he means by saying you can't store pointers-to-members (I think) is that you can't create a pointer-to-member in your program and hope to be able to use it without a pointer to the object itself handy. To clarify, with normal function pointers, you could do something like this:

void a_function()
{
cout

However, with pointer-to-member functions, a similar approach would *NOT* work... because the function you're calling needs a this pointer, you need an instance of your object to actually call your function pointer. Syntax looks something like this:

class some_class
{
public:
void a_function()
{
cout

One of the Enginuity articles had something it called a 'bound member functor', which pretty much encapsulates a member-to-function pointer and the object itself, and then overloads the () operator so you can use it like a normal function pointer.

 User Rating: 1015    Report this Post to a Moderator | Link

I haven't been here for a while, so I guess I wasn't logged in, and the system decided to eat most of my post because I used angle brackets instead of square ones for code. Oh well, I can't edit my AP post, so here it is:

What he means by saying you can't store pointers-to-members (I think) is that you can't create a pointer-to-member in your program and hope to be able to use it without a pointer to the object itself handy. To clarify, with normal function pointers, you could do something like this:
void a_function()
{
 cout<<"BAR!";
}

int main()
{
 void (*funcpointer)(void) = a_function;
 (*funcpointer)();
}


However, with pointer-to-member functions, a similar approach would *NOT* work... because the function you're calling needs a this pointer, you need an instance of your object to actually call your function pointer. Syntax looks something like this:
class some_class
{
public:
 void a_function()
 {
  cout<<"BAR!";
 }
};

int main()
{
 some_class MyObj;
 void (some_class::*funcpointer)(void) = &some_class::a_function;
 //Just calling (*funcpointer)() would not work
 (MyObj.*funcpointer)();

}


One of the Enginuity articles had something it called a 'bound member functor', which pretty much encapsulates a member-to-function pointer and the object itself, and then overloads the () operator so you can use it like a normal function pointer.

Something I meant to add - VS6 was very lax on how you assign and call pointers-to-members. I think VS7 is better about it, but I'm not positive. Anyway, the way they are assigned within the article:
if(HIGH_RES)
         Draw = DrawHiRes;
      else
         Draw = DrawLowRes;

will not compile with g++. Even though you're within the class, you still need to assign it as:
if(HIGH_RES)
         Draw = &CTurret::DrawHiRes;
      else
         Draw = &CTurret::DrawLowRes;


 User Rating: 1015   |  Rate This User  Send Private MessageView Profile Report this Post to a Moderator | Link

Quote:
Original post by graveyard filla
although i think there would be absolutely no performance increase (i mean cmon, its an if statement man), i DO see how this makes things more readable, and more elegant.


An if/else block is a series of comparison and conditional jump instructions in machine code. Any decent compiler can reduce a switch() with a bunch of linearly increasing cases (1, 2, 3, 4, etc. - like the state indices in the article) to a jump table, which is a simple bit of math and a jump. This is almost always more efficient than large if/else blocks because of the way branch prediction works. If you have any non-trivial state machine (say, 10 or more states) which changes state with any kind of frequency, this can make a huge performance difference between the elimination of branch mispredictions and cache misses.

See this article for details on how jump tables work, this one for a discussion on switch() performance at the machine code level, and this one for general optimizing information, which includes several mentions of switch() vs. if() performance.


Dirge of the Derelict
[Work - Egosoft] [Epoch Language] [Journal - Peek into my shattered mind]


 User Rating: 1950   |  Rate This User  Send Private MessageView ProfileView Journal Report this Post to a Moderator | Link

Or this for a 'self allocating linked list' of function pointers

 User Rating: 1015    Report this Post to a Moderator | Link

Actually the big increase in speed would be from entering the switch *only* when changing states, and skipping right to the chosen function in the main loop

As opposed to going trough the switch every single time in the loop.

while i see the performance increase, the benefit i see for gamedev is little, as these rendering switches usually are executed small number of times per frame anyway (not always tho).
What i'm interested on is that tiny comment about flags handling.
For example, if i have a zillion flags, how do i avoid checking each one with an 'if' statement?

example: renderer flags:

-render edges
-render console
-render shadows
-render FPS
-etc etc etc

disregarding shader logic, in the renderer i'd just ask for each flag. besides making each combination of flags a different member function and switching between them (a zillion flags make up for a bajillion combinations!!) how could this kind of thing be sped up using function pointers?

I always knew how to handle them... i just couldnt find any use for them

 User Rating: 1095   |  Rate This User  Send Private MessageView Profile Report this Post to a Moderator | Link

Nice article. I wish the author had shown the use of function pointers with an array (or vector or some such). I have seen function pointer used in such a way to greatly simplify code in business apps. This can significatly shorten conditional testing sections in certain cases. It can also make your code neater, more understandable, and therefore, easier to mantain.

 User Rating: 1074   |  Rate This User  Send Private MessageView Profile Report this Post to a Moderator | Link

Quote:
Original post by graveyard filla
Quote:
Original post by Fruny
So would have been pointing out that you cannot manipulate bound pointers-to-members (particularly, you can't store them).

could you explain this more? i dont understand what your talking about =)

See the expression obj.*pmf? As much as you might wish it be otherwise, the only thing you can use it for is an immediate call: (obj.*pmf)(args).

 User Rating: 2027   |  Rate This User  Send Private MessageView Profile Report this Post to a Moderator | Link

i use function pointers in my 3d engine because it api independant.
i've got a dll that handles ogl and another for d3d.
each dll contains a class derrived from my CApi class, and a function that creates an instance of their derrived classes (either COpenGL or CD3D), so my engine just loads the right dll then calls GetProcAddress to get the CreateNewApi func which it stores as a function pointer before calling it to init the 3d api of my choice ;)



 User Rating: 1038   |  Rate This User  Send Private MessageView Profile Report this Post to a Moderator | Link

Quote:
Original post by Madster
Actually the big increase in speed would be from entering the switch *only* when changing states, and skipping right to the chosen function in the main loop

As opposed to going trough the switch every single time in the loop.

while i see the performance increase, the benefit i see for gamedev is little, as these rendering switches usually are executed small number of times per frame anyway (not always tho).
What i'm interested on is that tiny comment about flags handling.
For example, if i have a zillion flags, how do i avoid checking each one with an 'if' statement?

example: renderer flags:

-render edges
-render console
-render shadows
-render FPS
-etc etc etc

disregarding shader logic, in the renderer i'd just ask for each flag. besides making each combination of flags a different member function and switching between them (a zillion flags make up for a bajillion combinations!!) how could this kind of thing be sped up using function pointers?

I always knew how to handle them... i just couldnt find any use for them


Well, I have a funciton pointer array, and my system just goes through and does what needs being done. I have it setup as a kernel/process type deal where you can add a process to the list, pause it, resume it, remove it. You can also set the amount of time to call it, for example: I currently use this to animate my water at specific intervals so it runs the same speed on all machines, yet doesn't need to update each and every frame. In your case, traversing a list would probably be just as slow as checking flags however, but if you generalize your functions a bit more it's worth it. Things like render console could easily be a new function in the list, while Draw FPS might just be a flag since you need only call a text/print function for it and probably over-kill to write a function for it. Render shadows is pretty hefty as well and could probably benefit from this method.

Another great thing about function pointers is this: I have a GUI I wrote, and I use function pointers attached to the command buttons. This way, when a button is clicked, whatever function I want called gets called. So, if I have a Quit button, I just create it with the Quit function as a parameter and it's good to go :).

 User Rating: 1053   |  Rate This User  Send Private MessageView Profile Report this Post to a Moderator | Link

Another good use for an array of function pointers is in a scripting system. For instance if a scripting system can call its host application's functions, calls in a script can be mapped to an index into an array of function pointers. Parameters may be an issue here, a function executer in the Virtual Machine can be created to push parameters appropriately.

Pseudo code with Pseudo VC++ like inline asm:

VMFuncExecuter(int funcIndex, ScriptParams *params)
{
__asm
{
push params[N]
[…]
push params[2]
push params[1]
call funcpntr[funcIndex]
}
}

just remember c calls push params in reverse order.

[Edited by - skyblu on July 2, 2004 5:40:25 PM]

 User Rating: 1039   |  Rate This User  Send Private MessageView Profile Report this Post to a Moderator | Link

I saw a comment above that mentioned that the performance increase might not be significant... depending on the code though, it could be. This gets a bit technical into the core of what a processor does, but it's pretty fascinating stuff actually... and it presents a big argument against having if statements. (Not that it matters a great deal, but it matters... or at least it did as of the Pentium II/III era. Does it still work this way with PIV on I wonder?)

The big thing about if statements is that they require the processor pipeline to attempt a "branch prediction" in order to process further instructions. You see, the processor can begin computing machine instructions several steps above the current one, as long as it knows absolutely what's coming up next (among other things).

Now, if it gets to an "if" statement it has to guess based on a complex algorhythm where the program might go. if it guesses right, operation continues at a normal pace. If not, the processor has to dump all of those preprocesses it was working on and continue fresh from there, without any instructions left in that buffer to keep it at full speed.

I know it has been this way for most of the Pentium era at least... but I don't know much about the PIV specs. Does anyone know if it still works this way, or if the PIV might have introduced a new way of doing it? I'm curious actually.

 User Rating: 1097   |  Rate This User  Send Private MessageView Profile Report this Post to a Moderator | Link

About the if vs switch performance debate the switch is way better most of the time but aren't we missing something here? Yes, this can possibly be a maintnace nightmare but I really don't think it should pose a problem.

pseudo (that is untested with fancier words ;)) code

enum eState {STATE_NULL, STATE_START, STATE_STOP, ...., COUNT_STATES}

void SetState( eState NewState)
{
  static StateFunPtr States[] = { Null, Start, Stop, ...};
  assert( (sizeof( States) / sizeof( *States)) COUNT_STATES);
  if( NewState < COUNT_STATES)//could get rid of this with an assert to....
     Execute = States[NewState];
}


You get the idea...

 User Rating: 1513   |  Rate This User  Send Private MessageView Profile Report this Post to a Moderator | Link

I"m glad that some people found the article helpfull.

I didn't think about using function pointer arrays, or more likely linked lists.

You could probably write a pretty handy class that maintains a few lists of function pointers for updates, drawing, and so on.
It would make adding new objects to a game pretty easy.


As for not using a typedef...well...typedefs are for commies.


"The paths of glory lead but to the grave." - Thomas Gray
My Stupid Blog
My Online Photo Gallery



 User Rating: 1062   |  Rate This User  Send Private MessageView Profile Report this Post to a Moderator | Link

Quote:
Original post by Ready4Dis
Another great thing about function pointers is this: I have a GUI I wrote, and I use function pointers attached to the command buttons. This way, when a button is clicked, whatever function I want called gets called. So, if I have a Quit button, I just create it with the Quit function as a parameter and it's good to go :).


Actually back in the DOS days i did a tiny 13h GUI library that attached void (void) functions to buttons, but without the STL i didn't bother going farther (the code was already unreadable enough).

now, reading all the posts i can clearly see how a list can make a difference with toggles. Unlike an array, the list can be very small and do just what's needed at that time, or grow according to the need.

And the scripting posts... thats priceless, i'll need to do that soon, and now it will be much easier with this. so thanks =D

 User Rating: 1095   |  Rate This User  Send Private MessageView Profile Report this Post to a Moderator | Link

Much nicer to look at if you use an inline interface function...

ie:
class CTurret {
public: 
void  DrawHiRes(float fAngle);
void  DrawLowRes(float fAngle);

// original Draw slightly modified //
void (CTurret::*pDraw)(float);

// the addition //
inline void Draw(float fAngle) { (*this.*pDraw)(fAngle); }

   void setup() {
      if(HIGH_RES)
         pDraw = DrawHiRes;
      else
         pDraw = DrawLowRes;
   }
};


Now you don't have to remember to dereference the pointer
when calling the function. You can just do this:
  CTurret *Turret;
  ...
  Turret->Draw(angle); 


 User Rating: 1009   |  Rate This User  Send Private MessageView Profile Report this Post to a Moderator | Link

Quote:
Original post by VThornheart
The big thing about if statements is that they require the processor pipeline to attempt a "branch prediction" in order to process further instructions. You see, the processor can begin computing machine instructions several steps above the current one, as long as it knows absolutely what's coming up next (among other things).


A processor doesn't "have" to use branch prediction -- it "gets" to use branch prediction. The issue is complex.

IF style:
In this style, the processor evaluates conditional branches until it finds a match. Modern two-level branch prediction algorithms are routinely in the neighborhood of 90% accurate for most branches. (Don't let your math background fool you, though: branch prediction accuracy isn't independent because branches are highly correlated -- so your branch prediction for three tight branches is generally higher than (0.9)^3). If a misprediction occurs, you have to discard the results of executing incorrect code and flush the pipeline. (IBM's got a nifty trick for chaining branches using condition code registers, but it's too much to go into here.)

SWITCH style:
A jump table is used, as specified before. Jump table prediction accuracy is generally somewhat lower than the if-style, but you don't have to worry about multiple branch predictions at the same time.

Virtual Function / Pointer-to-Function jump
The big problem inside the processor with these jumps is that the jump target isn't known until the value is produced, usually just an instruction or two beforehand. So once again you're predicting your jump target. This is one source of the virtual function performance hit that all C++ game programmers are warned about; it's generally small but it does exist.

As with anything else, the answer is: it depends. Depends on your architecture (MAC/IBM PowerPC will behave differently than x86, and different x86 flavors have different branch prediction performance characteristics.)

My first post, feel free to heckle...

 User Rating: 1015    Report this Post to a Moderator | Link

Quote:
Original post by griffenjam
As for not using a typedef...well...typedefs are for commies.


LOL! That WAS technical :D

 User Rating: 1412   |  Rate This User  Send Private MessageView Profile Report this Post to a Moderator | Link

Quote:

For the longest time I didn't even think about functions pointers until I was looking at a state machine one day and wished that instead of having a switchboard of if statements that executed single functions based on the state of the program, the class would just automatically execute the function appropriate for the current state. I realized that I could accomplish this with function pointers. I will create a small example class with various member function and a state changing function that will switch the current execute function. This is a good example of how to use function pointers to control the flow of a program and eliminating the if statements that you hit every time you call that function

uhh... i read the article. but i still didn't see the difference between
if (state == OVER)
   gameOver();
else if (state == DEAD)
   restartLevel();
else if (state == GOAL)
   loadNextLevel();


and

if (state == OVER)
   gameState = gameOver();
else if (state == DEAD)
   gameState = restartLevel();
else if (state == GOAL)
   gameState = loadNextLevel();


in both you're still using if statements and they still do the same thing: go through the if statement until they find a match, then execute the function.

 User Rating: 1750   |  Rate This User  Send Private MessageView ProfileView Journal Report this Post to a Moderator | Link

could someone help me out on this?

 User Rating: 1750   |  Rate This User  Send Private MessageView ProfileView Journal Report this Post to a Moderator | Link
Page:   1 2 »»
All times are ET (US)

Post Reply
 Last Thread Next Thread 
Forum Rules:
You may not post new threads
You may post replies
You may not edit your posts
You may not use HTML in your posts
Jump To:
Administrative Options: