13

If, like me, you shiver at the site of a While (True) loop, then you too must have thought long and hard about the best way to refactor it away. I've seen several different implementations, none really better than any other, such as the timer & delegate combination.

So what's the best way you've come up with or seen to refactor the dreaded While (True) loop?

Edit: As some comments mentioned, my intent was for this question to be an "infinite loop" refactoring, such as running a Windows style service where the only stop conditions would be OnStop or a fatal exception.

Jeff Schumacher
  • 3,126
  • 3
  • 23
  • 23
  • I should have worded this better, and thought about going back to do that, but it's a continual learning process, so I decided to leave the question as is as a reminder to myself. :) – Jeff Schumacher Oct 30 '08 at 23:02
  • 3
    If you "dread" while(true), you must be writing very simplistic algorithms. Most advanced algorithms require loops with multiple exit conditions. The most natural way to do this is to have an outer infinite loop and then multiple exit conditions that break out of the loop. Using For-loops or while-conditions work best when you only have a single exit condition. Although that is the most common case, it is hardly the universal situation. – Tyler Durden Feb 20 '17 at 19:59

12 Answers12

64

My preference would be

start:

   // code goes here

goto start;

This most clearly expresses the intent. Good luck getting it past your coding standards. (Wonder how much karma this is going to cost me).

idmean
  • 14,540
  • 9
  • 54
  • 83
fizzer
  • 13,551
  • 9
  • 39
  • 61
  • 6
    How does this better express your intent than a `while(true)` loop? On the other hand you didn't mention the drawbacks of your solution. So yes, all in all, this is a pretty crappy code. – Konrad Rudolph Oct 29 '08 at 08:21
  • 26
    The intent is an unconditional branch to start. 'goto' is specifically for that purpose. 'While' supports conditional branches. By calling it with a degenerate always-true condition, and relying on the compiler to optimize it away, you are an extra step removed from expressing what you mean. – fizzer Oct 29 '08 at 08:45
  • 7
    As for drawbacks, there are no technical ones. If you need a scope, put some braces in. If you don't, don't. (Assumes C or C++ - OP doesn't specify a language). – fizzer Oct 29 '08 at 08:47
  • I voted it up because that seemed like the thing to do. for (;;) says conditionless loop to me. – Tom Hawtin - tackline Dec 02 '08 at 14:38
  • 5
    You're gonna need another `goto` to break out of the loop... getting complex? – Amarghosh May 28 '10 at 11:55
  • 9
    @Amarghosh: If you need to break out of the loop, then it's not really an infinite loop; if you are using `while (true)` for such things you are doing something wrong. – Dan Moulding Aug 18 '10 at 15:53
  • 4
    `start:...goto start;` is subtly different than `while(1){...}`. In the latter, `break;` exits from the loop while in the former, `break;` exits from the parent loop (or parent switch/case). – ceilingcat Sep 06 '17 at 21:06
28

Do we really need to refactor while(true) loops? Sometimes it's a coding standard and most of the developers has got used to this structure. If you have to think hard on how to refactor this code, are you sure it's a good idea to refactor it?

Goto used to be a black sheep in coding standards. I've met algorithms where goto made the code much more readable and shorter. Sometimes it doesn't worth to refactor (or better to use goto).

On the other hand you can avoid while(true) most of the time.

artur02
  • 4,469
  • 1
  • 22
  • 15
23

What's so dreaded about it? Try finding a common break condition and refactor it to be the head of the loop. If that's not possible – fine.

Konrad Rudolph
  • 530,221
  • 131
  • 937
  • 1,214
18

When I encounter a while(true) loop, that tells me either

  1. the break condition is not easily tested at the top (or bottom) of the loop,
    • there are multiple break conditions,
    • or the prior programmer was too lazy to factor the loop properly.

1 and 2 means you might as well stick with while(true). (I use for(;;), but that's a style thing in my opinion.) I'm with another poster, why dread this? I dread tortored loops that jump through hoops to get the loop rolled "properly".

Jim Nelson
  • 1,688
  • 3
  • 15
  • 27
14

Replace True with the condition you were going to use to break out of the loop.

In the case of a service or background thread, you might use:

volatile bool m_shutdown = false;
void Run()
{
    while (!m_shutdown)
    { ... }
}
Jon B
  • 51,025
  • 31
  • 133
  • 161
  • 2
    Sometimes people do this for services, where execution is meant to continue indefinitely and is only broken OnStop or an exception. So there IS no condition. – Grank Oct 28 '08 at 19:17
  • 1
    I think the question is more targeted at the semi common pracitice of infinite looping when you are actually intending to do it a finite amount of times (ignoring things like threads etc) its just perhaps the end condition is complicated. – Keith Nicholas Oct 28 '08 at 19:19
  • In forth, there is the "BEGIN X WHILE Y REPEAT" where the condition is in the middle of the loop. This type of loop construct isn't easily converted to a more traditional "while{}" or "do {} while" loop. – Torlack Oct 28 '08 at 19:22
  • 1
    I don't agree; the mention of the timer & delegate method would seem to suggest that the question is more targeted at a desired indefinite looping – Grank Oct 28 '08 at 19:23
  • @Grank - Yes! I need to edit this question to be more specific. – Jeff Schumacher Oct 28 '08 at 19:24
14

Why refactor? And what is so "dreadful" about this construct? It is widely used, and well understood.

If it ain't broke, don't fix it.

Ken Ray
  • 2,500
  • 3
  • 21
  • 28
  • I would take that sentiment farther - the main measure of success is working code. Sometimes while(true) is the obvious solution, in a lot of environments "it works and is easy to read" is enough – Tadgh Wagstaff Mar 20 '22 at 17:09
8

The "running forever" situation is sometimes part of a larger state machine. Many embedded devices (with run-forever loops) don't really run forever. They often have several operating modes and will sequence among those modes.

When we built heat-pump controllers, there was a power-on-self-test (POST) mode that ran for a little while. Then there was a preliminary environmental gathering mode that ran until we figured out all the zones and thermostats and what-not.

Some engineers claimed that what came next was the "run-forever" loop. It wasn't really that simple. It was actually several operating modes that flipped and flopped. There was heating, and defrosting, and cooling, and idling, and other stuff.

My preference is to treat a "forever" loop as really just one operating mode -- there may be others at some point in the future.

someMode= True
while someMode:
    try:
        ... do stuff ...
    except SomeException, e:
        log.exception( e )
        # will keep running
    except OtherException, e:
        log.info( "stopping now" )
        someMode= False

Under some circumstances, nothing we've seen so far sets someMode to False. But I like to pretend that there'll be a mode change in some future version.

S.Lott
  • 384,516
  • 81
  • 508
  • 779
8
#define ever 1
for (;ever;)

?

Meh, just leave it how it is, while (true) is probably as legible as you're going to get..

Andrew Coleson
  • 10,100
  • 8
  • 32
  • 30
  • 1
    I hate abuse of "for" loops like that. There is a semantic for which the "for" loop was designed, (essentially a from - to semantic) and I think we should stick to that. What you're doing here is forcing a "while" semantic into the "for" keyword. At least the #define makes it marginally tolerable. – Chris Cudmore Nov 03 '08 at 19:02
  • 8
    if we're to go that ugly, why not "#define FOREVER while(1)" or something like that :) – utku_karatas Dec 12 '08 at 05:11
  • 1
    Shorter and uglier : `for(;"ever";)` – ShellCode May 26 '21 at 11:38
5

errr, to be a refactoring.....

  • Replace Infinite Loop with Infinite Recursion :-)

well, if you have a language that supports Tail calls....

Keith Nicholas
  • 43,549
  • 15
  • 93
  • 156
4

If you want it to continue indefinitely until a total abortion of program flow, I don't see anything wrong with while (true). I encountered it recently in a .NET data collection service that combined while (true) with thread.sleep to wake up every minute and poll the third-party data service for new reports. I considered refactoring it with a timer and a delegate, but ultimately decided that this was the simplest and easiest-to-read method. 9 times out of 10 it's a clear code smell, but when there's no exit condition, why make things more difficult?

Grank
  • 5,242
  • 7
  • 33
  • 36
2

I don't mind it when the infinite loop is contained within a window, and dies with the window.

Think of the Hasselhoff Recursion.

Chris Cudmore
  • 29,793
  • 12
  • 57
  • 94
-2
void whiletrue_sim(void)
  {
    //some code
    whiletrue_sim();
  }

Warning: Your stack may overflow.

S.S. Anne
  • 15,171
  • 8
  • 38
  • 76
  • While this code block may answer the question, it would be best if you could provide a little explanation for why it does so. – Rakete1111 May 18 '16 at 13:06
  • just read the code. I am bad with words and if you dont understand this simple code i cant explain it better. It just so that your stack may be overflow, dependent on language, optimizer or how your interpreter work. – 12431234123412341234123 Jun 09 '16 at 11:08