[comp.sys.mac.programmer] Preemption good, time-slicing bad

woody@truebalt.caltech.edu (William Edward Woody) (04/02/91)

After following this thread, I thought I'd post an interesting solution I
came up with for a compute-bound application which needs to work in the
background.  This uses the existing Macintosh calls (GetNextEvent, in
particular), and seems to work.

Of course I'm typing this solution off the top of my head, and I think I
may get some of the facts wrong.  However, I think I got most of it right.

Suppose you have a compute-bound task that executes in one or more loops.
One reasonable thing you may want to do is to display a window giving the
current status of the computation, and another would be to yield control
as soon as an event occured in another application.  This would allow the
user (for example) to run his word processor program and yet allow your
program most of the CPU time.

My solution involves creating a 'status display' routine which updates
the status window with some figure giving a measure of the amount of work
thus done.  The algorithm works something like this:

	int oldval;
	int newval;		/* Globals */
	long lastTime;

	UpdateStatus(int value)
	{
	    newval = value;	/* Stash new status value away */
	    if (lastTime + GetDblTime() < TickCount()) {
		DrawNewStatus(oldval,newval);
		oldval = newval;
		GetNextEvent(everyEvent,&e);
		lastTime = TickCount();
		if (IsCancel(&e)) AbortProgram();
	    }
	}

The principle part of this algorithm is to simply stash away the status
value away in a global variable and return immediately if a 'delta'
time (I used GetDblTime() in this example) hasn't passed.  This makes this
function have as little overhead as possible, so it can be called as
often as possible.

When an event occures, the user winds up waiting for a short period of
time (a double-click time is about a tenth of a second), but then he
gets control.  If this is the background application, Multifinder will
eventually pass control back to this routine as soon as the frontmost
application stops receiving events.

I keep both the 'oldval' and 'newval' globals as I usually draw a filled
rectangle to indicate the amount of computation that has elapsed, and
only fill the portion of the rectangle which has actually changed.

In imperical testing, I have noticed that when run by itself as a background
task, I seem to get about 95% of the CPU.  When I use a text editor in the
foreground the text editor doesn't seem to hesitate, as the tenth of a
second delay is just below my 'pain threshhold', and of course once the
foreground application is receiving events, it is not swapped out in favor
of the background application until the foreground stops receiving events
for some amount of time.

It is much nicer than the way MPW's C compiler seems to allow itself to
swap out; I've noticed up to a quarter of a second to a half a second delay
(sometimes even longer) before the foreground application starts noticing
events.

See, you don't have to have pre-emptive multitasking to make a good system
work well; you just have to think about the problem a tiny bit longer.

						-- Bill

-- 
	William Edward Woody		   | Disclamer:
USNAIL	P.O.Box 50986; Pasadena, CA 91115  |
EMAIL	woody@tybalt.caltech.edu	   | The useful stuff in this message
ICBM	34 08' 44''N x 118 08' 41''W	   | was only line noise. 

dorner@pequod.cso.uiuc.edu (Steve Dorner) (04/02/91)

In article <1991Apr2.055242.21143@nntp-server.caltech.edu> woody@truebalt.caltech.edu (William Edward Woody) writes:
>See, you don't have to have pre-emptive multitasking to make a good system
>work well; you just have to think about the problem a tiny bit longer.

Well, almost.  EVERYBODY has to think about the problem a tiny bit longer,
or you're sunk.  How is you or I thinking about the problem a tiny bit
longer for our apps going to fix Apple's C compiler?

The weakness of the current system is that it requires EVERY program to
behave in exactly the correct manner.  Protected, preemptive systems are
much more tolerant of flaws.

(Am I STILL in this argument?  I must have lost my mind...)
--
Steve Dorner, U of Illinois Computing Services Office
Internet: s-dorner@uiuc.edu  UUCP: uunet!uiucuxc!uiuc.edu!s-dorner