Description Usage Arguments Details Value Author(s)
Evaluate an R expression in a fork within a given time frame
1 2 3 4 5 6 | eval.within.time(expr, secs, dsecs = c(0.001, 0.1), time = as.difftime(secs,
units = "secs"), verbose = FALSE, write.obj = saveRDS,
read.obj = readRDS, make.con = tempfile, cleanup.con = function(con) if
(file.exists(con)) unlink(con), touch.con = function(con)
writeLines(character(), con), con.touched = file.exists,
make.signal.con = make.con, cleanup.signal.con = cleanup.con)
|
expr |
Expression to evaluate |
secs |
Seconds to timeout. Example: 10. Ignored if |
dsecs |
Seconds for parent process to sleep between checking the child process. It will be recycled to length 2. The first interval will be the first element, then each time it will wait twice as long until the interval is at least as long as the second element, then it will wait the second elemtn. This keep the ratio of time required to run and time actually taken to run close to 1 without having excessive checking for longer processes. Default: c(0.001, 0.1) (seconds). |
time |
|
verbose |
Boolean, default FALSE. If TRUE then emit messages with process IDs, etc. |
write.obj |
Function to serialize and write the resulting R object to
the connection. First argument is the object and second is the connection.
Default: |
read.obj |
Function to read and deserialize the resulting R object from
the connection. Argument is the connection. Default: |
make.con |
A function to make the connection for communication
between child and parent. The function will be called once with
no arguments. The child will then write to it with saveRDS and the
parent will read from it with readRDS. Default: |
cleanup.con |
A function to clean up a conncetion. Default:
|
touch.con |
A function to "touch" a connection. Default:
|
con.touched |
A predicate to check if the connection has been touched.
Default: |
make.signal.con |
Same as |
cleanup.signal.con |
Like |
The expression is evaluated in a child process while the
parent process waits up to the given time interval. If the child
process finishes quickly enough it will signal to the parent process to wake up
and return a particular value. If the time interval elapses before
the child process finishes then the parent wakes up anyway and kills
the child, then throws an error. (You may want to wrap this function
in a tryCatch
block to handle the error gracefully.)
The implementation uses the fork
package, which is loaded—an
error is thrown if unavailable. In fact, the parent sleeps for short
intervals (controlled by dsecs
param), each time waking up to
check if either the time has elapsed or the child has finished, then
acting accordingly.
The way the child signals to the parent is via the filesystem. There are two such files: the result file and the signal file. The child writes the result of the calculation to disk as a serialized R object. Usually you should try to keep this small. Then the child touches a second file, called the "signal" file, which signals that it is finished. Both of these are temporary files. While in loop, the parent checks for existence of the signal file. After exiting the loop, the parent reads the result file. An attempt is made to delete both files before returning or throwing an error.
The child process evalutes your expression within a try block. If this evaluation results in an error, then the captured error object is passed to the parent, which then throws it again.
It is possible that the child would *start* writing the result but not finish before the time elapses. That would be considered a timeout. The thing which the parent checks is if the signal file exists.
Don't be intimidated by the large number of arguments. Typically usage involves only the first two.
The result of evaluating expr
Brad Friedman
Add the following code to your website.
For more information on customizing the embed code, read Embedding Snippets.