;+ ; NAME: ; YIELD ; ; PURPOSE: ; Yields control to the Windows operating system to allow background ; processing & allows the user to abort or suspend execution. ; ; CATEGORY: ; Utilities. ; MS Windows. ; ; CALLING SEQUENCE: ; YIELD ; ; INPUTS: ; None ; ; INPUT KEYWORDS ; DESTROY If set, Yield destroys the widget base. ; ; OUTPUTS: ; None. ; ; SIDE EFFECTS: ; A button menu widget is displayed. Other Windows processes are given ; an opportunity to execute. ; ; DEPENDENCIES: ; Has an effect only on MS-Windows. May require IDL version >= 3.5 for ; CALL_EXTERNAL to work properly. ; ; PROCEDURE: ; Yield calls widget routines as necessary to maintain a button widget ; offering the choices 'Abort', 'Suspend' and 'Resume'. (The last is ; initially insensitive.) At each call, Yield checks for widget events ; and also calls the Windows API function "Yield" to allow other processes ; to execute. If no widget events are detected, Yield returns to the ; calling program. If 'Abort' is selected Yield writes a message & ; terminates. If 'Suspend' is selected, Yield sensitises the 'Resume' ; button and goes into a loop waiting for it to be pressed. ; ; EXAMPLE: ; ; Calls to yield should be distributed throughout lengthy computations. ; Yield takes approximately 8 ms to execute on an otherwise idle 486/66. ; (Most of that time is taken for the "Yield" API function.) So to give ; reasonable response in other applications without slowing IDL too much ; it should be called approx once every 0.2 sec. There should be a final ; call with the DESTROY keyword to remove the widget. (Otherwise it should ; be manually closed.) ; ; The following function (based on one by F Knight) counts the lines ; in a file and optionally calls Yield during processing: ; ; function nlines, file, yield=yield ; ; nl = 0L & tmp='' ; openr,lun,file,/get_lun ; on_ioerror,NOASCII ; while not eof(lun) do begin ; readf,lun,tmp ; nl = nl + 1 ; if keyword_set(yield) then if (nl mod 30) eq 0 then yield ; endwhile ; close,lun ; free_lun,lun ; NOASCII: ; if keyword_set(yield) then yield, /destroy ; return,nl ; ; end ; ; Reading a 3141 line file takes 5.3 second with the YIELD keyword set ; and 4.6 without. (If the references to the YIELD keyword are ; removed entirely, it still takes 4.6 s.) ; ; MODIFICATION HISTORY: ; Mark Hadfield, 3 April 1994: ; Created. ;- pro yield, destroy=destroy common yield_widget, base_id, button_id on_error,2 if (STRLOWCASE(STRMID(!VERSION.OS,0,3)) NE 'win') then return if n_elements(base_id) eq 0 then base_id = 0L if not keyword_set(destroy) then begin if not widget_info(base_id,/valid) then $ xmenu, ['Abort','Suspend','Resume'], base=base_id, $ button=button_id, /row, title='Yield' if not widget_info(base_id,/real) then begin widget_control, base_id, /realize widget_control, button_id(2), sensitive=0 endif event = widget_event(base_id,/nowait) OK = call_external("kernel.exe","Yield") if event.id ne 0 then begin case event.id of button_id(0): begin widget_control, base_id, /destroy message, "Operation aborted. " + $ "You may have to press RETALL " + $ "to return to the main program level." end button_id(1): begin message, /inform, "Operation suspended." widget_control, button_id(0), sensitive=0 widget_control, button_id(1), sensitive=0 widget_control, button_id(2), sensitive=1 event = widget_event(base_id,/nowait) while event.id ne button_id(2) do begin event = widget_event(base_id,/nowait) OK = call_external("kernel.exe","Yield") endwhile widget_control, button_id(0), sensitive=1 widget_control, button_id(1), sensitive=1 widget_control, button_id(2), sensitive=0 message, /inform, "Operation resumed." end else: message, "Unexpected event from Yield widget." endcase endif endif else begin if widget_info(base_id,/real) then widget_control, base_id, /destroy endelse end