eval.within.time: eval.within.time

Description Usage Arguments Details Value Author(s)

Description

Evaluate an R expression in a fork within a given time frame

Usage

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)

Arguments

expr

Expression to evaluate

secs

Seconds to timeout. Example: 10. Ignored if time is provied.

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

difftime object giving the timeout interval. Default: as.difftime(secs, units = "secs"), which simply means to build a difftime object from the secs argument. If this argument is provided then secs is ignored.

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: saveRDS.

read.obj

Function to read and deserialize the resulting R object from the connection. Argument is the connection. Default: readRDS.

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: tempfile.

cleanup.con

A function to clean up a conncetion. Default: function(con) if(file.exists(con)) unlink(con).

touch.con

A function to "touch" a connection. Default: function(con) writeLines(character(), con). This is used to signal through the signal file.

con.touched

A predicate to check if the connection has been touched. Default: file.exists.

make.signal.con

Same as make.con, but for the signal file. Default: make.con.

cleanup.signal.con

Like cleanup.con, but for the signal file. Default: cleanup.con.

Details

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.

Value

The result of evaluating expr

Author(s)

Brad Friedman


apomatix/AnalysisPageServer documentation built on May 26, 2019, 11:36 a.m.