In many of my programs I use some kind of loop (e.g. READ, FOR) that processes lots of entries and takes some time (hours) to run. To let the user see the progress of the program I print out the current iteration like this:
FOR #N 1 50000
SET CONTROL 'N'
INPUT (AD=IO) #N
END-FOR
However, if the user wants to abort the program it does not respond to his inputs due to SET CONTROL ‘N’:
SET KEY PF3
FOR #N 1 50000
SET CONTROL 'N'
INPUT (AD=IO) #N
IF *PF-KEY EQ 'PF3' /* this does not work
ESCAPE BOTTOM
END-IF
END-FOR
Is there
a way to abort such a loop according to the user’s input or
any other way of keeping the user informed about the progress of the loop that can be aborted?
The problem, of course, is that you want to use SET CONTROL ‘N’ to apprise the user of what is happening, and this does not allow for interaction with the user. If you add an INPUT without SET CONTROL ‘N’, you permit the user to interact, but you slow things down ( the user, of course, will be the slowest part of the processing).
The following code is as close as I think you will get to satisfying both of your requirements:
define data local
1 #loop (n8)
1 redefine #loop
2 filler 4x
2 #ten-thousand (a1)
2 #one-thousand (a1)
1 #end (a1)
1 #delay (i2) init <1>
end-define
*
for #loop = 1 to 100000
perform break processing
check for a thousands break
at break of #one-thousand
call ‘cmroll’ #delay
set control ‘n’
input 'up to iteration: ’ #loop (ad=o)
end-break
now check if a ten thousand break
at break of #ten-thousand
input ‘do you wish to end processing? Y or N ==>’ #end
if #end = ‘Y’
stop
end-if
end-break
end-for
end
The CALL CMROLL is just to slow things down so you can see what is happening. If you remove it, the up tp iteration message will be just a blur.
Of course, you would have to set the conditions for the two breaks. If you were reading through a file in logical sequence, by name, you might use the first letter of the name to control the second input and a counter within that break to control the first break.
Lots of variations of the code are possible, BUT, as noted above, you will have to establish the conditions for the two breaks.
your solution does not work for me, because under normal circumstances the loop should run through without any user interaction at all (think of a program that runs really long, e.g. 40h like mine: nobody can sit in front of it that long). Only if the user spontaneously decides he wants to abort it (e.g. because he found a bug) it should be stopped.
What I’ve done before is to stow the program while it’s running or simply to close its session, but that leads to a hard abort without any possibility to clean up (e.g. close work files, end transactions).
I’ve come up with this solution (and it’s working fine for me), but I still would like to know if there is any other way to do this.
Function ABORT
DEFINE FUNCTION ABORT
RETURNS (L)
ABORT := FALSE
END-FUNCTION
END
Loop
F1. FOR...
IF ABORT(<>)
PERFORM CLEAN-UP
ESCAPE BOTTOM (F1.)
END-IF
/* normal loop processing
END-FOR
Now I can change the return value of ABORT to TRUE and stow the function during the loop’s runtine and have it abort cleanly. However, there are two tradeoffs with this approach:
the overhead of calling ABORT in every loop iteration
a normal user without access to the source code can still not abort the program
Instead of your current approach (which requires access to source code), How about having an external file? The user would have the responsibility to alter a value in what would be a work file.
This could be combined with Mogens idea of a counter controlling when to test for abort.
Perhaps the attention key (on unix I believe it is CTRL+C) can interrupt your program. On mf there must be an Adabas call in the loop to stop it. I do not have a unix available so I cannot test.
Yes, that would be a possibility. The overhead for reading the file could be compensated by only doing it evey nth iteration. Thanks for the idea. Although I would rather find a more “natural” way for the user to abort the program. I think I’ll take a closer look at what Morgens wrote:
Mh… does anyone know how to enter attention keys in linux? What are the default key combinations used for them? CTRL-C and all the other usual suspects don’t seem to work (not recognized by *PF-KEY). I’ve tried it using our own terminal emulation and PuTTY.