Skip to content

Commit 10ec3cc

Browse files
resolved(): consolidate and improve documentation
1 parent 43abfe2 commit 10ec3cc

11 files changed

+141
-78
lines changed

DESCRIPTION

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
Package: future
2-
Version: 1.58.0-9001
2+
Version: 1.58.0-9002
33
Title: Unified Parallel and Distributed Processing in R for Everyone
44
Depends:
55
R (>= 3.2.0)

R/backend_api-11.ClusterFutureBackend-class.R

Lines changed: 25 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -545,6 +545,26 @@ getSocketSelectTimeout <- function(future, timeout = NULL) {
545545
} ## getSocketSelectTimeout()
546546

547547

548+
#' @param timeout (numeric) The maximum time (in seconds) for polling the worker
549+
#' for a response. If no response is available within this time limit, FALSE is
550+
#' returned assuming the future is still being processed.
551+
#' If NULL, the value defaults to `getOption("future.<type>.resolved.timeout")`,
552+
#' then `getOption("future.resolved.timeout")`, and finally 0.01 (seconds),
553+
#' where `<type>` corresponds to the type of future, e.g. `cluster` and `multicore`.
554+
#'
555+
#' @section Behavior of cluster and multisession futures:
556+
#' `resolved()` for `ClusterFuture`, and therefore also `MultisessionFuture`,
557+
#' will always check whether any of the currently running futures are resolved,
558+
#' and if one of them has been resolved, then its result is collected. This makes
559+
#' sure to free up workers, when possible.
560+
#'
561+
#' `resolved()` for `ClusterFuture` may receive immediate condition objects, rather
562+
#' than a [FutureResult], when polling the worker for results. In such cases, the
563+
#' condition object is collected and another poll it performed. Up to 100 immediate
564+
#' conditions may be collected this way per `resolved()` call, before considering
565+
#' the future non-resolved and FALSE being returned.
566+
#'
567+
#' @rdname resolved
548568
#' @importFrom parallelly connectionId isConnectionValid
549569
#' @export
550570
resolved.ClusterFuture <- function(x, run = TRUE, timeout = NULL, ...) {
@@ -585,7 +605,8 @@ resolved.ClusterFuture <- function(x, run = TRUE, timeout = NULL, ...) {
585605

586606
## If at least one is available, then launch this lazy future
587607
if (any(avail)) future <- run(future)
588-
}
608+
} ## if (run)
609+
589610
return(FALSE)
590611
}
591612

@@ -1568,15 +1589,15 @@ handleInterruptedFuture <- local({
15681589
#' If a function, it is called without arguments _when the future
15691590
#' is created_ and its value is used to configure the workers.
15701591
#' The function should return any of the above types.
1592+
#' If `workers == 1`, then all processing using done in the
1593+
#' current/main \R session and we therefore fall back to using a
1594+
#' sequential future. To override this fallback, use `workers = I(1)`.
15711595
#'
15721596
#' @param persistent If FALSE, the evaluation environment is cleared
15731597
#' from objects prior to the evaluation of the future.
15741598
#'
15751599
#' @param \ldots Additional named elements passed to [Future()].
15761600
#'
1577-
#' @return
1578-
#' A ClusterFuture.
1579-
#'
15801601
#' @example incl/cluster.R
15811602
#'
15821603
#' @seealso

R/backend_api-11.MulticoreFutureBackend-class.R

Lines changed: 8 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -271,19 +271,11 @@ nbrOfFreeWorkers.MulticoreFutureBackend <- function(evaluator, background = FALS
271271

272272

273273

274-
#' A multicore future is a future whose value will be resolved asynchronously in a parallel process
275-
#'
276-
#' @inheritParams MultiprocessFuture-class
277-
#' @inheritParams Future-class
278-
#'
279-
#' @return
280-
#' `MulticoreFuture()` returns an object of class `MulticoreFuture`.
281-
#'
282-
#' @section Usage:
283-
#' To use 'multicore' futures, use `plan(multicore, ...)`, cf. [multicore].
284-
#'
285-
#' @name MulticoreFuture-class
286-
#' @keywords internal
274+
#' @section Behavior of multicore futures:
275+
#' `resolved()` for `MulticoreFuture` may receive immediate condition objects, rather than a
276+
#' [FutureResult], when polling the worker for results. In such cases, _all_ such condition
277+
#' objects are collected, before considering the future non-resolved and FALSE being returned.
278+
#' @rdname resolved
287279
#' @export
288280
resolved.MulticoreFuture <- local({
289281
selectChildren <- import_parallel_fcn("selectChildren")
@@ -618,16 +610,11 @@ interruptFuture.MulticoreFutureBackend <- function(backend, future, ...) {
618610
#' @param workers The number of parallel processes to use.
619611
#' If a function, it is called without arguments _when the future
620612
#' is created_ and its value is used to configure the workers.
621-
#'
622-
#' @param \ldots Additional named elements to [Future()].
623-
#'
624-
#' @return
625-
#' A [Future].
626613
#' If `workers == 1`, then all processing using done in the
627614
#' current/main \R session and we therefore fall back to using a
628615
#' sequential future. To override this fallback, use `workers = I(1)`.
629-
#' This is also the case whenever multicore processing is not supported,
630-
#' e.g. on Windows.
616+
#'
617+
#' @param \ldots Additional named elements to [Future()].
631618
#'
632619
#' @example incl/multicore.R
633620
#'
@@ -665,6 +652,7 @@ interruptFuture.MulticoreFutureBackend <- function(backend, future, ...) {
665652
#' whether multicore futures are supported or not on the current
666653
#' system.
667654
#'
655+
#' @aliases MulticoreFuture
668656
#' @export
669657
multicore <- function(..., workers = availableCores(constraints = "multicore"), gc = FALSE, earlySignal = FALSE, envir = parent.frame()) {
670658
stop("INTERNAL ERROR: The future::multicore() function must never be called directly")

R/backend_api-13.MultisessionFutureBackend-class.R

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -127,6 +127,7 @@ print.MultisessionFutureBackend <- function(x, validate = TRUE, ...) {
127127
#' Use [parallelly::availableCores()] to see the total number of
128128
#' cores that are available for the current \R session.
129129
#'
130+
#' @aliases MultisessionFuture
130131
#' @export
131132
multisession <- function(..., workers = availableCores(), lazy = FALSE, rscript_libs = .libPaths(), gc = FALSE, earlySignal = FALSE, envir = parent.frame()) {
132133
stop("INTERNAL ERROR: The future::multisession() must never be called directly")

R/backend_api-Future-class.R

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -722,6 +722,7 @@ result.Future <- function(future, ...) {
722722
}
723723

724724

725+
#' @rdname resolved
725726
#' @export
726727
resolved.Future <- function(x, run = TRUE, ...) {
727728
future <- x

R/core_api-resolved.R

Lines changed: 24 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -3,20 +3,28 @@
33
#' @param x A \link{Future}, a list, or an environment (which also
44
#' includes \link[listenv:listenv]{list environment}).
55
#'
6+
#' @param run (logical) If TRUE, any lazy futures is launched,
7+
#' otherwise not.
8+
#'
69
#' @param \ldots Not used.
710
#'
8-
#' @return A logical of the same length and dimensions as `x`.
11+
#' @return
12+
#' A logical vector of the same length and dimensions as `x`.
913
#' Each element is TRUE unless the corresponding element is a
1014
#' non-resolved future in case it is FALSE.
1115
#'
1216
#' @details
13-
#' This method needs to be implemented by the class that implement
14-
#' the Future API. The implementation should return either TRUE or FALSE
15-
#' and must never throw an error (except for [FutureError]:s which indicate
16-
#' significant, often unrecoverable infrastructure problems).
17-
#' It should also be possible to use the method for polling the
18-
#' future until it is resolved (without having to wait infinitely long),
19-
#' e.g. `while (!resolved(future)) Sys.sleep(5)`.
17+
#' Checking a lazy future, triggers it to be launched, unless `run = FALSE`.
18+
#'
19+
#' `resolved()` methods must always return `TRUE` or `FALSE` values, must
20+
#' always launch lazy futures by default (`run = TRUE`), and must never block
21+
#' indefinitely. This is because it should always be possible to poll futures
22+
#' until they are resolved using `resolved()`, e.g.
23+
#' `while (!all(resolved(futures))) Sys.sleep(5)`.
24+
#'
25+
#' Each future backend must implement a `resolved()` method that returns
26+
#' either TRUE or FALSE, or throw a [FutureError] (which indicate a
27+
#' significant, often unrecoverable infrastructure problem, or an interrupt).
2028
#'
2129
#' @export
2230
resolved <- function(x, ...) {
@@ -37,9 +45,15 @@ resolved <- function(x, ...) {
3745
UseMethod("resolved")
3846
}
3947

48+
#' @return
49+
#' The default method always returns TRUE.
50+
#'
51+
#' @rdname resolved
4052
#' @export
4153
resolved.default <- function(x, ...) TRUE
4254

55+
56+
#' @rdname resolved
4357
#' @export
4458
resolved.list <- function(x, ...) {
4559
debug <- isTRUE(getOption("future.debug"))
@@ -76,6 +90,8 @@ resolved.list <- function(x, ...) {
7690
res
7791
}
7892

93+
94+
#' @rdname resolved
7995
#' @export
8096
resolved.environment <- function(x, ...) {
8197
debug <- isTRUE(getOption("future.debug"))

man/MulticoreFuture-class.Rd

Lines changed: 0 additions & 21 deletions
This file was deleted.

man/cluster.Rd

Lines changed: 4 additions & 4 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

man/multicore.Rd

Lines changed: 5 additions & 9 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

man/multisession.Rd

Lines changed: 5 additions & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)