#' Lock external directory 
#'
#' Lock the external directory so that multiple processes cannot try to create environments at the same time.
#'
#' @param path String containing the path to the external directory.
#' @param ... For \code{lockExternalDir}, further arguments to pass to \code{\link[dir.expiry]{lockDirectory}} such as \code{exclusive}.
#' For \code{unlockExternalDir}, further arguments to pass to \code{\link[dir.expiry]{unlockDirectory}} such as \code{clear}.
#' @param lock.info A lock object generated by \code{\link[dir.expiry]{lockDirectory}}.
#'
#' @return 
#' \code{lockExternalDir} will return a lock object from \code{\link[dir.expiry]{lockDirectory}}.
#' 
#' \code{unlockExternalDir} will unlock the file and return \code{NULL} invisibly.
#'
#' @details
#' This will apply a lock to the (possibly user-specified) external environment directory,
#' so that a user trying to run parallel \pkg{basilisk} processes will not have race conditions during lazy environment creation.
#' We use \pkg{dir.expiry} to manage the locking process for us, with the following strategy:
#' \itemize{
#' \item If a system installation is being performed, we do not perform any locking.
#' Rather, the R package manager will lock the entire R installation directory for us.
#' \item If the external directory is not yet present, we establish an exclusive lock and create that directory.
#' \item If an external installation directory is already present, we establish a shared lock.
#' This will wait for any exclusive lock to expire (and thus any currently running installation to finish).
#' No waiting is required if there are no existing exclusive locks.
#' }
#'
#' Note that locking is only required during the creation of virtual environments, not during their actual use.
#' Once an environment is created, we assume that it is read-only for all processes.
#'
#' @author Aaron Lun
#'
#' @examples
#' loc <- lockExternalDir()
#' unlockExternalDir(loc)
#'
#' @export
#' @importFrom dir.expiry lockDirectory
lockExternalDir <- function(path=getExternalDir(), ...) {
    lockDirectory(path, ...)
}

#' @export
#' @rdname lockExternalDir
#' @importFrom dir.expiry unlockDirectory
unlockExternalDir <- function(lock.info, ...) {
    if (!is.null(lock.info)) {
        unlockDirectory(lock.info, ...)
    }
    invisible(NULL)
}
