-
Notifications
You must be signed in to change notification settings - Fork 29
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
How to run_now()
with_temp_loop()
?
#165
Comments
If you want it to run, you need to call library(later)
with_temp_loop({
later(function() print("foo"), delay = 1)
run_now(2)
}) The temporary loop exists until the If you want the loop to persist, you need to do something like this: loop <- create_loop()
with_loop(loop, later(function() print("foo"), delay = 2)) In this case, the loop will exist until it is garbage collected, or you call I decided to test to make what I'm saying is correct; here's the code: library(later)
# A quiet wrapper for gc().
gc <- function() invisible(base::gc())
# A function for checking whether a loop exists, by id. This is so that we don't
# need to keep a reference to the full loop object which holds a reference to
# the underlying data structure and will prevent it from being destroyed.
# Instead, we just need the loop ID.
loop_exists <- function(id) later::exists_loop(list(id = id))
make_f <- function() {
reg.finalizer(
environment(),
function(e) { print("finalized") }
)
function() { print("run") }
}
# Sanity check: creating the function and GC'ing it will cause the finalizer to
# run.
make_f()
NULL # Need to run this at console, so the function isn't saved in .Last.value
gc()
#> [1] "finalized"
# Creating a private loop, scheduling the callback on it, and running the global
# loop with run_now(): will cause the callback to run.
loop <- create_loop()
with_loop(loop, later(make_f(), 2))
run_now(2)
#> [1] "run"
gc()
#> [1] "finalized"
# Creating a private loop, scheduling the callback on it, and then destroying
# the private loop: the callback won't run and can be GC'd.
loop <- create_loop()
with_loop(loop, later(make_f(), 2))
destroy_loop(loop)
gc()
#> [1] "finalized"
# Creating a private loop, scheduling the callback on it, and then removing the
# var referencing the loop: the loop and callback still exist and will run. This
# is because the global loop keeps a reference to the private loop (until it is
# emptied).
loop <- create_loop()
(loop_id <- loop$id)
#> [1] 3
with_loop(loop, later(make_f(), 2))
rm(loop)
gc()
loop_exists(loop_id)
#> [1] TRUE
run_now(2)
#> [1] "run"
loop_exists(loop_id)
#> [1] FALSE
gc()
#> [1] "finalized"
# With parent=NULL, the loop (and objects in it) will be finalized after there
# are no more references to it -- it doesn't have to wait until the loop is
# empty.
loop <- create_loop(parent = NULL)
(loop_id <- loop$id)
#> [1] 4
with_loop(loop, later(make_f(), 2))
rm(loop)
loop_exists(loop_id)
#> [1] TRUE
gc() # Loop is destroyed on first GC
loop_exists(loop_id)
#> [1] FALSE
gc() # Callback env is finalized on second GC
#> [1] "finalized" |
@wch aaaahhhh that makes sense, I I also assume, then, that something like this (swapping the delay & timeout values in your example) would be an anti-pattern preventing execution: with_temp_loop({
later(function() print("foo"), delay = 2)
run_now(1) ## too soon, as the `later` function isn't ready yet.
}) If I gin up some examples (using some of your examples from this thread), would it be worth me adding to the documentation and submitting a PR (or do y'all prefer to write your own documentation internally)? |
Yes, thanks, that would be good to add in the documentation! If you are feeling ambitious, a new page about private event loops would be a great thing to have. |
I'm probably missing something very obvious here, but I'm also completed stumped as to how to use
with_temp_loop()
.Here's a trivial global-loop example:
Works great; prints "foo" after a few seconds.
Now I wanted to pop this onto a different (i.e. non-global) loop ... one way is to formally create a loop and use that loop's reference. Per the documentation, for a one-time-only later execution we can also do something like this(?):
But this never seems to execute. And since temp loops are created with
parent=NULL
(and thus the global loop'srun_now()
doesn't trigger this temp loop to run), it's not obvious to me how to force execution withrun_now()
(since we don't have a reference to the loop).Perhaps related to rstudio/httpuv#250?
The text was updated successfully, but these errors were encountered: