1

I have a code like this

typedef void(_stdcall * MyProcessor)(int, int);

void FunctionProcess (MyProcessor process){
    MyProcessor myCallback;
    myCallback = (process != NULL)? process:"<functionThatDoesNothing>";
    ...
}

If there won't be any callback function in the argument, I'd like to assign some function to myCallback, which would do nothing (or little something), because afterwards, I'm calling this function in loop (and I'd like to avoid 'if' in the loop because of the pipeline flush). I've tried a no-op lambda with no success (incompatible).

Are there any functions like this? Are there any other possibilities? Thank you.

Community
  • 1
  • 1
DropDropped
  • 1,253
  • 1
  • 22
  • 50

3 Answers3

5

Your logic is insane! If the if is correctly-predicted it will be nearly free. If the indirect jump is incorrectly predicted, it will be horrible. An if is much easier to predict than an indirect jump (only two possibilities, speculative execution is possible, there are more prediction slots on most CPUs). So there are pretty much no conceivable circumstances where this makes sense.

David Schwartz
  • 179,497
  • 17
  • 214
  • 278
  • 1
    Sorry, cargo cult programming really gets under my skin. – David Schwartz Aug 27 '12 at 08:50
  • @David - Blunt and to the point. Why not call a spade a space?! – Ed Heal Aug 27 '12 at 08:53
  • Note that logic cannot be insane. Logic can be flawed or wrong. People can be insane. – bitmask Aug 27 '12 at 08:53
  • @bitmask: Actually, "illogical" is a synonym for "insane". So it could be understood as "what you are presenting as logic is in fact illogical". But I see your point. – David Schwartz Aug 27 '12 at 08:57
  • @DavidSchwartz did you mean to say that it's computationally cheaper to check for NULL when the callback has to be called than to pass an empty function as a callback? – Qnan Aug 27 '12 at 09:50
  • @Qnan: Sort of, but not quite. The comptuational cost has to do with how predictable they are. If they're both very well predicted, there won't be much computational difference. My point is more that this is like setting your house on fire to make sure you don't waste your fire extinguisher on a house that's not burning. *If* the branch would cause pipeline flushes, the indirect jump would be very likely to be many times worse because it's much harder to predict. – David Schwartz Aug 27 '12 at 10:13
  • @DavidSchwartz I agree with this point, but I think this is not quite relevant here. The OP doesn't mention the reasons for doing what they want to do and I can think of at least a couple of logical ones that have nothing to do with efficiency. It could be that the callback is passed to some [legacy] algorithm, which does not expect NULL for this callback. Or it might be that the callback is invoked in multiple places in the code and it's desirable not to check every time. – Qnan Aug 27 '12 at 11:26
  • @DavidSchwartz Finally, I would expect that the performance penalty in question would only have serious impact if the callback is used in a performance-critical part of the application and is invoked often. – Qnan Aug 27 '12 at 11:27
  • 1
    @Qnan: OP says "I'd like to avoid 'if' in the loop because of the pipeline flush". This is cargo cult programming: *I heard that X was bad but never really understood why, so I'll replace it with something that's much worse for that very same reason*. – David Schwartz Aug 27 '12 at 11:28
1

Write an empty function with the signature you want.

void __stdcall pass(int a, int b) 
{
}
Qnan
  • 3,714
  • 18
  • 15
0
typedef void(_stdcall * MyProcessor)(int,int);

void _stdcall noop(int,int) {}

void functionProcess (MyProcessor process){
    MyProcessor const myCallback = process?process:noop;
    myCallback(7,4);
}
bitmask
  • 32,434
  • 14
  • 99
  • 159