Newsgroups: comp.sys.apple2.programmer Path: news.weeg.uiowa.edu!news.uiowa.edu!hobbes.physics.uiowa.edu!math.ohio-state.edu!howland.reston.ans.net!xlink.net!fauern!imp.ch!chsun!bernina!news From: GUDATH@EZINFO.VMSMAIL.ETHZ.CH (Bright Software) Subject: Writing code that multitasks Message-ID: Sender: news@bernina.ethz.ch (USENET News System) Nntp-Posting-Host: ezinfo Organization: ETH Zuerich Date: Fri, 27 Aug 1993 21:42:49 GMT X-News-Reader: VMS NEWS 1.24 Lines: 155 Net, After posting this silly mail some days ago, I got some inquiries about how multitasking works. Therefore I'll post some facts about TM. (I don't think it's wasted bandwidth ;-) ) >So how do I make my desktop applications compatible with multitasking a-la >The Manager? Do I leave my "GetNextEvent()" loop intact, or do I mask out >Null Events? >In the Event loop, in a desktop program, can my program have a DoNull >subroutine, or does my DoNull have to be an RTS and be used solely for >Manager background tasks. Or should I completely ignore the DoNull Event >type. Thanks for clearing this up for me (since I want to make a program >I'm working on Manager compatible). The answer is: your program will do those things in the background that are in the DoNull routine. If DoNull is only "rts", then you won't be able to multitask. [Note: you can use TaskMaster or GetNextEvent - both work equally well with TM] The Manager processes programs in the background in discrete steps - only the code between two GetNextEvents (GNE) will be executed "at once" ( :-) ). Needless to say, TM doesn't care if the two GNE are two distinct toocalls or actually only one around which the program loops. Though this seems to be a silly remark, this leads to two different implementations of multitasking-compatible code. Multitasking with "DoNull" If you're a perfectionist, you need the ultra-superduper-DoNull mechanism. This method, however, can turn the main event loop into the worst piece of software because it might become seriously complex. Anyway... The usual desktop app(-lication) contains one single event loop. All user interactions go through this loop: EventLoop TaskMaster(this&that) pla asl tax jsr (:DoSomething,x) bra EventLoop :DoSomething dw DoNull ;no actions dw InMenu,InContent,Control...etc DoNull inc x ;increment x rts InMenu ... InContent ... .... ... Normally, the DoNull routine returns immediately - because, as the name implies, there is nothing to do. Under TM, however, this subroutine is the only part of background programs that will be executed. The reason is simple: when the active app is not busy, it loops around in its own GNE loop and receives only Null events. In such situations, TM passes control to one background program during the GNE toolcall located in the active application. The GNE where the _background_ program was interrupted finally returns NIL, therefore DoNull is being called. (DoNull returns then to the main event loop, TM switches back to the front app etc etc) As you can see, DoNull must do *something* in order to mutlitask. Two warnings at this point: what it does must be done very quickly, otherwise the environment becomes sluggish. Secondly, you must be carefull with GrafPorts - restore the GrafPort that was active before returning!! The problem: you have to modify a separate, continuous routine so that it can be processed in discrete steps. As an example, imagine you have a telecomm program and have started a macro. You could, for example, take one single macro command, process it, and then return. During the second visit of your app, take the second one, etc etc. Of course, since the interesting stuff is happening in the event loop you have to add some flags because the user can select more functions before you have actually terminated the first one. (Dim the corresponding menu items, for example.) Lazy programmer's cheap trick (my favorite:-)) Another possibility is adding pseudo-taskmasters in your routines. This is much simpler than the method above. Insert here and there a TaskMaster with a _NIL_ event mask. Make sure you do not pass a pointer to your main event record. When modifying existing routines, you often refer to values found in this record, and by inserting pseudo taskmasters you overwrite those paramaters. (It takes hours to find this bug, believe me..:)). Of course, carefully place the taskmasters so that the code between two TaskMasters does not require too much CPU time but accomplishes enough to justify the significant overhead of switching apps. Furthermore, don't forget to add a few TaskMasters with a "update event" mask. Remember, users can switch back and forth, and each time the desktop must be redrawn. Use NIL masks in tight loops, and then handle update events in outer loops. If I may suggest a routine: FirstMultiTask ;call this routine first _GetPort sta MyPort _TaskMaster(NIL) _GetPort sta OtherPort _SetPort(MyPort) rts MultiTask ;then continue calling this one lda PacketSize and #%1 beq :always lda PacketSize eor #%10 sta PacketSize and #%10 bne :skip :always _GetPort sta MyPort _SetPort(OtherPort) _TaskMaster(NIL) _GetPort sta OtherPort _SetPort(MyPort) :skip rts LastMultiTask ;before returning from your routine, call me _GetPort sta MyPort _SetPort(OtherPort) _TaskMaster(NIL) rts When a particular routine takes over control, execute the first routine. Then, sporadically, call MultiTask. At the end, jsr to LastMultiTask. The three routines save and restore GrafPorts properly - if you do not depend on them, great! (Note: You should call TaskMaster(Update) from time to time - the above code does not care about updates...) The middle routine also contains another feature. If PacketSize=%1, then only each second call to this routine will actually call TaskMaster. I recommend you add a check box somewhere in your program where the user can switch between the two speeds - owners of accelerated computers will be most thankfull.... (tasks need far less time because lots of app switching is not needed...) Feel free to mail me if things are not clear! henrik [PS: no, GNE is not a UNIX port-over...:)))] ___________________________________________________________________ | | | Andre Horstmann | I am not Henrik, and Henrik is not me! | | GEnie A.HORSTMANN | Ask me about ShadowWrite! Apple IIGS? | | Internet: shadow@ | Hmmm - nicht immer, aber immer oefter! | | ezinfo.vmsmail.ethz.ch | There's still a glittering in my eyes..| |___________________________________________________________________|