Is it okay if I use a lot of while(true) loops?

P

Phlip

Really? You can only execute 1 per thread, so how many are you going to
have in any given application (I highly doubt it's more than a handful)?

Things like 'loop and a half' and loops with complex exit conditions
where break simplifies things are orders of magnitude more common (of
course, I haven't worked in any environment where break was banned).

I suspect he meant "common in the industry", such as a service thread,
not "common in an application".
 
P

Phlip

  You could always do it like:

    while(codeThatReturnsAResult() &&
          someMoreCodeWhichAlwaysReturnsTrue())
    {}

and implement those functions appropriately (passing all necessary local
variables as references, as necessary).

"passing all necessary local variables as references" is why I
suggested Method Object Refactor.
 
P

Phlip

Some people want to implement that as:

while (true) {
   codeA();
   if (!codeB()) break;
   codeC();
}

It's 4 lines. Kanze would have a problem with it. I'd have a problem
with something much longer than 4 lines.

So we get back to What if your boss reviews your code, dislikes it,
and is wrong. I'm sure Kanze never had that problem... (-:
 
D

Daniel

I suspect he meant "common in the industry", such as a service thread,
not "common in an application".

Although service threads are often constructed as

while (!aborted)
{
}

if you want to provide a less brutal way to abort them.

-- Daniel
 
D

Daniel

  You could always do it like:

    while(codeThatReturnsAResult() &&
          someMoreCodeWhichAlwaysReturnsTrue())
    {}

and implement those functions appropriately (passing all necessary local
variables as references, as necessary).

  Now you have the ending condition nicely in the while loop.
And as a bonus, your code is significantly more obfuscated
and harder to follow.

:)
 
D

Daniel

At the top of the loop, you say it's forever.  If it's
not, then you've lied to the reader of your program.
Of course, if that was your only objection, then the following should
suffice:

const int loop_until_you_can_loop_no_more = 1;

while (loop_until_you_can_loop_no_more)
{
...
}

I don't think that's your only, or main, objection, though.

-- Daniel
 
D

Daniel

let's replace while(true) with while(activating()),
where the activating() method (under a better name) contains whatever
the top half of the loop was doing.
I think you mean activating() to mutate state, which may not be
desirable.

-- Daniel
 
P

Phlip

while (!aborted)
{
}

if you want to provide a less brutal way to abort them.

-- Daniel

Kanze _should_ bust on that, and so I'll do it for him.

All statements should be as positive as possible, starting with
conditionals.

while (gracefully_threading)
{
}
 
P

Phlip

I think you mean activating() to mutate state, which may not be
desirable.

-- Daniel

Ah, functions are procedures are magically different, and the ones
that return values, _especially_ when used as booleans, should not
mutate state. Sorry I forgot!
 
P

Phlip

Ah, functions
and

procedures are magically different, and the ones
that return values, _especially_ when used as booleans, should not
mutate state. Sorry I forgot!
 
D

Daniel

Ah, functions are procedures are magically different, and the ones
that return values, _especially_ when used as booleans, should not
mutate state. Sorry I forgot!

Well, if you're worried about being scolded by Meyer, you could write

while (activating.isActive())
(
)

But I'm more narrow minded than that, I don't want to mutate any state
at all.

-- Daniel
 
J

James Kanze

Ah, functions are procedures are magically different, and the
ones that return values, _especially_ when used as booleans,
should not mutate state. Sorry I forgot!

The function called in a condition shouldn't mutate state. It's
too confusing. (There are exceptions, really only acceptable
because of their ubiquity.) The "correct" way to write a loop
and a half is:

firstHalf();
while ( ! endCondition ) {
secondHalf();
firstHalf();
}

(Very schemetized, of course.) In practice, I would stick with
this pattern for general cases. There are some specific,
consecrated exceptions, however, and like everyone else,
I write:

std::string line;
while ( getline(in, line) ) {
// ...
}

(rather than the "cleaner":

std::string line;
getline( in, line );
while ( ! in.fail() ) {
// ...
getline( in, line );
}

..)

Unless it is an idiom as ubiquious as the while (getline) idiom,
however, I'll use the second pattern. Writing it more often as
a for loop:

for ( declaration = initialValue();
! endCondition;
declaration = nextValue ) {
// ...
}

What I will say, too, is that while things like:

while ( true ) {
firstHalf();
if ( endCondition )
break;
secondHalf();
}

are confusing, and should be avoided, if the code in firstHalf
and secondHalf is complicated enough for the confusion to be
important, then you have a real problem there as well.
 
J

James Kanze

Nobody in his sane mind should write a "for(;;)" or
"while(true)" loop meaning it as a "pseudo-truly infinite
loop" (I mean, without any "break", "return" or similar within
the loop itself),

That's the only time "for (;;)" or "while ( true )" are really
acceptable. (Now let's watch the hackers come out of the
woodwork.)
 
J

James Kanze

On Aug 21, 5:03 pm, "Alf P. Steinbach /Usenet" <alf.p.steinbach
(e-mail address removed)> wrote:

[...]
Then you get contortions & redundancy for common loop-and-a-half loops.

That's what is commonly said. But all of the examples end up
showing that if you write functions which are too complex, there
is no clean solution.

[...]
I think we had the discussion about loop-and-a-half at least
twice before, and you've been partially convinced by some
example like
for( ;; )
{
showGameState();
cmd = usersCommand();
if( cmd == exitCmd ) { break; }
doCommand( cmd );
}

No. The cleanest way to write this would be:

for ( Command cmd = usersCommand();
cmd != exitCmd;
cmd = usersCommand() )
doCommand( cmd );
}

What I have said, however, is that *if* the code in question was
complicated enough for the difference to make the function
actually unreadable (supposing it was correctly
formatted---putting the break at the end of the line is
definitely additional obfuscation, and makes your version
unreadable), then the real problem is that the function is too
complicated. Similarly, all of the examples I've seen arguing
that the break (or a goto) simplifies the code start from the
premise of a too complicated function.
Of course you can create monstrosity like
showGameStateAndGetUsersCommand and call that in a 'while'
loop head as checking expression with side effects.
Or you can put a call to showGameState() before the loop,
which is redundancy,

I think you're exagerating the redundancy argument, given that
it's a single function call. And that the first call is used to
initialize (construct) a variable, where as the others assign to
it.
 
F

Francesco S. Carta

That's the only time "for (;;)" or "while ( true )" are really
acceptable. (Now let's watch the hackers come out of the
woodwork.)

It's evident, from the sentence you have quoted from me, that I don't
consider it something acceptable, now you say that it is acceptable if
it is meant to do what I described.

If it weren't for your parenthetic, I'd think you'd consider the target
itself as acceptable, not only the means utilized to achieve that target.

I'd like to see an example (not actual code, just the concept) where
such a non-self-terminating program would be advisable - or gets
actually used. Where are the hackers?
 
J

James Kanze

* Öö Tiib, on 22.08.2010 04:09:
"Exit" is a special command because it needs handling at the
level that calls 'doCommand'. That level has to stop looping.
In your code you're thinking about 'doCommand' perhaps asking
the user to confirm, but you stop looping anyway...

Since we don't have the actual program specification, it's hard
to say what the exit command has to do:). Given Öö's premise
that it requires some additional actions, and may result in not
actually exit, means that processing it in the doCommand()
function is a reasonable solution. And that you then need some
means of doCommand to signal that we should terminate. One
could also imagine several different commands which trigger
termination.

None of which was implied in the original example. The pattern
is a classic one for servers:

while ( ! terminationRequested ) {
Request rq = getRequest();
processRequest( rq );
}

Processing the request may result in terminationRequested being
set. Or the server may have some other means of setting this
variable. (On many systems I've worked on, terminationRequested
was a volatile sigatomic_t, set in a signal handler.) While this
is the pattern I've almost always seen for servers, I suspect
that it is appropriate for many other types of applications as
well. Still, IIUC, it wasn't the pattern you had in mind.
So, you can either special-case the signature of 'doCommand'
to support "Exit", or you can just handle it directly.
Special-casing is problematic because there can be two or
three such special cases.
It's the KISS principle, Keep It Simple.
You might alternatively consider the weaker example
double sum = 0.0;
cout << explanation << endl;
for( ;; )
{
double const number = numberFromUser( "Number? " );
if( number == 0.0 ) { break; }
sum += number;
}

One thing: *if* you want to defend this way of writing things,
the line containing the break must be immediately visible.
In some other language, one might imagine:

double sum = 0.0;
cout << explanation << endl;
LOOP
double number = numberFromUser( "Number? " );
UNTIL number == 0.0;
sum += number;
END

I don't think it's necessary, and it isn't as simple to reason
about (since you have different invariants before and after the
UNTIL), but at least it's visible.
But in a way it accentuates the issue because here it's
a least plausible to put both the input operation and checking
as a 'while' loop condition.
To my eyes the 'while', with side-effect condition, obfuscates
what the effect of the code is,

Totally agreed. The idiom is ubiquious with iostream, so we're
sort of stuck with it, but we don't want to extend it to other
things. As a rule, you should be able to follow the general
outline of the code by just scanning down the left side of the
code. Hiding state changes in the conditional of a while is
just obfuscation.
 
J

James Kanze

[...]
I'd like to see an example (not actual code, just the concept)
where such a non-self-terminating program would be advisable
- or gets actually used.

Most of the servers I've worked on run 24 hours a day, 7 days
a week, over a period of years. Some of them had special
provisions for "orderly" shutdown, but that was far from
universel (or universally necessary); the usual way of
terminating the application was to reboot the system.

(On a number of these projects, we had contractual penalties for
down time---on the order of 5000 Euro per minute. Given that it
took 2 or 3 minutes to read the initial configuration from disk,
stopping the application would cost a minimum of 10 or 15
thousand Euros.)
 
J

James Kanze

It's 4 lines. Kanze would have a problem with it. I'd have
a problem with something much longer than 4 lines.

If that's your criteria:

codeA() ; while ( codeB() ) { codeC(); codeA(); }

is only one line. What we're comparing is:

codeA();
while ( codeB() ) {
codeC();
codeA();
}

vs:

while ( true ) { // But not really
codeA();
if ( codeB() )
break; // fooled ya.
codeC();
}

I don't think the difference in the number of lines is
significant (even if it actually favors my solution).
So we get back to What if your boss reviews your code,
dislikes it, and is wrong. I'm sure Kanze never had that
problem... (-:

If you're boss doesn't listen to or understand technical
arguments, and still insists on making technical decisions, then
you have a real problem. In my experience, however, such cases
are rare. (Companies which allow them to persist go under.)
 
J

James Kanze

Kanze _should_ bust on that, and so I'll do it for him.
All statements should be as positive as possible, starting with
conditionals.
while (gracefully_threading)
{

I sort of like that:). From experience, however, it's usually:

while ( !terminationRequested() ) ...

or something similar. (In multithreaded environments, there's
often one along the lines of:

while ( threadCount() != 0 ) ...

in the main thread.)

But not all applications need a "clean" shutdown. In a lot of
the telephone systems I've worked on, the only "shutdown" we had
was to unplug the power cord, or turn the system off.
 
F

Francesco S. Carta

On Aug 21, 4:07 pm, "Francesco S. Carta"<[email protected]> wrote:
[...]
I'd like to see an example (not actual code, just the concept)
where such a non-self-terminating program would be advisable
- or gets actually used.

Most of the servers I've worked on run 24 hours a day, 7 days
a week, over a period of years. Some of them had special
provisions for "orderly" shutdown, but that was far from
universel (or universally necessary); the usual way of
terminating the application was to reboot the system.

OK, now I see, thanks for the example.
(On a number of these projects, we had contractual penalties for
down time---on the order of 5000 Euro per minute. Given that it
took 2 or 3 minutes to read the initial configuration from disk,
stopping the application would cost a minimum of 10 or 15
thousand Euros.)

A penalty of 5K€ per minute of downtime? What was that, if I can be
indiscreet?

In such a case, I suppose forcing the admin to reboot the machine by not
providing any "orderly shutdown" command seems indeed The Way To Go ;-)

- If there is one thing a being cannot have in this universe, that would
be the sense of proportions [ loose quotation from you all know very
well what, indeed I had not that sense of proportion for the case above
:) ]
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,770
Messages
2,569,583
Members
45,072
Latest member
trafficcone

Latest Threads

Top