2
votes

I am running my code on SWI Prolog and Windows 7. In my code, I call another application using 'win_exec()' (I tried using the method 'shell()', but it won't work.), and at the end produces its output in a text file. However sometimes it runs for times like 30 minutes. Now my prolog code uses this output text file, to further parse it and process it. This is the code I use to call the other application and then use its output file:

main(Value,X) :- win_exec('C:\\myfolder\\external_app.bat C:\\myfolder\\outputfile.txt', normal),
                 open('C:\\myfolder\\outputfile.txt', read, Mf),
                 read_file(Mf, X),  % PROCEDURE TO READ FILE CONTENTS 
                 close(Mf),
                 statistics(cputime, Value). % CALCULATE HOW LONG IT TOOK

However, since the file has not been outputted by that another application, it gives the error:

ERROR: open/4: source_sink `C:\myfolder\outputfile.txt' does not exist (No such file or directory)

So, as a workaround, I try to catch the error, handle it by comparing with 'existence_error' and then recursively call the open procedure, until it finally succeeds i.e. the other application has completed its processing and the output file is produced. This is my workaround code for this:

main(Value,X) :- win_exec('C:\\myfolder\\external_app.bat C:\\myfolder\\outputfile.txt', normal),
                 open_output(X),   % PROCEDURE FOR FILE EXCEPTION HANDLING
                 statistics(cputime,Value).

open_output(X) :- catch((open('C:\\myfolder\\outputfile.txt', read, Mf), read_file(Mf,X), close(Mf)),
                         error(Err,Context),
                         open_output_aux(Err,X)). % AUX PROCEDURE TO RECOVER

% Write some code here
% open_output_aux code matches the error code with 'existence_error';
% if true, calls open_aux_wait procedure; else throw the error.

open_aux_wait(Z):- catch((open('C:\\myfolder\\outputfile.txt', read, Mf), read_file(Mf,Z), close(Mf)),
                   error(Err,Context),
                   open_aux_wait(Z)).

However this seems to be very inefficient of way doing this. I wanted to know if there's any better way to do this, like in java, you could simply call wait() while handling file exception. In the documentation, there's a method 'wait_for_input\3' but it says 'wait_for_input()' cannot be used for File Streams in Windows. I tried using it, but it gives error.

Any help or guidelines is greatly appreciated.

1

1 Answers

2
votes

You have several options to solve this:

  1. You can totally reconsider the way that these processes communicate. For example, SWI-Prolog ships with very powerful HTTP libraries, and you can set up the communication between the two processes to work over HTTP, using a client/server architecture. In this case, you avoid the busy waiting that currently uses many CPU cycles unnecessarily.

  2. A much more trivial solution is to simply insert a call of the built-in sleep/1 predicate to put the process to sleep before trying to open the file again. Use for example sleep(1) to put the process to sleep for 1 second.

  3. Use for example process_wait/2 to wait until the called process has finished and generated the file.

From what you are describing, it looks like (2) will do, (3) is slightly more elegant, and (1) may be good to know in general, for more difficult cases.