www.digitalmars.com         C & C++   DMDScript  

digitalmars.D - skipping a statemnet from inside a repeating block

reply "Gopan" <Gopan.Gopalakrishnan gmail.com> writes:
Dear Friends,

I have a callback function which will be called back so many 
times, say at every second for a week.

void TimerCallback(int number)
{
     Statement_1;

     if(number == MY_MAGIC_NUMBER)
     {
         /*
         I have been waiting for this so far.  Now, I have got 
want I want.		
         So, I don't want to execute the the above if condition 
for further callbacks.

         IS THERE ANY TECHNIQUE by which I can say HERE that,
         from Statement_1, the control can directly go to 
Statement_3,
         skipping the evaluation of the above if condition?
         If it is not possible, is it a limitation at the
         micro-processor architecture level?
         */
     }

     Statement_3;
}

Thank you.
Feb 14 2013
next sibling parent reply "John Colvin" <john.loughran.colvin gmail.com> writes:
On Thursday, 14 February 2013 at 13:14:47 UTC, Gopan wrote:
 Dear Friends,

 I have a callback function which will be called back so many 
 times, say at every second for a week.

 void TimerCallback(int number)
 {
     Statement_1;

     if(number == MY_MAGIC_NUMBER)
     {
         /*
         I have been waiting for this so far.  Now, I have got 
 want I want.		
         So, I don't want to execute the the above if condition 
 for further callbacks.

         IS THERE ANY TECHNIQUE by which I can say HERE that,
         from Statement_1, the control can directly go to 
 Statement_3,
         skipping the evaluation of the above if condition?
         If it is not possible, is it a limitation at the
         micro-processor architecture level?
         */
     }

     Statement_3;
 }

 Thank you.

Not internally to the function, no. In truth, there's no need to do this. Branch prediction (http://en.wikipedia.org/wiki/Branch_predictor) should reduce the cost hugely. Also, a comparison is only going to be 1 cycle, saving a single cycle per second is irrelevant.
Feb 14 2013
parent Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> writes:
On 2/16/13 12:21 PM, Gopan wrote:
 For iterating through a ranges of indices in a circular way, I have seen
 people coding like

 int i=0;
 while(true)
 {
 ...
 i = (i+1)%10;
 }

 People argue i = (i+1)%10 is less costly to the combination below.
 ++i;
 if(i==10)
 i = 0;

 If the comparison instruction takes only one cycle, how is this argument
 correct? Please let me know if that argument is incorrect.

 Thanks,
 Gopan.

The general argument is that code with branches may be slower than straight-line code on superscalar architectures. In this particular case the test-based code is likely to be cheaper, which can be easily shown by profiling. For details paste this: uint fun1(uint x) { return (x + 1) % 10; } uint fun2(uint x) { return x == 10 ? 0 : x + 1; } into http://d.godbolt.org and take a look at the generated code. It contains no jumps. Andrei
Feb 16 2013
prev sibling next sibling parent "Andrea Fontana" <nospam example.com> writes:
On Thursday, 14 February 2013 at 13:14:47 UTC, Gopan wrote:
 Dear Friends,

 I have a callback function which will be called back so many 
 times, say at every second for a week.

 void TimerCallback(int number)
 {
     Statement_1;

     if(number == MY_MAGIC_NUMBER)
     {
         /*
         I have been waiting for this so far.  Now, I have got 
 want I want.		
         So, I don't want to execute the the above if condition 
 for further callbacks.

         IS THERE ANY TECHNIQUE by which I can say HERE that,
         from Statement_1, the control can directly go to 
 Statement_3,
         skipping the evaluation of the above if condition?
         If it is not possible, is it a limitation at the
         micro-processor architecture level?
         */
     }

     Statement_3;
 }

 Thank you.

Maybe you can write 2 different callbacks, one with if, one without and switch between them. Maybe with a compile-time code generation to avoid code repetitions... Just for a int comparison or is it a different long operation?
Feb 14 2013
prev sibling next sibling parent "Diego" <beosman gmail.com> writes:
On Thursday, 14 February 2013 at 13:14:47 UTC, Gopan wrote:
 Dear Friends,

 I have a callback function which will be called back so many 
 times, say at every second for a week.

 void TimerCallback(int number)
 {
     Statement_1;

     if(number == MY_MAGIC_NUMBER)
     {
         /*
         I have been waiting for this so far.  Now, I have got 
 want I want.		
         So, I don't want to execute the the above if condition 
 for further callbacks.

         IS THERE ANY TECHNIQUE by which I can say HERE that,
         from Statement_1, the control can directly go to 
 Statement_3,
         skipping the evaluation of the above if condition?
         If it is not possible, is it a limitation at the
         micro-processor architecture level?
         */
     }

     Statement_3;
 }

 Thank you.

You can use static variables inside that function: void TimerCallback(int number) { statement_1; static bool i_found_my_magic_number = false; if(!i_found_my_magic_number && number == MY_MAGIC_NUMBER) { i_found_my_magic_number = true; // Do what you need. } statement_3; } Static variables does not lose its value over different function calls, so you can use it to control what happen inside functions over calls without using global variables. Hope that helps.
Feb 15 2013
prev sibling next sibling parent "Gopan" <gopan.gopalakrishnan gmail.com> writes:
On Thursday, 14 February 2013 at 16:57:17 UTC, Andrea Fontana 
wrote:
 Maybe you can write 2 different callbacks, one with if, one 
 without and switch between them.

I like that idea. But it is less elegant. For example, for a timer callback, I may have to restart the timer with a new callback function. Instead of a single callback, if it is a event subscription, other subscribers will be affected.
 Maybe with a compile-time code generation to avoid code 
 repetitions...

I am looking for a more generic solution. It should work with within a loop also. Just for the sake of achieving it I will have to put those statements in a function, call it with function pointer, etc. while(true) { ... Statement_1; if(i == MY_MAGIC_NUMBER) { //done with this. } Statement_3; ... }
 Just for a int comparison or is it a different long operation?

Thanks, Gopan
Feb 16 2013
prev sibling next sibling parent "Gopan" <gopan.gopalakrishnan gmail.com> writes:
On Friday, 15 February 2013 at 09:02:06 UTC, Diego wrote:

 You can use static variables inside that function:

 void
 TimerCallback(int number) {
     statement_1;

     static bool i_found_my_magic_number = false;

     if(!i_found_my_magic_number && number == MY_MAGIC_NUMBER) {
         i_found_my_magic_number = true;
         // Do what you need.
     }

     statement_3;
 }

 Static variables does not lose its value over different 
 function calls, so you can use it to control what happen inside 
 functions over calls without using global variables.

 Hope that helps.

Dear Diego, Thanks for caring to reply. In fact, it is not a business requirement or something like that. My question is purely on academic interest. The if_condition being costly is not exaclty what I want to escape from. I am thinking why I am forced to execute the condition, when I know that I will not be benefited. Thanks, Gopan.
Feb 16 2013
prev sibling next sibling parent "Gopan" <gopan.gopalakrishnan gmail.com> writes:
On Thursday, 14 February 2013 at 13:29:07 UTC, John Colvin wrote:

 Not internally to the function, no.

 In truth, there's no need to do this. Branch prediction 
 (http://en.wikipedia.org/wiki/Branch_predictor) should reduce 
 the cost hugely.

 Also, a comparison is only going to be 1 cycle, saving a single 
 cycle per second is irrelevant.

have seen people coding like int i=0; while(true) { ... i = (i+1)%10; } People argue i = (i+1)%10 is less costly to the combination below. ++i; if(i==10) i = 0; If the comparison instruction takes only one cycle, how is this argument correct? Please let me know if that argument is incorrect. Thanks, Gopan.
Feb 16 2013
prev sibling next sibling parent "Gopan" <gopan.gopalakrishnan gmail.com> writes:
Let me ask the question more specifically, with an example of 
assembly version.
Consider the function below.

void Test()
{
     int x, y, z;

     x = 1;
     if(x==1)
         y=2;
     else
         y=3;
OtherStuff:
     z = 4;
}
---------------
     x = 1;
012313BE  mov     dword ptr [x],1
     if(x==1)
012313C5  cmp     dword ptr [x],1
012313C9  jne     Test+34h (12313D4h)
         y=2;
012313CB  mov     dword ptr [y],2
     else
012313D2  jmp     OtherStuff (12313DBh)
         y=3;
012313D4  mov     dword ptr [y],3
OtherStuff:
     z = 4;
012313DB  mov     dword ptr [z],4


The assembly instruction corresponding to 'if(x==1)' is
012313C5  cmp     dword ptr [x],1

So, if I am able to change the instruction at this address during 
run-time to
012313C5  jmp     OtherStuff (12313DBh)

Then, I will be able to permanently skip the condition checking.  
Right?
Why is this not possible?

All the languages I have heard about allow the programmer to 
change only the data in memory; not the instructions.  The 
programmer's thought process is controlled by this idea, 
subconsciously.
Why can't we change the instructions at runtime?  Is there any 
fundamental issue with that?
Is it possible to do it through direct assembly coding?

Thanks,
Gopan
Feb 16 2013
prev sibling parent "John Colvin" <john.loughran.colvin gmail.com> writes:
On Saturday, 16 February 2013 at 17:03:30 UTC, Gopan wrote:
 On Thursday, 14 February 2013 at 16:57:17 UTC, Andrea Fontana 
 wrote:
 Maybe you can write 2 different callbacks, one with if, one 
 without and switch between them.

I like that idea. But it is less elegant. For example, for a timer callback, I may have to restart the timer with a new callback function. Instead of a single callback, if it is a event subscription, other subscribers will be affected.
 Maybe with a compile-time code generation to avoid code 
 repetitions...

I am looking for a more generic solution. It should work with within a loop also. Just for the sake of achieving it I will have to put those statements in a function, call it with function pointer, etc. while(true) { ... Statement_1; if(i == MY_MAGIC_NUMBER) { //done with this. } Statement_3; ... }
 Just for a int comparison or is it a different long operation?

Thanks, Gopan

for a loop: while(true) { Statement_1; if(magic) { //do something with magic Statement_2; break; } Statement_2; } while(true) { Statement_1; Statement_2; } Simple (assuming that the break in the if statement is the only way out of the loop). The code repetition can be easily removed by making Statement_1 and Statement_2 mixins. Remember that D is a compiled language, you can't change the instructions at runtime so there is no way to edit out the if statement at a runtime-dependant time. You have to specify a whole new code path to follow (i.e. the second while loop).
Feb 16 2013