[comp.sys.mac.programmer] WaitNextEvent problem

jrk@s1.sys.uea.ac.uk (Richard Kennaway CMP RA) (10/14/88)

I'm having a problem with WaitNextEvent in a background application.  
InsideMac, InsideMultifinder (or whatever it's called), the few TechNotes 
I've seen, and the MPW manual don't help.  Can anyone out there?

The context:  I have written a simple application called BackgroundClock, 
which shows the current time in a little window.  MacII, System 4.3, Finder 6.0.

(By the way, if anyone can send me a MacII-compatible, MultiFinder -
compatible, everything-else-compatible, totally bomb-proof, clock-in-the-
menu-bar INIT, or tell me how to write one in C (Inside Mac says next to 
nothing about INITs and VBQ tasks), or point me to any of this information,
that would solve the problem of having a background clock ... but not the
WNE problem, which I'd like solved anyway.  I have JClock, which works with
MultiFinder on a Mac+, but crashes a MacII.)

The problem is that switching between BackgroundClock and other applications 
or DAs usually hangs the system when I switch back to BackgroundClock.

Here's some pieces of the code.  I only update the time once a second, so
to be friendly to applications, I call WNE with a 60-tick delay, in a loop
like this (MPW C):

	#define WNEDELAY	60L
		/* MPW longs are 4 bytes, I can never remember whether
		   plain ints are 4 or 2 bytes */

	while (TRUE) {
	  if (WaitNextEvent( everyEvent, &TheEvent, WNEDELAY, NULL ) ||
	      (TheEvent.what == nullEvent)) {
	    OneEvent();
	  }
	}  /* while (TRUE) */

(MPW-ers will realise that the MPW C for "TRUE" is "true".  Dont worry, I
#define TRUE to be true, because I call it TRUE on every other system I use.)

And this is OneEvent().  ClockDialogWindow is a dialog box with just a single 
statText to show the time:

	OneEvent()
	{
	DialogPtr theDialog;
	int16 theItem;	/* int16 is typedef'd as a two-byte integer */

	  AdjustClock();  /* read the clock, change the statText in the
	                     window if the time has changed */
	  if (TheEvent.what == mouseDown) {
	    DoMouseDown();  /* drags the window or handles menu commands */
	  } else if (TheEvent.what == app4Evt) {
	    if (FrontWindow() != ClockDialogWindow) {
	      SystemEvent( &TheEvent );
	        /* I think IM or some TN said to do this, I dont know why.
	           Taking it out doesnt help. */
	    }
	  } else if (IsDialogEvent(&TheEvent)) {
	    DialogSelect(&TheEvent, &theDialog, &theItem);
	  }
	}  /* OneEvent() */

If I use a 0-tick delay, then it doesn't hang (at least, I haven't seen it 
happen), but the more frequent juggling in of BackgroundClock can interfere 
noticeably with the speed of everything else.  The larger the tick-count, the 
more likely the hang.

I tried changing the boolean flags in the SIZE(-1) resource in various ways, 
but the problem remained.

SysBeep()-ing at strategic places indicates that the hang happens in the call
of WaitNextEvent() that should return a resume event when the program is
switched in.

MacsBug?  I don't understand any of the random number display it puts up.  
Is this thing documented anywhere?  Besides, life isn't long enough to use 
assembly-level debuggers...  I have tried ES-ing in MacsBug: the result is to 
kill anything *except* BackgroundClock - even the Finder.
-- 
Richard Kennaway
School of Information Systems, University of East Anglia, Norwich, U.K.
uucp:	...mcvax!ukc!uea-sys!jrk	Janet:	kennaway@uk.ac.uea.sys

anson@elrond.CalComp.COM (Ed Anson) (10/18/88)

In article <159@s1.sys.uea.ac.uk> jrk@s1.sys.uea.ac.uk (Richard Kennaway CMP RA) writes:
>
>I'm having a problem with WaitNextEvent in a background application.  
>
>The problem is that switching between BackgroundClock and other applications 
>or DAs usually hangs the system when I switch back to BackgroundClock.
>
>Here's some pieces of the code.  I only update the time once a second, so
>to be friendly to applications, I call WNE with a 60-tick delay, in a loop

Consult Tech Note #177. There is a bug in old versions of MultiFinder (such
as you are using) which requires the delay to be 50 or less.

Try reducing your delay.

I hope this helps.
-- 
=====================================================================
   Ed Anson,    Calcomp Display Products Division,    Hudson NH 03051
   (603) 885-8712,      anson@elrond.CalComp.COM

steve@ivucsb.UUCP (Steve Lemke <steve>) (10/20/88)

In article <159@s1.sys.uea.ac.uk> jrk@s1.sys.uea.ac.uk (Richard Kennaway CMP RA) writes:
>(By the way, if anyone can send me a MacII-compatible, MultiFinder -
>compatible, everything-else-compatible, totally bomb-proof, clock-in-the-
>menu-bar INIT, or tell me how to write one in C (Inside Mac says next to 
>nothing about INITs and VBQ tasks), or point me to any of this information,
>that would solve the problem of having a background clock ... but not the
>WNE problem, which I'd like solved anyway.  I have JClock, which works with
>MultiFinder on a Mac+, but crashes a MacII.)

Well, have you ever heard of SuperClock?  It's by Steve Christianson (I think,
though I'm not sure of the spelling of his name).  He's up to version 2.9 or
so by now - perhaps this would be a good thing to put out in mac.binaries,
since I'm still running 2.8 and many people would probably like to get 2.9.

Anyone listening up there at Sumex?  If you don't have 2.9, let us know so
someone can send it to you and you can then put it in out in binaries.
 
----- Steve Lemke ------------------- "MS-DOS (OS/2, etc.) - just say no!"
----- Internet: steve@ivucsb.UUCP; lemke@apple.COM   AppleLink:  LEMKE
----- uucp:     pyramid!comdesign!ivucsb!steve       CompuServe: 73627,570
----- alt.uucp: {decwrl!}sun!apple!lemke             GEnie:      S.Lemke
----- Quote:    "What'd I go to college for?"   "You had fun, didn't you?"

dunlop@cs.glasgow.ac.uk (Mark Dunlop) (04/28/89)

I have written a small application which converts Sun rasters into PICT format.
The application does not require any NULL events, as it only does a 
conversion upon command. I thought to myself, let's be MultiFinder friendly so
I used WaitNextEvent, when I ran my program the clocks in the menu bar stopped!

I tried using SuperClock, and the Moire screensavers clock - both stopped!
Both INIT/CDEV clocks which run in the background and usually behave very well.
I then brought up a DA (under MultiFinder) selected my application and the
clock started to work again. This solution did not work by opening a background
application (e.g. Telnet).

I recon that if there is not a desk accessory running MultiFinder decides there
is no need to call SystemTask and therefor the clock stops.

I have tested the problem on two configurations...

	1M Mac Plus running MultiFinder	6.0.1
			    Finder	B1-6.1
			    System	B1-6.0.2

	4M Mac IIx running  MultiFinder	6.0.3
			    Finder	B1-6.0.3
			    System	B1-6.0.3

The call was -> WaitNextEvent(EveryEvent,TheEvent,-1,nil);

I later changed this to WaitNextEvent(EveryEvent,TheEvent,600,nil) and the clock
changed once every 10 seconds.


Any help on what's going wrong? I just tried to be MultiFinder Friendly and time
stands still....

Mark Dunlop

dunlop@cs.glasgow.ac.uk                                  dunlop@uk.ac.glasgow.cs
                       !mcvax!ukc!uk.ac.glasgow.cs!dunlop

trebor@biar.UUCP (Robert J Woodhead) (05/02/89)

In article <2864@crete.cs.glasgow.ac.uk> dunlop@cs.glasgow.ac.uk (Mark Dunlop) writes:
> [Mark is having problems with WaitNextEvent]
> The call was -> WaitNextEvent(EveryEvent,TheEvent,-1,nil);

Mark,

Did you remember to tell the system that the application was multifinder
friendly, etc, etc, by setting the appropriate bits in the SIZE -1 resource.
See IM and the tech notes for details on being multifinder friendly.

In particular, if you want to chunk around in the background, you should be
accepting NULL events, and when you get one you should be calling SystemTask.
(In general, anytime you get an event, you should be calling SystemTask).

In my programs, if I combine the proper SIZE -1 bits (notably jugglerAware
[hehe, shows how old the program is] and canBackground) with a program that
calls SystemTask each time it gets events, you have no problems.

-- 
Robert J Woodhead, Biar Games, Inc.  ...!uunet!biar!trebor | trebor@biar.UUCP
"The NY Times is read by the people who run the country.  The Washington Post
is read by the people who think they run the country.   The National Enquirer
is read by the people who think Elvis is alive and running the country..."

darin@Apple.COM (Darin Adler) (05/03/89)

In article <520@biar.UUCP> trebor@biar.UUCP (Robert J Woodhead) writes:
> In article <2864@crete.cs.glasgow.ac.uk> dunlop@cs.glasgow.ac.uk (Mark Dunlop) writes:
> > [Mark is having problems with WaitNextEvent]
> > The call was -> WaitNextEvent(EveryEvent,TheEvent,-1,nil);
> 
> Did you remember to tell the system that the application was multifinder
> friendly, etc, etc, by setting the appropriate bits in the SIZE -1 resource.
> See IM and the tech notes for details on being multifinder friendly.

Mark is doing the right things to be MF friendly.

Mark, you have found one of the known bugs in existing versions of MultiFinder.
Drivers get starved when applications pass large sleep values, because MF
only calls SystemTask to service drivers when feeding events to an application.
We had this same problem with the DTS Sample application last year, and MacApp
has the same problem. It will be fixed in a future version of MultiFinder, but
for now, passing a large sleep value has this side effect.
-- 
Darin Adler, System Software Scapegoat, Apple Computer
	Internet: darin@Apple.com
	UUCP: {nsc,sun}!apple!darin

omh@brunix (Owen M. Hartnett) (05/06/89)

Does anyone have any idea of what to pass for sleep?  Most code I've seen uses
the GetDblTime call, but without explanation as to why this is (or isn't) good.

Really nice would be recommended values of sleep for 1) responsive applications
(i.e. a Word Processor) 2) background tasks (while the user is thinking, let's
post the daily transaction file.)

-Owen

Owen Hartnett
Brown University Computer Science

omh@cs.brown.edu.CSNET 

darin@Apple.COM (Darin Adler) (05/13/89)

In article <5781@brunix.UUCP> omh@zaphod.UUCP (Owen M. Hartnett) writes:
> Does anyone have any idea of what to pass for sleep?  Most code I've seen uses
> the GetDblTime call, but without explanation as to why this is (or isn't) good

The best value to pass for sleep is the number of ticks until you will need to
do something. For an application which does nothing in the background, the
correct value is something huge (like MAXLONGINT in Pascal). For an application
which is currently frontmost (keeping track as in the MultiFinder Programmer's
Guide), which is only using idle time to flash the insertion point, an
appropriate value is GetCaretTime. This will give your application time
just often enough to flash it.

If you are in the background and want to do background processing, almost any
value will due. Larger values will result in larger intervals between the
times you get background time. Even using values as small as 1 or 2 would be
acceptable, especially if you used extremely large values when not doing
anything.

The most important this is that you don't get time that you use doing nothing
and calling WaitNextEvent again. To do this effectively, you should use both
sleep and mouseRgn. The Sample and TESample programs from DTS are good examples
for this stuff.
-- 
Darin Adler, System Software Scapegoat, Apple Computer
	Internet: darin@Apple.com
	UUCP: {nsc,sun}!apple!darin