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

I had thought to post this a few weeks ago, but I thought it was too silly. However having seen a few similar queries go past, it seems reasonable.

It seems there is no perl command that causes perl to give up the remains of it's timeslice. Languages like Visual Basic have some kind of "do_events" call (in fact I think it's a windows API).

When this is called, the program finsihes it's allocated timeslice early, handing it over to the kernel to be spent as needed somewhere else.

This is fantastic for those moments when you just want to check something as often as possible, as long as it doesn't get it anyones way.

Sleep doesn't really cut it, because you are then fixing yourself to only check a fixed number of times per second.

Block isn't it either, because you might want to do a few tasks before you check and &do_events.

So is there an easy solution? Is there a solution at all? Should I submit this for Perl 6 or has someone done so already?

____________________
Jeremy
I didn't believe in evil until I dated it.

Replies are listed 'Best First'.
Re: I want to forfeit my timeshare
by dws (Chancellor) on Aug 24, 2001 at 08:41 UTC
    So is there an easy solution? Is there a solution at all?

    Check out the four-argument form of select. The forth argument specifies the amount of time to sleep. You can specify fractional seconds.

      Regardless of the fraction of a second I can sleep, I'm still locking myself to n checks per second. I want to check once each time I get a time slice, but every time I get a time slice. If I limit myself to every tenth of a second, when the program runs a 100 Ghz machine it will still only check ten times per second.

      ____________________
      Jeremy
      I didn't believe in evil until I dated it.

        Not true; select will wake your process if there are any pending filehandle events (read/write/error), before the timelimit is up. The argument is simply a timeout, after which control is returned to your program, assuming no events occur.

        If your problem with select is that it doesn't allow you to wait on the other types of events, then it would help if you mentioned exactly what sorts of events you're catching. In the meantime, I'd suggest looking at Event (or POE, which I don't particularly like).

           MeowChow                                   
                       s aamecha.s a..a\u$&owag.print
        Sleep (0) is the answer, because it is not optimized away. (and since sleep is implemented using select...).

        T I M T O W T D I
Re: I want to forfeit my timeshare
by traveler (Parson) on Aug 24, 2001 at 22:05 UTC
    Two cases:
    1. With gtk: I add the socket(s) to the pending events queue. In this case the gtk main loop takes care of giving up the CPU.
    2. In "straight perl" you can ask the socket to signal you (use fcntl with F_SETSIG to tell the socket what signal to send) when there is input then do a wait (which can be interrupted by a signal). The wait gives up the CPU, the signal tells the system to reschedule your process. DisclaimerActiveState does not have F_SETSIG so this won't work with that Windows port. It may or may not work with any other.
    HTH, --traveler
Re: I want to forfeit my timeshare
by dga (Hermit) on Aug 24, 2001 at 21:51 UTC

    More data on task provided in jepri's to the top post below

    It's my understanding that select does the exact thing you want.

    You set up the list of open files you want to know if you can read from/write to (or both) and call select. The OS then blocks you until one of those files (sockets) is ready to go then wakes you and tells you which file is ready even. You can set a timeout in case you really do want to do something after a while even if no files are ready to go.

    This would seem to give you a wait which is over at exactly the correct time and you don't even get called on slices where you nothing to do at all.

Re: I want to forfeit my timeshare
by John M. Dlugosz (Monsignor) on Aug 24, 2001 at 08:55 UTC
    I don't see much use for that. If you wake up, do your checking, and are done, you'll block on the event again waiting for the OS to tell you something happened. That naturally gives up the timeslice.

    I do lots of multithreaded programming in C++ (in fact, I started writing a book about it, but that's another story), and have never needed to give up the timeslice while still remaining ready.

    —John

      That's only if you use blocking, which is sometimes undesirable. How about if I want to check four sockets just once per slice?

      Normally we'd do something like this:

      while (1) { foreach ( $s -> can_read) { recv $_, $buffer, 1000; } print "."; }

      but as a recent petitioner noted, the CPU use hits 95%. Of course that's because it's using up all the available idle time, and not actually cutting into another processes time, but it's still not neat. And there's no way to get away from that select statement.

      ____________________
      Jeremy
      I didn't believe in evil until I dated it.

        For polling?! Use an explicit timer rather than the nebulus "once per slice". Especially if after giving up your slice (there's an undocumented way to do it in Win32) you are immediatly run again as being the highest priority thread waiting!

        I think Perl 6 will allow decimal seconds in the sleep command, so you can say e.g. sleep(0.01);.

        In Win32, I'd never write such a loop anyway. I have Winsock post a message when activity occurs (ready to read, ready to write, etc) on a socket, and that is handled along with the GUI messages.

        So what you really want is a standard Perl syntax for having socket activity trigger a callback dispatch, and that mechanism can be implemented in whatever way is nice and efficient on each platform.

        —John