File: future_promise.Rd

package info (click to toggle)
r-cran-promises 1.2.0.1%2Bdfsg-1
  • links: PTS, VCS
  • area: main
  • in suites: bookworm
  • size: 2,420 kB
  • sloc: cpp: 45; sh: 13; makefile: 2
file content (122 lines) | stat: -rw-r--r-- 5,037 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
% Generated by roxygen2: do not edit by hand
% Please edit documentation in R/future_promise.R
\name{future_promise_queue}
\alias{future_promise_queue}
\alias{future_promise}
\title{\pkg{future} promise}
\usage{
future_promise_queue()

future_promise(
  expr = NULL,
  envir = parent.frame(),
  substitute = TRUE,
  globals = TRUE,
  packages = NULL,
  ...,
  queue = future_promise_queue()
)
}
\arguments{
\item{expr}{An R expression. While the \code{expr} is eventually sent to \code{\link[future:future]{future::future()}}, please use the same precautions that you would use with regular \code{promises::promise()} expressions. \code{future_promise()} may have to hold the \code{expr} in a \code{\link[=promise]{promise()}} while waiting for a \pkg{future} worker to become available.}

\item{envir}{The \link{environment} from where global objects should be
identified.}

\item{substitute}{If TRUE, argument \code{expr} is
\code{\link[base]{substitute}()}:ed, otherwise not.}

\item{globals}{(optional) a logical, a character vector, or a named list
to control how globals are handled.
For details, see section 'Globals used by future expressions'
in the help for \code{\link[future:future]{future()}}.}

\item{packages}{(optional) a character vector specifying packages
to be attached in the \R environment evaluating the future.}

\item{...}{extra parameters provided to \code{\link[future:future]{future::future()}}}

\item{queue}{A queue that is used to schedule work to be done using \code{\link[future:future]{future::future()}}.  This queue defaults to \code{\link[=future_promise_queue]{future_promise_queue()}} and requires that method \code{queue$schedule_work(fn)} exist.  This method should take in a function that will execute the promised \pkg{future} work.}
}
\value{
Unlike [future::future()\verb{], }future_promise()\verb{returns a [promise()] object that will eventually resolve the \pkg{future}}expr`.
}
\description{
\ifelse{html}{\out{<a href='https://www.tidyverse.org/lifecycle/#experimental'><img src='figures/lifecycle-experimental.svg' alt='Experimental lifecycle'></a>}}{\strong{Experimental}}
}
\details{
When submitting \pkg{future} work, \pkg{future} (by design) will block the main R session until a worker becomes available.
This occurs when there is more submitted \pkg{future} work than there are available \pkg{future} workers.
To counter this situation, we can create a promise to execute work using future (using \code{future_promise()}) and only begin the work if a \pkg{future} worker is available.

Using \code{future_promise()} is recommended when ever a continuous runtime is used, such as with \pkg{plumber} or \pkg{shiny}.

For more details and examples, please see the \href{https://rstudio.github.io/promises/articles/future_promise.html}{\code{vignette("future_promise", "promises")}} vignette().
}
\section{Functions}{
\itemize{
\item \code{future_promise_queue}: Default \code{future_promise()} work queue to use. This function returns a \link{WorkQueue} that is cached per R session.

\item \code{future_promise}: Creates a \code{\link[=promise]{promise()}} that will execute the \code{expr} using \code{\link[future:future]{future::future()}}.
}}

\examples{
\donttest{# Relative start time
start <- Sys.time()
# Helper to force two `future` workers
with_two_workers <- function(expr) {
  if (!require("future")) {
    message("`future` not installed")
    return()
  }
  old_plan <- future::plan(future::multisession(workers = 2))
  on.exit({future::plan(old_plan)}, add = TRUE)
  start <<- Sys.time()
  force(expr)
  while(!later::loop_empty()) {Sys.sleep(0.1); later::run_now()}
  invisible()
}
# Print a status message. Ex: `"PID: XXX; 2.5s promise done"`
print_msg <- function(pid, msg) {
  message(
    "PID: ", pid, "; ",
    round(difftime(Sys.time(), start, units = "secs"), digits = 1), "s " ,
    msg
  )
}

# `"promise done"` will appear after four workers are done and the main R session is not blocked
# The important thing to note is the first four times will be roughly the same
with_two_workers({
  promise_resolve(Sys.getpid()) \%...>\% print_msg("promise done")
  for (i in 1:6) future::future({Sys.sleep(1); Sys.getpid()}) \%...>\% print_msg("future done")
})
{
#> PID: XXX; 2.5s promise done
#> PID: YYY; 2.6s future done
#> PID: ZZZ; 2.6s future done
#> PID: YYY; 2.6s future done
#> PID: ZZZ; 2.6s future done
#> PID: YYY; 3.4s future done
#> PID: ZZZ; 3.6s future done
}

# `"promise done"` will almost immediately, before any workers have completed
# The first two `"future done"` comments appear earlier the example above
with_two_workers({
  promise_resolve(Sys.getpid()) \%...>\% print_msg("promise")
  for (i in 1:6) future_promise({Sys.sleep(1); Sys.getpid()}) \%...>\% print_msg("future done")
})
{
#> PID: XXX; 0.2s promise done
#> PID: YYY; 1.3s future done
#> PID: ZZZ; 1.4s future done
#> PID: YYY; 2.5s future done
#> PID: ZZZ; 2.6s future done
#> PID: YYY; 3.4s future done
#> PID: ZZZ; 3.6s future done
}}
}
\seealso{
\code{\link{WorkQueue}}
}