Advertisement
Guest User

Untitled

a guest
Dec 8th, 2016
74
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 2.38 KB | None | 0 0
  1. library(shiny)
  2. # Also uses parallel, shinyjs, tools
  3.  
  4. # Create a long-running task, executed in a forked process. (Doesn't work on Windows)
  5. #
  6. # The return value is a promise-like object with three
  7. # methods:
  8. # - completed(): FALSE initially, then TRUE if the task succeeds,
  9. # fails, or is cancelled. Reactive, so when the state changes
  10. # any reactive readers will invalidate.
  11. # - result(): Use this to get the return value. While execution is
  12. # in progress, performs a req(FALSE). If task succeeded, returns
  13. # the return value. If failed, throws error. Reactive, so when
  14. # the state changes any reactive readers will invalidate.
  15. # - cancel(): Call this to prematurely terminate the task.
  16. create_forked_task <- function(expr) {
  17. makeReactiveBinding("state")
  18. state <- factor("running",
  19. levels = c("running", "success", "error", "cancel"),
  20. ordered = TRUE
  21. )
  22.  
  23. result <- NULL
  24.  
  25. # Launch the task in a forked process. This always returns
  26. # immediately, and we get back a handle we can use to monitor
  27. # or kill the job.
  28. task_handle <- parallel::mcparallel({
  29. force(expr)
  30. })
  31.  
  32. # Poll every 100 milliseconds until the job completes
  33. o <- observe({
  34. res <- parallel::mccollect(task_handle, wait = FALSE)
  35. if (is.null(res)) {
  36. invalidateLater(100)
  37. } else {
  38. o$destroy()
  39. if (!is.list(res) || length(res) != 1 || !inherits(res[[1]], "try-error")) {
  40. state <<- "success"
  41. result <<- res[[1]]
  42. } else {
  43. state <<- "error"
  44. result <<- attr(res[[1]], "condition", exact = TRUE)
  45. }
  46. }
  47. })
  48.  
  49. list(
  50. completed = function() {
  51. state != "running"
  52. },
  53. result = function() {
  54. if (state == "running") {
  55. # If running, abort the current context silently.
  56. # We've taken a reactive dependency on "state" so if
  57. # the state changes the context will invalidate.
  58. req(FALSE)
  59. } else if (state == "success") {
  60. return(result)
  61. } else if (state == "error") {
  62. stop(result)
  63. } else if (state == "cancel") {
  64. validate(need(FALSE, "The operation was cancelled"))
  65. }
  66. },
  67. cancel = function() {
  68. if (state == "running") {
  69. state <<- "cancel"
  70. o$destroy()
  71. tools::pskill(task_handle$pid, tools::SIGTERM)
  72. tools::pskill(-task_handle$pid, tools::SIGTERM)
  73. parallel::mccollect(task_handle, wait = FALSE)
  74. }
  75. }
  76. )
  77. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement