Wassercrats has asked for the wisdom of the Perl Monks concerning the following question:

I'm REALLY new at Perl, so few things that go wrong with my scripting attempts suprise me, but this one did. I want to add data to a log that will be read shortly after it's written--in the time it takes for a new page from my site load. If there is already an entry in the log, the script waits about five seconds to give it a chance to get used:
open(IN, $logfile); @file = <IN>; close IN; if(@file != "") { for ($count=1; $count<9999999; $count++) {} open(LOG, ">$logfile"); print LOG ""; close (LOG) };
Then the new entry is added. I don't know if it's a good idea to do things this way, but that's not my main concern. My main concern is that an image that's supposed to be printed in the beginning of the script (code not shown), isn't printed until AFTER the do-nothing loop. Without the loop, it's printed alot faster. How can I have the image be displayed and THEN have a delay? Am I just hallucinating?

Replies are listed 'Best First'.
Re: Do-nothing loops
by chromatic (Archbishop) on Mar 16, 2002 at 05:05 UTC
    It sounds as if you are Suffering from Buffering.

    In lieu of your CPU-time-eating delay, you might look into sleep, which is much more deterministic. In other words, it's more efficient, and it's easier to get the time right.

Re: Do-nothing loops
by tachyon (Chancellor) on Mar 16, 2002 at 11:00 UTC

    You could replace all your code with:

    $|++; sleep 5 if -s $logfile;

    This code gets your program to sleep for 5 seconds unless $logfile has a non zero size (-s filetest). You don't need to open a file and check its contents is not blank. If this is the case it will have a size greater than zero. For the filetest operators see perlman:perlfunc:alphabetical and look for -X. The $|++ will flush the buffers. The code if (@file != "") is the same as if (@file) BTW

    cheers

    tachyon

    s&&rsenoyhcatreve&&&s&n.+t&"$'$`$\"$\&"&ee&&y&srve&&d&&print

    A reply falls below the community's threshold of quality. You may see it by logging in.
    A reply falls below the community's threshold of quality. You may see it by logging in.
Re: Do-nothing loops
by theguvnor (Chaplain) on Mar 16, 2002 at 05:15 UTC

    First thing of note is that you are reading your entire logfile into an array, which is perfectly fine, but then you're doing a comparison to see if the array is numerically not equal to a null string. It appears to me you are trying to test for an empty file - then I'd suggest doing one of the following:

    if (@file != 0) {# @file in scalar context here - returns number of li +nes in the array #your stuff here };
    or
    if ($#file < 0) {# $#file returns max index of array #your stuff here };

    Secondly, you can achieve a delay in program execution using Perl's sleep built-in function, much more readably and simply than a for loop that does nothing.

    Finally, the reason that your script's output is not being displayed until after the delay loop, is output buffering. There is an excellent FAQ on this topic here. Update: this is the same link as chromatic++ gives above.

    I hope this is of some use to you! Good luck.

    ..Guv

    Update: ++tachyon for a neat, very Perlish solution below!

      This might be better:

      if (defined(@file)) #your stuff here };

        if (defined(@file))

        my @foo = (); print defined(@foo) ? "Empty arrays are defined\n" : "Empty arrays are + undefined\n"

        U28geW91IGNhbiBhbGwgcm90MTMgY
        W5kIHBhY2soKS4gQnV0IGRvIHlvdS
        ByZWNvZ25pc2UgQmFzZTY0IHdoZW4
        geW91IHNlZSBpdD8gIC0tIEp1ZXJk
        

Re: Do-nothing loops
by erikharrison (Deacon) on Mar 16, 2002 at 05:58 UTC

    In addition to Perl buffering issues, there is the browser-parse, web-server buffering issue. There is a good discussion of that over at cgi buffer flush.

    Cheers,
    Erik
    A reply falls below the community's threshold of quality. You may see it by logging in.
    A reply falls below the community's threshold of quality. You may see it by logging in.
    A reply falls below the community's threshold of quality. You may see it by logging in.
Re: Do-nothing loops
by tmiklas (Hermit) on Mar 16, 2002 at 12:35 UTC
    Hi!

    If you want to wait a few seconds before taking an action, use the sleep(), becouse loops like yours strongly occupy your machine. sleep() works great with full number of seconds, but if you need delays below 1 sec or for example 1.7 sec, then use Time::HiRes module from CPAN. It works fine and should fit well :-)

    BTW. CPAN has a nice search engine...

    Good luck!
somewhat related.. (OT)
by archen (Pilgrim) on Mar 17, 2002 at 03:27 UTC
    Actually a friend of mine in college made an egg timer (in VB) that did something similar. It went something like
    while now <> time show time on main form end while
    (or however the hell VB syntax works). It was sort of interesting that his entire machine would literally slow to a crawl while it was running, so as other people have been saying - yes these sorts of loops really will eat all your CPU cycles. {I think a few months later he was enlightened by the VB Timer function} And I'm sure the admin of the server you put it on wouldn't be too happy either ;)
    A reply falls below the community's threshold of quality. You may see it by logging in.