Skip to content

Commit

Permalink
collapse 'cleanup' argument into single logical, closes #79
Browse files Browse the repository at this point in the history
  • Loading branch information
shikokuchuo committed Oct 11, 2023
1 parent 0a56b67 commit 0b64525
Show file tree
Hide file tree
Showing 7 changed files with 58 additions and 25 deletions.
2 changes: 1 addition & 1 deletion NEWS.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
* Adds 'mirai' method for 'as.promise()' from the `promises` package (if both packages `promises` and `later` are available). This functionality is merged from the package `mirai.promises` for convenience, and allows use of the promise pipe `%...>%` with a 'mirai'.
* Eliminates the 'exitlinger' period that still applied to ephemeral daemons. These now synchronise with host and exit as soon as permissible.
* Daemons connecting over TLS now follow the specified 'asyncdial'.
* `daemons()` argument 'cleanup' now takes a logical vector specifying the cleanup actions to take, rather than an integer bitmask (thanks @krlmlr #79).
* `daemon()` argument 'cleanup' simplified to a logical argument, with more granular control offered by the existing integer bitmask (thanks @krlmlr #79).
* Adds a 'not implemented' `[` method for 'miraiCluster' (thanks @HenrikBengtsson #83).
* Removes the deprecated deferred evaluation pipe `%>>%`.
* Requires nanonext >= [0.10.2.9001].
Expand Down
39 changes: 28 additions & 11 deletions R/daemon.R
Original file line number Diff line number Diff line change
Expand Up @@ -45,14 +45,11 @@
#' argument to \code{\link{daemons}} or \code{\link{launch_local}} to provide
#' redirection of output to the host process (applicable only for local
#' daemons when not using dispatcher).
#' @param cleanup [default TRUE] logical value, whether to perform cleanup of
#' the global environment and restore loaded packages and options to an
#' initial state after each evaluation. For more granular control, also
#' accepts an integer value (see 'Cleanup Options' section below).
#' @param ... reserved but not currently used.
#' @param cleanup [default c(TRUE, TRUE, TRUE, FALSE)] logical vector of length
#' 4, specifying whether to perform the following operations after each
#' evaluation: (1) cleanup the global environment, (2) reset loaded packages,
#' (3) reset options to an initial state, and (4) perform garbage collection.
#' This option should not normally be modified - do not set unless you are
#' certain you require persistence across evaluations. Caution: do not reset
#' options but not loaded packages if packages set options on load.
#' @param tls [default NULL] required for secure TLS connections over 'tls+tcp://'
#' or 'wss://'. \strong{Either} the character path to a file containing
#' X.509 certificate(s) in PEM format, comprising the certificate authority
Expand All @@ -71,11 +68,26 @@
#' resources may be added or removed dynamically and the host or
#' dispatcher automatically distributes tasks to all available daemons.
#'
#' @section Cleanup Options:
#'
#' The 'cleanup' argument also accepts an integer value, which operates an
#' additive bitmask: perform cleanup of the global environment (1L), reset
#' loaded packages to an initial state (2L), restore options to an initial
#' state (4L), and perform garbage collection (8L).
#'
#' As an example, to perform cleanup of the global environment and garbage
#' collection, specify 9L (1L + 8L). The default argument value of TRUE
#' performs all actions apart from garbage collection and is equivalent to a
#' value of 7L.
#'
#' Caution: do not reset options but not loaded packages if packages set
#' options on load.
#'
#' @export
#'
daemon <- function(url, asyncdial = FALSE, maxtasks = Inf, idletime = Inf,
walltime = Inf, timerstart = 0L, output = FALSE, ...,
cleanup = c(TRUE, TRUE, TRUE, FALSE), tls = NULL, rs = NULL) {
walltime = Inf, timerstart = 0L, output = FALSE,
cleanup = TRUE, ..., tls = NULL, rs = NULL) {

sock <- socket(protocol = "rep")
on.exit(reap(sock))
Expand All @@ -86,8 +98,7 @@ daemon <- function(url, asyncdial = FALSE, maxtasks = Inf, idletime = Inf,

if (is.numeric(rs)) `[[<-`(.GlobalEnv, ".Random.seed", as.integer(rs))
if (idletime > walltime) idletime <- walltime else if (idletime == Inf) idletime <- NULL
if (length(cleanup) != 4L)
cleanup <- c(cleanup %% 2L, (clr <- as.raw(cleanup)) & as.raw(2L), clr & as.raw(4L), clr & as.raw(8L))
cleanup <- parse_cleanup(cleanup)
if (!output) {
devnull <- file(nullfile(), open = "w", blocking = FALSE)
sink(file = devnull)
Expand Down Expand Up @@ -173,3 +184,9 @@ dial_and_sync_socket <- function(sock, url, asyncdial, tls = NULL) {
dial(sock, url = url, autostart = asyncdial || NA, tls = tls, error = TRUE)
wait(cv)
}

parse_cleanup <- function(cleanup) {
is.logical(cleanup) ||
return(c(as.integer(cleanup) %% 2L, (clr <- as.raw(cleanup)) & as.raw(2L), clr & as.raw(4L), clr & as.raw(8L)))
c(cleanup, cleanup, cleanup, FALSE)
}
3 changes: 2 additions & 1 deletion R/daemons.R
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,8 @@
#' @param ... (optional) additional arguments passed through to
#' \code{\link{dispatcher}} if using dispatcher and/or \code{\link{daemon}}
#' if launching daemons. These include 'token' and 'lock' at dispatcher and
#' 'maxtasks', 'idletime', 'timerstart', 'output' and 'cleanup' at daemon.
#' 'maxtasks', 'idletime', 'walltime', 'timerstart', 'output' and 'cleanup'
#' at daemon.
#' @param seed [default NULL] (optional) supply a random seed (single value,
#' interpreted as an integer). This is used to inititalise the L'Ecuyer-CMRG
#' RNG streams sent to each daemon. Note that reproducible results can be
Expand Down
2 changes: 1 addition & 1 deletion R/parallel.R
Original file line number Diff line number Diff line change
Expand Up @@ -224,7 +224,7 @@ print.miraiNode <- function(x, ...) {

#' @export
#'
`[.miraiCluster` <- function(x, ...) stop(.messages[["not_implemented"]], call. = FALSE)
`[.miraiCluster` <- function(x, ...) stop(.messages[["not_implemented"]])

# internals --------------------------------------------------------------------

Expand Down
32 changes: 23 additions & 9 deletions man/daemon.Rd

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 2 additions & 1 deletion man/daemons.Rd

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion tests/tests.R
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,7 @@ nanotest(daemons(url = value <- mirai:::auto_tokenized_url(), dispatcher = FALSE
nanotest(grepl("://", launch_remote(status()$daemons), fixed = TRUE))
nanotestz(daemons(0L))
Sys.sleep(1L)
nanotesto(daemons(1L, dispatcher = FALSE, idletime = 500L, timerstart = 1L, cleanup = c(FALSE, FALSE, FALSE, FALSE), seed = 1546, .compute = "new"))
nanotesto(daemons(1L, dispatcher = FALSE, idletime = 500L, timerstart = 1L, cleanup = FALSE, seed = 1546, .compute = "new"))
nanotest(is.character(nextget("urls", .compute = "new")))
nanotest(is.integer(nextstream(.compute = "new")))
Sys.sleep(1.5)
Expand Down

0 comments on commit 0b64525

Please sign in to comment.