get out of the loops?

Pages: 12
Actually.... an online friend of mine had a very efficient use of goto in his NES emulator:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
switch (cpu.opcode)
{
  case lda_imm:
    get_imm();
    goto lda;
  case lda_zp:
    get_zp():
    goto lda;
  case adc_imm:
    get_imm();
    goto adc;

  lda: /* do stuff */
    break;
  adc: /* do stuff */
    break;
}


The first time I looked at this I was like "wtf, goto?", but as I thought about it, it started to make more and more sense.

*) There are 256 opcodes (256 cases in that switch) but most of them are different addressing modes of the same instruction. IE: ADC immediate vs. ADC absolute.

*) As this is a CPU emulator, it will run this switch statement hundreds of thousands of times per second, so it needs to be quick.

*) ADC/LDA/etc instructions all have the same code in them, so repeating the same code multiple times is no good.

*) Putting ADC/LDA/etc code in separate (non-inline) functions has a lot of unnecessary overhead.

*) Putting ADC/LDA/etc code in inline functions inflates code size, potentially slowing it down (remember that this switch is going to have 256 cases -- if you're inlining both the addressing mode code as well as the instruction code it'll be huge)

*) Goto allows you to share code while keeping the switch size minimal, and without adding the overhead of function calls.



So it just goes to show you. Don't write off a language feature just because it's "evil". Here, it's actually not that bad of an idea.

Although now I wonder if another switch statement would be better....

oh well that's a topic for another forum!
Good. But don't expect anyone else to support it.
Goodness, I seem to have caused quite a stir!
I personally don't find any issue with retyping the code; you really aren't causing any more code execution than you would normally need to. It's a question of efficiency. Does the use of break streamline the code sufficiently to counter the potential disruption of flow? What is worse, retyping the code or adding a break? (Undeniably, if you are dealing with tons of code it's much cleaner to use a break. But in little situations I would rather skip it.)
I'm putting it out there at least. There is always a workaround; whether or not to use it is quite another matter.
http://www.cplusplus.com/forum/lounge/12155/page2.html#msg61551

As for the break/copy-paste issue, code repetition should be avoided as often as possible, not because of efficiency, but because of maintainability. Even when the pieces are close to one another, it's still a hassle to change both when you need to make changes, and it also open up the possibility of making mistakes. When the pieces are far from each other it's even worse. You might end up changing one but not the other at different circumstances, each version evolving separately into eventually completely different entities.
Wouldn't you just add the condition in the for's specs?
e.g:

1
2
3
4
for (int i=0;i<10;i++) {
cout << i;
}
//rest of the code 


why would you want this? :

1
2
3
4
5
6
7
8
for (;1==1;;) {
int i = 0;
cout << i;
i++;
if (i=>10) {
break;
}
}

As for the break/copy-paste issue, code repetition should be avoided as often as possible, not because of efficiency, but because of maintainability. Even when the pieces are close to one another, it's still a hassle to change both when you need to make changes, and it also open up the possibility of making mistakes. When the pieces are far from each other it's even worse. You might end up changing one but not the other at different circumstances, each version evolving separately into eventually completely different entities.


Very good point. I had not thought about that.
As for kibestar's post, you wouldn't. That is definitely an example of poor use of break.
(If you want to do an infinite loop, better style would be
for (;;)
or
while(true)
Someone said something about this somewhere.)
why would you want this? :

because limiting yourself to common loop usage requires planning and possibly changing existing lines, if you had already started coding. it takes lots of time. loops get complex. we run out of coffee.

i'm surprised anyone is concerned about duplicate code. repetition of code is traditionally avoided by adding functions or restructuring, right? this is the first time i've heard of break being used like that.
Code is written once, and read many times. Using a goto because you'd otherwise run out of coffee is unacceptable and ought to fail any quality review.

There are times when judicious use of goto is the better way to solve a problem, but those circumstances do not occur in the realm of normal front end application development. It is quite possible that Dish's example from a NES emulator may well be one of those cases, but the other examples/reasons cited in this thread are down right irresponsible.

Computer software isn't only written and used by engineers/geeks/hackers who understand software failings. Most software is used by the general public who expect software to work as reliably as an electric iron. My Panasonic TV runs Linux. The systems have to be right, and you don't get to that state by cutting corners.
Hi!

And what are your opinion about exceptions?

Once I had to use more neasted loops (for numeric calculation) and I resolved the exiting with exception. Was it good techiques or not?

Like this:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
try
{
  for(...)
  {
     for(...)
     {
        for(...)
        etc.
        if (user_wantto_immediately_exit)throw 1;
     }
  }
}
catch(int x)
{
}


Thanks.
Exceptions are used to communicate typed errors. If I were running that code review, you'd be rewriting it.
Last edited on
It's funny you should mention Linux. Its code is riddled with gotos.
http://www.kernel.org/pub/linux/docs/lkml/#s15-5

And yeah, that's awful. I'll take gotos before that.
It does beg the question, why is that function so complex? That comes down to poor design being compensated for with bad code.
Topic archived. No new replies allowed.
Pages: 12