mirror of
https://github.com/rstudio/shiny.git
synced 2026-01-13 08:57:57 -05:00
92 lines
2.1 KiB
R
92 lines
2.1 KiB
R
# Return the current time, in milliseconds from epoch, with
|
|
# unspecified time zone.
|
|
now <- function() {
|
|
as.numeric(Sys.time()) * 1000
|
|
}
|
|
|
|
TimerCallbacks <- R6Class(
|
|
'TimerCallbacks',
|
|
portable = FALSE,
|
|
class = FALSE,
|
|
public = list(
|
|
.nextId = 0L,
|
|
.funcs = 'Map',
|
|
.times = data.frame(),
|
|
|
|
initialize = function() {
|
|
.funcs <<- Map$new()
|
|
},
|
|
clear = function() {
|
|
.nextId <<- 0L
|
|
.funcs$clear()
|
|
.times <<- data.frame()
|
|
},
|
|
schedule = function(millis, func) {
|
|
# If args could fail to evaluate, let's make them do that before
|
|
# we change any state
|
|
force(millis)
|
|
force(func)
|
|
|
|
id <- .nextId
|
|
.nextId <<- .nextId + 1L
|
|
|
|
t <- now()
|
|
|
|
# TODO: Horribly inefficient, use a heap instead
|
|
.times <<- rbind(.times, data.frame(time=t+millis,
|
|
scheduled=t,
|
|
id=id))
|
|
.times <<- .times[order(.times$time),]
|
|
|
|
.funcs$set(as.character(id), func)
|
|
|
|
return(id)
|
|
},
|
|
timeToNextEvent = function() {
|
|
if (dim(.times)[1] == 0)
|
|
return(Inf)
|
|
return(.times[1, 'time'] - now())
|
|
},
|
|
takeElapsed = function() {
|
|
t <- now()
|
|
elapsed <- .times$time < now()
|
|
result <- .times[elapsed,]
|
|
.times <<- .times[!elapsed,]
|
|
|
|
# TODO: Examine scheduled column to check if any funny business
|
|
# has occurred with the system clock (e.g. if scheduled
|
|
# is later than now())
|
|
|
|
return(result)
|
|
},
|
|
executeElapsed = function() {
|
|
elapsed <- takeElapsed()
|
|
if (nrow(elapsed) == 0)
|
|
return(FALSE)
|
|
|
|
for (id in elapsed$id) {
|
|
thisFunc <- .funcs$remove(as.character(id))
|
|
# TODO: Catch exception, and...?
|
|
# TODO: Detect NULL, and...?
|
|
thisFunc()
|
|
}
|
|
return(TRUE)
|
|
}
|
|
)
|
|
)
|
|
|
|
timerCallbacks <- TimerCallbacks$new()
|
|
|
|
scheduleTask <- function(millis, callback) {
|
|
cancelled <- FALSE
|
|
timerCallbacks$schedule(millis, function() {
|
|
if (!cancelled)
|
|
callback()
|
|
})
|
|
|
|
function() {
|
|
cancelled <<- TRUE
|
|
callback <<- NULL # to allow for callback to be gc'ed
|
|
}
|
|
}
|