Too many programs these days have user configuration options to set the WaitNextEvent delay parameter.
Most users who are not programmers have no idea what this means, or what value they should set it to. If they set it to zero, then the application gives good performance but it hogs the CPU and slows down all the other applications on the Mac. If they set it too high then the application does not cripple the Mac, but it runs slowly.
It is a decision users shouldn't have to make, and leads them to conclude that the Mac is useless and they really want a system with preemptive multitasking so that they don't have to worry about stupid issues like WaitNextEvent parameters.
Actually the opposite is true. The benefit (perhaps the only benefit) of cooperative multitasking is that the application is able to make informed decisions about how what share of the CPU it needs at any moment in time, instead of having a preemptive operating system trying to guess what is going on. Sadly, not many application programmers take advantage of this ability.
This note explains a simple way to make applications adaptively share the CPU according to their needs. It is the technique I use in Bolo.
My technique is to have a variable called "sleep" which is the value you pass to WaitNextEvent. Have your program increment this variable once per second, up to a maximum value of 15. This way you still get, at worst, four null events per second in the foreground so that you can perform housekeeping tasks like flashing the cursor. Any time something happens that requires your application to do some work reset this variable to zero so that you get maximum CPU, for fast response.
This way, you still get peak performance while the user is actively using your program, but if I walk away and leave your program as the front application it slowly backs off to a sleep time of 15 ticks so that it doesn't completely cripple performance for other programs on my Mac (like Peter Lewis's FTPd which is constantly running in the background).
You can use the same technique to maintain good performance in the background too -- just make the ceiling 60 when in the background and 15 when in the foreground.
Here is some simple source code to do this:
#define MinSleepValue 0
#define MaxFGSleepValue 15
#define MaxBGSleepValue 60
Boolean isFrontApplication = TRUE;
Boolean ApplicationBusy;
void smartWaitNextEvent(EventRecord *e)
{
static long busytime;
long this_time = TickCount();
long sleep;
if (ApplicationBusy) { ApplicationBusy = FALSE; busytime = this_time; }
sleep = (this_time - busytime) >> 6;
if (sleep < MinSleepValue) sleep = MinSleepValue;
else if (isFrontApplication && sleep > MaxFGSleepValue) sleep = MaxFGSleepValue;
else if (sleep > MaxBGSleepValue) sleep = MaxBGSleepValue;
WaitNextEvent(everyEvent, e, sleep, NULL);
if (e->what == osEvt && e->message >> 24 == suspendResumeMessage)