R/load.R

##' Loading and unloading shared-object libraries
##'
##' \code{pompLoad} and \code{pompUnload} cause compiled codes associated with \code{object} to be dynamically linked or unlinked, respectively.
##' \code{solibs<-} is a helper function for developers of packages that extend \pkg{pomp}.
##'
##' When C snippets are used in the construction of a \sQuote{pomp} object, the resulting shared-object library is dynamically loaded (linked) before each use, and unloaded afterward.
##'
##' @name load
##' @docType methods
##' @rdname load
##' @aliases pompLoad pompUnload solibs<-
##' @include pomp_class.R
##' @keywords internal
NULL

setGeneric(
  "pompLoad",
  function (object, ...)
    standardGeneric("pompLoad")
)

setGeneric(
  "pompUnload",
  function (object, ...)
    standardGeneric("pompUnload")
)

setGeneric(
  "solibs<-",
  function (object, ..., value)
    standardGeneric("solibs<-")
)

##' @rdname load
##' @param object an object of class \sQuote{pomp}, or extending this class.
##' @export
setMethod(
  "pompLoad",
  signature=signature(object="pomp"),
  definition = function (object, ...) {
    pompLoad_internal(object,...)
  })

##' @rdname load
##' @export
setMethod(
  "pompUnload",
  signature=signature(object="pomp"),
  definition = function (object, ...) {
    pompUnload_internal(object,...)
  })

##' @rdname load
##' @details
##' \code{solibs<-} prepends the \sQuote{lib} generated by \code{\link{hitch}}
##'  to the \sQuote{solibs} slot of a \sQuote{pomp} object.
##' @export
setMethod(
  "solibs<-",
  signature=signature(object="pomp"),
  definition=function (object, ..., value) {
    if (!is.null(value)) {
      object@solibs <- c(list(value),object@solibs)
    }
    object
  }
)

pompLoad_internal <- function (object, ...,
  verbose = getOption("verbose", FALSE)) {
  .Call(P_set_userdata,object@userdata)
  for (lib in object@solibs) {
    if (!is.loaded("__pomp_load_stack_incr",PACKAGE=lib$name)) {
      dir <- srcDir(lib$dir,verbose=verbose)
      solib <- file.path(dir,paste0(lib$name,.Platform$dynlib.ext))
      if (file.exists(solib)) {
        dyn.load(solib)
      } else {
        pompCompile(fname=lib$name,direc=dir,src=lib$src,verbose=verbose)
        dyn.load(solib)
      }
      if (verbose) cat("loading",sQuote(solib),"\n")
    }
    .Call(P_load_stack_incr,lib$name)
  }
  invisible(NULL)
}

pompUnload_internal <- function (object, ...,
  verbose = getOption("verbose", FALSE)) {
  for (lib in object@solibs) {
    if (is.loaded("__pomp_load_stack_decr",PACKAGE=lib$name)) {
      st <- .Call(P_load_stack_decr,lib$name)
      if (st==0) {
        dir <- srcDir(lib$dir,verbose=verbose)
        solib <- file.path(dir,paste0(lib$name,.Platform$dynlib.ext))
        dyn.unload(solib)
        if (verbose) cat("unloading",sQuote(solib),"\n")
      }
    }
  }
  invisible(NULL)
}
kingaa/pomp documentation built on May 4, 2024, 1:20 p.m.