diff --git a/.Rbuildignore b/.Rbuildignore
index 2bc8698b2..7109ad47f 100644
--- a/.Rbuildignore
+++ b/.Rbuildignore
@@ -1,14 +1,21 @@
^.*\.Rproj$
-^\.Rproj\.user$
-^\.Rprofile$
-^src/tbb/build/lib_.*$
-^tests/testthat/pkg/RcppParallelTest/src/.*\.s?o$
-^tests/testthat/pkg/RcppParallelTest/src/.*\.dll$
-^inst/lib$
^.travis.yml
^README.md
-^doc$
-^src/.*\.o$
-^gen/
+^\.Rprofile$
+^\.Rproj\.user$
^appveyor\.yml$
+^check$
+^doc$
+^gen$
+^libs$
+^inst/lib$
+^inst/libs$
^revdep$
+^src/.*\.o$
+^src/tbb/build$
+^tags$
+^tests/testthat/pkg/RcppParallelTest/src/.*\.dll$
+^tests/testthat/pkg/RcppParallelTest/src/.*\.s?o$
+^tools/tbb$
+^\.github$
+^patches
\ No newline at end of file
diff --git a/.github/.gitignore b/.github/.gitignore
new file mode 100644
index 000000000..2d19fc766
--- /dev/null
+++ b/.github/.gitignore
@@ -0,0 +1 @@
+*.html
diff --git a/.github/workflows/R-CMD-check.yaml b/.github/workflows/R-CMD-check.yaml
new file mode 100644
index 000000000..897585d50
--- /dev/null
+++ b/.github/workflows/R-CMD-check.yaml
@@ -0,0 +1,39 @@
+# Workflow derived from https://github.com/r-lib/actions/tree/v2/examples
+# Need help debugging build failures? Start at https://github.com/r-lib/actions#where-to-find-help
+on:
+ push:
+ branches: [main, master]
+ pull_request:
+ branches: [main, master]
+
+name: R-CMD-check
+
+jobs:
+ R-CMD-check:
+ runs-on: ${{ matrix.config.os }}
+
+ name: ${{ matrix.config.os }} (${{ matrix.config.r }})
+
+ strategy:
+ fail-fast: false
+ matrix:
+ config:
+ - {os: macOS-latest, r: 'release'}
+ - {os: ubuntu-latest, r: 'release'}
+ - {os: windows-latest, r: 'release'}
+ env:
+ GITHUB_PAT: ${{ secrets.GITHUB_TOKEN }}
+ R_KEEP_PKG_SOURCE: yes
+ steps:
+ - uses: actions/checkout@v3
+
+ - uses: r-lib/actions/setup-r@v2
+ with:
+ use-public-rspm: true
+
+ - uses: r-lib/actions/setup-r-dependencies@v2
+ with:
+ extra-packages: any::rcmdcheck
+ needs: check
+
+ - uses: r-lib/actions/check-r-package@v2
diff --git a/.gitignore b/.gitignore
index 4efd25bce..240c3f21c 100644
--- a/.gitignore
+++ b/.gitignore
@@ -3,9 +3,18 @@
.Rhistory
.RData
.DS_Store
-config.log
-config.status
-autom4te.cache/
-src-i386/
-src-x64/
+check
inst/doc
+inst/lib
+inst/libs
+libs
+revdep
+src-i386
+src-x64
+tbb.log
+
+src/tbb/build
+src/tbb/build-tbb
+
+R/tbb-autodetected.R
+
diff --git a/.travis.yml b/.travis.yml
deleted file mode 100644
index 13c0af011..000000000
--- a/.travis.yml
+++ /dev/null
@@ -1,23 +0,0 @@
-# Run Travis CI for R using https://eddelbuettel.github.io/r-travis/
-
-language: c
-sudo: required
-group: edge
-
-before_install:
- - curl -OLs https://eddelbuettel.github.io/r-travis/run.sh && chmod 0755 run.sh
- - ./run.sh bootstrap
-
-install:
- - ./run.sh install_aptget r-cran-rcpp r-cran-bh r-cran-runit r-cran-knitr r-cran-rmarkdown
-
-script:
- - ./run.sh run_tests
-
-after_failure:
- - ./run.sh dump_logs
-
-notifications:
- email:
- on_success: change
- on_failure: change
\ No newline at end of file
diff --git a/DESCRIPTION b/DESCRIPTION
index baf8f0d24..d51de8a09 100644
--- a/DESCRIPTION
+++ b/DESCRIPTION
@@ -1,35 +1,39 @@
Package: RcppParallel
Type: Package
Title: Parallel Programming Tools for 'Rcpp'
-Version: 4.4.4
+Version: 5.1.10.9000
Authors@R: c(
+ person("Kevin", "Ushey", role = c("aut", "cre"), email = "kevin@rstudio.com",
+ comment = c(ORCID = "0000-0003-2880-7407")),
person("JJ", "Allaire", role = c("aut"), email = "jj@rstudio.com"),
person("Romain", "Francois", role = c("aut", "cph")),
- person("Kevin", "Ushey", role = c("aut", "cre"), email = "kevin@rstudio.com"),
person("Gregory", "Vandenbrouck", role = "aut"),
person("Marcus", "Geelnard", role = c("aut", "cph"),
- comment = "TinyThread library, http://tinythreadpp.bitsnbites.eu/"),
- person(family = "RStudio", role = "cph"),
- person(family = "Intel", role = c("aut", "cph"),
- comment = "Intel TBB library, https://www.threadingbuildingblocks.org/"),
- person(family = "Microsoft", role = "cph")
+ comment = "TinyThread library, https://tinythreadpp.bitsnbites.eu/"),
+ person("Hamada S.", "Badr", email = "badr@jhu.edu", role = c("ctb"),
+ comment = c(ORCID = "0000-0002-9808-2344")),
+ person("Dirk", "Eddelbuettel", role = c("aut"), email = "edd@debian.org",
+ comment = c(ORCID = "0000-0001-6419-907X")),
+ person(family = "Intel", role = c("aut", "cph"), comment = "oneTBB library"),
+ person(family = "UXL Foundation", role = c("aut", "cph"), comment = "oneTBB library"),
+ person(family = "Microsoft", role = "cph"),
+ person(family = "Posit, PBC", role = "cph")
)
Description: High level functions for parallel programming with 'Rcpp'.
For example, the 'parallelFor()' function can be used to convert the work of
a standard serial "for" loop into a parallel one and the 'parallelReduce()'
function can be used for accumulating aggregate or other values.
-Depends: R (>= 3.0.2)
+Depends: R (>= 3.6.0)
Suggests:
Rcpp,
RUnit,
knitr,
rmarkdown
-SystemRequirements: GNU make, Windows: cmd.exe and cscript.exe, Solaris: g++ is required
-License: GPL-2
-URL: http://rcppcore.github.io/RcppParallel, https://github.com/RcppCore/RcppParallel
+Roxygen: list(markdown = TRUE)
+SystemRequirements: CMake (>= 3.5)
+License: GPL (>= 3)
+URL: https://rcppcore.github.io/RcppParallel/, https://github.com/RcppCore/RcppParallel
+BugReports: https://github.com/RcppCore/RcppParallel/issues
Biarch: TRUE
-Collate:
- 'build.R'
- 'hooks.R'
- 'options.R'
- 'skeleton.R'
+RoxygenNote: 7.3.2
+Encoding: UTF-8
diff --git a/NAMESPACE b/NAMESPACE
index 2cd799681..94da28d51 100644
--- a/NAMESPACE
+++ b/NAMESPACE
@@ -1,6 +1,9 @@
-export(setThreadOptions)
-export(defaultNumThreads)
-export(RcppParallelLibs)
+# Generated by roxygen2: do not edit by hand
+
export(CxxFlags)
export(LdFlags)
export(RcppParallel.package.skeleton)
+export(RcppParallelLibs)
+export(defaultNumThreads)
+export(setThreadOptions)
+export(tbbLibraryPath)
diff --git a/NEWS.md b/NEWS.md
new file mode 100644
index 000000000..80cdc71e8
--- /dev/null
+++ b/NEWS.md
@@ -0,0 +1,203 @@
+
+## RcppParallel 6.0.0 (UNRELEASED)
+
+* RcppParallel no longer includes tbb headers as part of the RcppParallel/TBB.h
+ header, and instead only exposes its TBB-specific APIs for parallel work.
+
+* RcppParallel now bundles oneTBB 2022.0.0. Note that the TBB ABI has changed;
+ packages which depend on RcppParallel may need to be rebuilt.
+
+* On Windows, RcppParallel now uses the copy of TBB provided by Rtools.
+ If TBB is not available, RcppParallel will use only the fallback 'tinythread'
+ implementation. In practice, this implies that RcppParallel will now only
+ provide a TBB backend with R (>= 4.2.0).
+
+## RcppParallel 5.1.11
+
+* Compatibility fixes for LLVM 21.
+
+## RcppParallel 5.1.10
+
+* Fixed an issue where packages linking to RcppParallel could inadverently
+ depend on internals of the TBB library available during compilation, even
+ if the package did not explicitly use TBB itself.
+
+## RcppParallel 5.1.9
+
+* RcppParallel no longer passes `-rpath` when building / linking on Windows.
+ This fixes build issues when building RcppParallel when using the LLVM
+ linker on Windows. (@kalibera)
+
+## RcppParallel 5.1.8
+
+* RcppParallel now explicitly links to the bundled copy of TBB on macOS. (#206; @jeroen)
+
+## RcppParallel 5.1.7
+
+* Remove deprecated `std::iterator`. (#192; @Enchufa2)
+
+## RcppParallel 5.1.6
+
+* Patch for TBB to allow compilation with gcc-13.
+
+* Fixed a memory leak that could occur when using TinyThread on POSIX systems.
+ (#185; @dipertix and and @kevinushey)
+
+## RcppParallel 5.1.5
+
+* Patches to ensure compatibility with the R 4.2.0 UCRT toolchain on Windows,
+ adapted from patches contributed by Tomas Kalibera.
+
+* Fixed an issue where setting `TBB_ROOT` (or `TBB_INC` / `TBB_LIB`) would
+ copy rather than symlink the associated libraries. (#161)
+
+## RcppParallel 5.1.4
+
+* Fixed an issue causing client packages of RcppParallel to fail to compile
+ on Solaris.
+
+## RcppParallel 5.1.3
+
+* Fixed an issue that prevented compilation of RcppParallel with R (< 4.0.0)
+ of R on Windows.
+
+* The `RCPP_PARALLEL_USE_TBBMALLOC_PROXY` environment variable can now be used
+ to control whether RcppParallel loads the `tbbmalloc_proxy` library on load.
+ See https://www.threadingbuildingblocks.org/docs/help/tbb_userguide/Automically_Replacing_malloc.html
+ for more information.
+
+## RcppParallel 5.1.2
+
+* `RcppParallel` gains the `tbbLibraryPath()` function, to be used when attempting
+ to query the location of the TBB libraries that `RcppParallel` has been
+ configured to use. This may be useful for R packages which wish to explicitly
+ use, or link to, these libraries.
+
+## RcppParallel 5.1.1
+
+* Updated bundled version of TBB (Intel TBB 2019 Update 8).
+
+* RcppParallel can now be configured to use an external copy of TBB, via the
+ `TBB_LIB` and `TBB_INC` environment variables. These should be set to the
+ directories containing the TBB libraries and headers, respectively.
+
+* Added support for the latest versions of Intel oneAPI TBB / oneTBB.
+
+* Updated TBB functionality for the new interface.
+
+* Falling back to building TBB from local source code.
+
+* Backward TBB compatibility based on `__TBB_tbb_stddef_H`.
+
+* Resolved conflicts between system and local TBB headers.
+
+* Fixed URLs, used HTTPS, and minor cleanups.
+
+* Updated package DESCRIPTION and bumped version.
+
+* `setThreadOptions(...)` can again be called multiple times per session.
+ The requested number of threads will be used for invocations to `parallelFor()`
+ and `parallelReduce()` that don't explicitly request a specific number of threads.
+
+* The `parallelFor()` and `parallelReduce()` functions gain the `numThreads`
+ argument, allowing one to limit the number of threads used for a
+ particular computation.
+
+## RcppParallel 5.0.3
+
+* Fixed compilation on macOS M1 machines.
+
+## RcppParallel 5.0.2
+
+* `setThreadOptions(...)` can now only be called once per session, to avoid
+ segfaults when compiling RcppParallel / TBB with gcc 10.1. Subsequent
+ calls to `setThreadOptions(...)` are ignored.
+
+## RcppParallel 5.0.1
+
+* Fixed compilation issue on OpenSUSE Tumbleweed with -flto=auto
+
+* Fixed compilation when CPPFLAGS = -I/usr/local/include and a version
+ of libtbb is installed there
+
+## RcppParallel 5.0.0
+
+* RcppParallel backend can now be customized with RCPP_PARALLEL_BACKEND
+ environment variable (supported values are 'tbb' and 'tinythread')
+
+* Fixed issue when compiling RcppParallel on macOS Catalina
+
+* Fixed issue when compiling RcppParallel with Rtools40
+
+## RcppParallel 4.4.4
+
+* Fixed an issue when compiling RcppParallel with clang-9 on Fedora
+
+## RcppParallel 4.4.3
+
+* Suppress gcc-9 warnings related -Wclass-memaccess
+
+* Added TBB headers for serial TBB operations (#90, @mikejiang)
+
+* Fixed row iterator constructor (#87, @wtianyi)
+
+* Fixed compilation on FreeBSD
+
+## RcppParallel 4.4.2
+
+* Suppress gcc-8 warnings related to -Wclass-memaccess
+
+* Use PKG_CXXFLAGS rather than PKG_CPPFLAGS
+
+* Remove unused dependency on the BH package
+
+## RcppParallel 4.4.1
+
+* Ensure user-specified R configuration passed to TBB
+
+* Work around warnings emitted by gcc 8
+
+## RcppParallel 4.4.0
+
+* Respect user-defined compiler settings (e.g. from ~/.R/Makevars).
+
+* Remove TBB's attempts to suppress compiler diagnostics.
+
+* Allow setting the number of threads to use via RCPP_PARALLEL_NUM_THREADS
+ environment variable.
+
+* Update to TBB 2018 Update 1.
+
+* Add native registration of compiled functions.
+
+## RcppParallel 4.3.20
+
+* Add support for Rtools 3.3 w/ GCC 4.9
+
+## RcppParallel 4.3.14
+
+* Add support for TBB on Solaris
+
+* Fix failure to compile on OS X Snow Leopard R toolchain
+
+* Add const and non-const operator[] for RMatrix class
+
+## RcppParallel 4.3.8
+
+* Add tbbmalloc library
+
+* Correctly pass clang to TBB configure when R is using clang
+
+## RcppParallel 4.3.6
+
+* Support for TBB on Windows
+
+## RcppParallel 4.3.3
+
+* Update to TBB 4.3 (fixes clang compilation error in platform.h)
+
+* Forward CXX to TBB Makefile
+
+## RcppParallel 4.2.5
+
+* Initial release
diff --git a/R/RcppParallel-package.R b/R/RcppParallel-package.R
new file mode 100644
index 000000000..79081f9fb
--- /dev/null
+++ b/R/RcppParallel-package.R
@@ -0,0 +1,24 @@
+
+#' Parallel programming tools for Rcpp
+#'
+#' High level functions for doing parallel programming with Rcpp. For example,
+#' the `parallelFor()` function can be used to convert the work of a
+#' standard serial "for" loop into a parallel one, and the `parallelReduce()`
+#' function can be used for accumulating aggregate or other values.
+#'
+#' The high level interface enables safe and robust parallel programming
+#' without direct manipulation of operating system threads. On Windows, macOS,
+#' and Linux systems the underlying implementation is based on Intel TBB
+#' (Threading Building Blocks). On other platforms, a less-performant fallback
+#' implementation based on the TinyThread library is used.
+#'
+#' For additional documentation, see the package website at:
+#'
+#'
+#'
+#'
+#' @name RcppParallel-package
+#' @docType package
+#' @aliases RcppParallel RcppParallel-package
+#' @keywords package parallel
+NULL
diff --git a/R/aaa.R b/R/aaa.R
new file mode 100644
index 000000000..568a2aac9
--- /dev/null
+++ b/R/aaa.R
@@ -0,0 +1,8 @@
+
+# stubs that get overridden via configure script
+TBB_ENABLED <- TRUE
+TBB_LIB <- ""
+TBB_INC <- ""
+
+TBB_NAME <- "tbb"
+TBB_MALLOC_NAME <- "tbbmalloc"
\ No newline at end of file
diff --git a/R/build.R b/R/build.R
deleted file mode 100644
index 95cbf5e8b..000000000
--- a/R/build.R
+++ /dev/null
@@ -1,99 +0,0 @@
-
-
-# Output the CXX flags. These flags are propagated to sourceCpp via the
-# inlineCxxPlugin (defined below) and to packages via a line in Makevars[.win]
-# like this:
-#
-# PKG_CXXFLAGS += $(shell "${R_HOME}/bin${R_ARCH_BIN}/Rscript.exe" -e "RcppParallel::CxxFlags()")
-#
-CxxFlags <- function() {
- cat(tbbCxxFlags())
-}
-
-
-# Output the LD flags for building against TBB. These flags are propagated
-# to sourceCpp via the inlineCxxPlugin (defined below) and to packages
-# via a line in Makevars[.win] like this:
-#
-# PKG_LIBS += $(shell "${R_HOME}/bin${R_ARCH_BIN}/Rscript.exe" -e "RcppParallel::LdFlags()")
-#
-LdFlags <- function() {
- cat(tbbLdFlags())
-}
-
-# alias for backward compatibility
-RcppParallelLibs <- function() {
- LdFlags()
-}
-
-# Inline plugin used by sourceCpp.
-inlineCxxPlugin <- function() {
- list(
- env = list(
- PKG_CXXFLAGS = tbbCxxFlags(),
- PKG_LIBS = tbbLdFlags()
- ),
- includes = "#include ",
- LinkingTo = "RcppParallel",
- body = function(x) x,
- Depends = "RcppParallel"
- )
-}
-
-tbbCxxFlags <- function() {
-
- flags <- c()
-
- # opt-in to TBB on Windows
- if (Sys.info()['sysname'] == "Windows")
- flags <- paste(flags, "-DRCPP_PARALLEL_USE_TBB=1")
-
- flags
-}
-
-# Return the linker flags requried for TBB on this platform
-tbbLdFlags <- function() {
- # on Windows and Solaris we need to explicitly link against tbb.dll
- if ((Sys.info()['sysname'] %in% c("Windows", "SunOS")) && !isSparc()) {
- tbb <- tbbLibPath()
- paste("-L", asBuildPath(dirname(tbb)), " -ltbb -ltbbmalloc", sep = "")
- } else {
- ""
- }
-}
-
-# Determine the platform-specific path to the TBB library
-tbbLibPath <- function(suffix = "") {
- sysname <- Sys.info()['sysname']
- tbbSupported <- list(
- "Darwin" = paste("libtbb", suffix, ".dylib", sep = ""),
- "Linux" = paste("libtbb", suffix, ".so.2", sep = ""),
- "Windows" = paste("tbb", suffix, ".dll", sep = ""),
- "SunOS" = paste("libtbb", suffix, ".so", sep = "")
- )
- if ((sysname %in% names(tbbSupported)) && !isSparc()) {
- libDir <- "lib/"
- if (sysname == "Windows")
- libDir <- paste(libDir, .Platform$r_arch, "/", sep="")
- system.file(paste(libDir, tbbSupported[[sysname]], sep = ""),
- package = "RcppParallel")
- } else {
- NULL
- }
-}
-
-isSparc <- function() {
- Sys.info()['sysname'] == "SunOS" && Sys.info()[["machine"]] != "i86pc"
-}
-
-# Helper function to ape the behavior of the R build system
-# when providing paths to libraries
-asBuildPath <- function(path) {
- if (.Platform$OS.type == "windows") {
- path <- normalizePath(path)
- if (grepl(' ', path, fixed=TRUE))
- path <- utils::shortPathName(path)
- path <- gsub("\\\\", "/", path)
- }
- return(path)
-}
diff --git a/R/flags.R b/R/flags.R
new file mode 100644
index 000000000..6ae1f8280
--- /dev/null
+++ b/R/flags.R
@@ -0,0 +1,53 @@
+
+#' Compilation flags for RcppParallel
+#'
+#' Output the compiler or linker flags required to build against RcppParallel.
+#'
+#' These functions are typically called from `Makevars` as follows:
+#'
+#' ```
+#' PKG_LIBS += $(shell "${R_HOME}/bin/Rscript" -e "RcppParallel::LdFlags()")
+#' ```
+#'
+#' On Windows, the flags ensure that the package links with the built-in TBB
+#' library. On Linux and macOS, the output is empty, because TBB is loaded
+#' dynamically on load by `RcppParallel`.
+#'
+#' \R packages using RcppParallel should also add the following to their
+#' `NAMESPACE` file:
+#'
+#' ```
+#' importFrom(RcppParallel, RcppParallelLibs)
+#' ```
+#'
+#' This is necessary to ensure that \pkg{RcppParallel} (and so, TBB) is loaded
+#' and available.
+#'
+#' @name flags
+#' @rdname flags
+#' @aliases RcppParallelLibs LdFlags CxxFlags
+#'
+#' @return Returns \code{NULL}, invisibly. These functions are called for
+#' their side effects (writing the associated flags to stdout).
+#'
+NULL
+
+
+#' @name flags
+#' @export
+CxxFlags <- function() {
+ cat(tbbCxxFlags())
+}
+
+#' @name flags
+#' @export
+LdFlags <- function() {
+ cat(tbbLdFlags())
+}
+
+#' @name flags
+#' @export
+RcppParallelLibs <- function() {
+ LdFlags()
+}
+
diff --git a/R/hooks.R b/R/hooks.R
deleted file mode 100644
index be993c8f0..000000000
--- a/R/hooks.R
+++ /dev/null
@@ -1,48 +0,0 @@
-
-dllInfo <- NULL
-mallocDllInfo <- NULL
-
-.onLoad <- function(libname, pkgname) {
-
- # load tbb and tbbmalloc on supported platforms
- tbb <- tbbLibPath()
- if (!is.null(tbb)) {
- if (!file.exists(tbb)) {
- warning(paste("TBB library", tbb, "not found."))
- } else {
- dllInfo <<- dyn.load(tbb, local = FALSE, now = TRUE)
- }
- }
- tbbMalloc <- tbbLibPath("malloc")
- if (!is.null(tbbMalloc)) {
- if (!file.exists(tbbMalloc)) {
- warning(paste("TBB malloc library", tbbMalloc, "not found."))
- } else {
- mallocDllInfo <<- dyn.load(tbbMalloc, local = FALSE, now = TRUE)
- }
- }
-
- # load the package library
- library.dynam("RcppParallel", pkgname, libname)
-
- # set default thread options
- numThreads <- "auto"
- numThreadsEnv <- Sys.getenv("RCPP_PARALLEL_NUM_THREADS", unset = NA)
- if (!is.na(numThreadsEnv))
- setThreadOptions(numThreads = as.integer(numThreadsEnv))
- else
- setThreadOptions(numThreads = "auto")
-}
-
-.onUnload <- function(libpath) {
-
- # unload the package library
- library.dynam.unload("RcppParallel", libpath)
-
- # unload tbb if we loaded it
- if (!is.null(dllInfo))
- dyn.unload(dllInfo[["path"]])
- # unload tbbmalloc if we loaded it
- if (!is.null(mallocDllInfo))
- dyn.unload(mallocDllInfo[["path"]])
-}
diff --git a/R/options.R b/R/options.R
index eac85482c..9b54a37c5 100644
--- a/R/options.R
+++ b/R/options.R
@@ -1,7 +1,48 @@
-
-setThreadOptions <- function(numThreads = "auto", stackSize = "auto") {
-
+#' Thread options for RcppParallel
+#'
+#' Set thread options (number of threads to use for task scheduling and stack
+#' size per-thread) for RcppParallel.
+#'
+#' RcppParallel is automatically initialized with the default number of threads
+#' and thread stack size when it loads. You can call `setThreadOptions()` at
+#' any time to change the defaults.
+#'
+#' The `parallelFor()` and `parallelReduce()` also accept `numThreads` as
+#' an argument, if you'd like to control the number of threads specifically
+#' to be made available for a particular parallel function call. Note that
+#' this value is advisory, and TBB may choose a smaller number of threads
+#' if the number of requested threads cannot be honored on the system.
+#'
+#' @aliases setThreadOptions defaultNumThreads
+#'
+#' @param numThreads
+#' Number of threads to use for task scheduling. Call `defaultNumThreads()`
+#' to determine the the default value used for "auto".
+#'
+#' @param stackSize
+#' Stack size (in bytes) to use for worker threads. The
+#' default used for "auto" is 2MB on 32-bit systems and 4MB on 64-bit systems
+#' (note that this parameter has no effect on Windows).
+#'
+#' @return
+#' `defaultNumThreads()` returns the default number of threads used by
+#' RcppParallel, if another value isn't specified either via
+#' `setThreadOptions()` or explicitly in calls to `parallelFor()` and
+#' `parallelReduce()`.
+#'
+#' @examples
+#'
+#' \dontrun{
+#' library(RcppParallel)
+#' setThreadOptions(numThreads = 4)
+#' defaultNumThreads()
+#' }
+#'
+#' @export setThreadOptions
+setThreadOptions <- function(numThreads = "auto",
+ stackSize = "auto")
+{
# validate and resolve numThreads
if (identical(numThreads, "auto"))
numThreads <- -1L
@@ -18,19 +59,27 @@ setThreadOptions <- function(numThreads = "auto", stackSize = "auto") {
else
stackSize <- as.integer(stackSize)
- # Call setThreadOptions if using tbb
- if (!is.null(dllInfo)) {
- invisible(.Call("setThreadOptions", numThreads, stackSize,
- PACKAGE = "RcppParallel"))
- }
-
+ # set RCPP_PARALLEL_NUM_THREADS
if (numThreads == -1L)
Sys.unsetenv("RCPP_PARALLEL_NUM_THREADS")
else
Sys.setenv(RCPP_PARALLEL_NUM_THREADS = numThreads)
+
+ # set RCPP_PARALLEL_STACK_SIZE
+ if (stackSize == 0L)
+ Sys.unsetenv("RCPP_PARALLEL_STACK_SIZE")
+ else
+ Sys.setenv(RCPP_PARALLEL_STACK_SIZE = stackSize)
}
+#' @rdname setThreadOptions
+#' @export
defaultNumThreads <- function() {
.Call("defaultNumThreads", PACKAGE = "RcppParallel")
}
+isUsingTbb <- function() {
+ backend <- Sys.getenv("RCPP_PARALLEL_BACKEND", "tbb")
+ identical(backend, "tbb")
+}
+
diff --git a/R/platform.R b/R/platform.R
new file mode 100644
index 000000000..fe7569ff1
--- /dev/null
+++ b/R/platform.R
@@ -0,0 +1,26 @@
+
+is_windows <- function() {
+ .Platform$OS.type == "windows"
+}
+
+is_mac <- function() {
+ Sys.info()[["sysname"]] == "Darwin"
+}
+
+is_unix <- function() {
+ .Platform$OS.type == "unix"
+}
+
+is_solaris <- function() {
+ Sys.info()[["sysname"]] == "SunOS"
+}
+
+is_sparc <- function() {
+ info <- Sys.info()
+ all(
+ info[["sysname"]] == "SunOS",
+ info[["machine"]] != "i86pc"
+ )
+}
+
+
diff --git a/R/plugin.R b/R/plugin.R
new file mode 100644
index 000000000..78dc2aab2
--- /dev/null
+++ b/R/plugin.R
@@ -0,0 +1,15 @@
+
+# Inline plugin used by sourceCpp.
+inlineCxxPlugin <- function() {
+
+ list(
+ env = list(
+ PKG_CXXFLAGS = tbbCxxFlags(),
+ PKG_LIBS = tbbLdFlags()
+ ),
+ includes = "#include ",
+ LinkingTo = "RcppParallel",
+ body = identity,
+ Depends = "RcppParallel"
+ )
+}
diff --git a/R/skeleton.R b/R/skeleton.R
index 88cbcdbcb..4b12b711d 100644
--- a/R/skeleton.R
+++ b/R/skeleton.R
@@ -1,3 +1,53 @@
+
+#' Create a skeleton for a new package depending on RcppParallel
+#'
+#' \code{RcppParallel.package.skeleton} automates the creation of a new source
+#' package that intends to use features of RcppParallel.
+#'
+#' It is based on the \link[utils]{package.skeleton} function which it executes
+#' first.
+#'
+#' In addition to \link[Rcpp]{Rcpp.package.skeleton} :
+#'
+#' The \samp{DESCRIPTION} file gains an Imports line requesting that the
+#' package depends on RcppParallel and a LinkingTo line so that the package
+#' finds RcppParallel header files.
+#'
+#' The \samp{NAMESPACE} gains a \code{useDynLib} directive as well as an
+#' \code{importFrom(RcppParallel, evalCpp} to ensure instantiation of
+#' RcppParallel.
+#'
+#' The \samp{src} directory is created if it does not exists and a
+#' \samp{Makevars} file is added setting the environment variables
+#' \samp{PKG_LIBS} to accomodate the necessary flags to link with the
+#' RcppParallel library.
+#'
+#' If the \code{example_code} argument is set to \code{TRUE}, example files
+#' \samp{vector-sum.cpp} is created in the \samp{src} directory.
+#' \code{Rcpp::compileAttributes()} is then called to generate
+#' \code{src/RcppExports.cpp} and \code{R/RcppExports.R}. These files are given
+#' as an example and should eventually by removed from the generated package.
+#'
+#' @param name The name of your R package.
+#' @param example_code If \code{TRUE}, example C++ code using RcppParallel is
+#' added to the package.
+#' @param ... Optional arguments passed to \link[Rcpp]{Rcpp.package.skeleton}.
+#' @return Nothing, used for its side effects
+#' @seealso \link[utils]{package.skeleton}
+#' @references Read the \emph{Writing R Extensions} manual for more details.
+#'
+#' Once you have created a \emph{source} package you need to install it: see
+#' the \emph{R Installation and Administration} manual, \code{\link{INSTALL}}
+#' and \code{\link{install.packages}}.
+#' @keywords programming
+#' @examples
+#'
+#' \dontrun{
+#' # simple package
+#' RcppParallel.package.skeleton("foobar")
+#' }
+#'
+#' @export RcppParallel.package.skeleton
RcppParallel.package.skeleton <- function(name = "anRpackage",
example_code = TRUE,
...)
@@ -21,9 +71,12 @@ RcppParallel.package.skeleton <- function(name = "anRpackage",
on.exit(setwd(owd), add = TRUE)
# remove dummy stuff
- unlink("data/dummy.Rda")
+ unlink("data", recursive=TRUE)
unlink("man/dummy.Rd")
unlink("Read-and-delete-me")
+ lns <- readLines("NAMESPACE")
+ writeLines(lns[!grepl("dummy", lns)], "NAMESPACE")
+ unlink("src/init.c")
message("\nAdding RcppParallel settings")
@@ -56,7 +109,7 @@ RcppParallel.package.skeleton <- function(name = "anRpackage",
message(" >> added src/Makevars")
cat(
c(
- 'CXX_STD = CXX11',
+ '# We also need importFrom(RcppParallel,RcppParallelLibs) in NAMESPACE',
'PKG_LIBS += $(shell ${R_HOME}/bin/Rscript -e "RcppParallel::RcppParallelLibs()")'
),
file = "src/Makevars",
@@ -67,7 +120,6 @@ RcppParallel.package.skeleton <- function(name = "anRpackage",
message(" >> added src/Makevars.win")
cat(
c(
- 'CXX_STD = CXX11',
'PKG_CXXFLAGS += -DRCPP_PARALLEL_USE_TBB=1',
'PKG_LIBS += $(shell "${R_HOME}/bin${R_ARCH_BIN}/Rscript.exe" -e "RcppParallel::RcppParallelLibs()")'
),
diff --git a/R/tbb-autodetected.R.in b/R/tbb-autodetected.R.in
new file mode 100644
index 000000000..7cc750e09
--- /dev/null
+++ b/R/tbb-autodetected.R.in
@@ -0,0 +1,7 @@
+
+TBB_ENABLED <- @TBB_ENABLED@
+TBB_LIB <- "@TBB_LIB@"
+TBB_INC <- "@TBB_INC@"
+
+TBB_NAME <- "@TBB_NAME@"
+TBB_MALLOC_NAME <- "@TBB_MALLOC_NAME@"
\ No newline at end of file
diff --git a/R/tbb.R b/R/tbb.R
new file mode 100644
index 000000000..3d8fbb328
--- /dev/null
+++ b/R/tbb.R
@@ -0,0 +1,135 @@
+
+#' Get the Path to a TBB Library
+#'
+#' Retrieve the path to a TBB library. This can be useful for \R packages
+#' using RcppParallel that wish to use, or re-use, the version of TBB that
+#' RcppParallel has been configured to use.
+#'
+#' @param name
+#' The name of the TBB library to be resolved. Normally, this is one of
+#' `tbb`, `tbbmalloc`, or `tbbmalloc_proxy`. When `NULL`, the library
+#' path containing the TBB libraries is returned instead.
+#'
+#' @export
+tbbLibraryPath <- function(name = NULL) {
+
+ # library paths for different OSes
+ sysname <- Sys.info()[["sysname"]]
+
+ # find root for TBB install
+ tbbRoot <- Sys.getenv("TBB_LIB", unset = tbbRoot())
+ if (is.null(name))
+ return(tbbRoot)
+
+ # form library names
+ tbbLibNames <- list(
+ "Darwin" = paste0("lib", name, ".dylib"),
+ "Windows" = paste0("lib", name, c("12", ""), ".a"),
+ "SunOS" = paste0("lib", name, ".so"),
+ "Linux" = paste0("lib", name, c(".so.2", ".so"))
+ )
+
+ # skip systems that we know not to be compatible
+ isCompatible <- !is_sparc() && !is.null(tbbLibNames[[sysname]])
+ if (!isCompatible)
+ return(NULL)
+
+ # find the request library (if any)
+ libNames <- tbbLibNames[[sysname]]
+ for (libName in libNames) {
+
+ tbbName <- file.path(tbbRoot, libName)
+ if (file.exists(tbbName))
+ return(tbbName)
+
+ arch <- if (nzchar(.Platform$r_arch)) .Platform$r_arch
+ suffix <- paste(c("lib", arch, libName), collapse = "/")
+ tbbName <- system.file(suffix, package = "RcppParallel")
+ if (file.exists(tbbName))
+ return(tbbName)
+
+ }
+
+}
+
+tbbCxxFlags <- function() {
+
+ if (!TBB_ENABLED)
+ return("-DRCPP_PARALLEL_USE_TBB=0")
+
+ flags <- c("-DRCPP_PARALLEL_USE_TBB=1")
+
+ # if TBB_INC is set, apply those library paths
+ tbbInc <- Sys.getenv("TBB_INC", unset = TBB_INC)
+ if (!file.exists(tbbInc)) {
+ tbbInc <- system.file("include", package = "RcppParallel")
+ }
+
+ # add include path
+ if (nzchar(tbbInc) && file.exists(tbbInc)) {
+
+ # prefer new interface if version.h exists -- we keep this
+ # for compatibility with packages like StanHeaders, rstan
+ versionPath <- file.path(tbbInc, "tbb/version.h")
+ if (file.exists(versionPath))
+ flags <- c(flags, "-DTBB_INTERFACE_NEW")
+
+ # now add the include path
+ flags <- c(flags, paste0("-I", asBuildPath(tbbInc)))
+
+ }
+
+ # return flags as string
+ paste(flags, collapse = " ")
+
+}
+
+# Return the linker flags required for TBB on this platform
+tbbLdFlags <- function() {
+
+ # on Windows, we statically link to oneTBB
+ if (is_windows()) {
+
+ libPath <- system.file("libs", package = "RcppParallel")
+ if (nzchar(.Platform$r_arch))
+ libPath <- file.path(libPath, .Platform$r_arch)
+
+ ldFlags <- sprintf("-L%s -lRcppParallel", asBuildPath(libPath))
+ return(ldFlags)
+
+ }
+
+ # shortcut if TBB_LIB defined
+ tbbLib <- Sys.getenv("TBB_LINK_LIB", Sys.getenv("TBB_LIB", unset = TBB_LIB))
+ if (nzchar(tbbLib)) {
+ if (R.version$os == "emscripten") {
+ fmt <- "-L%1$s -l%2$s"
+ return(sprintf(fmt, asBuildPath(tbbLib), TBB_NAME))
+ }
+ fmt <- "-L%1$s -Wl,-rpath,%1$s -l%2$s -l%3$s"
+ return(sprintf(fmt, asBuildPath(tbbLib), TBB_NAME, TBB_MALLOC_NAME))
+ }
+
+ # explicitly link on macOS
+ # https://github.com/RcppCore/RcppParallel/issues/206
+ if (is_mac()) {
+ fmt <- "-L%s -l%s -l%s"
+ return(sprintf(fmt, asBuildPath(tbbLibraryPath()), TBB_NAME, TBB_MALLOC_NAME))
+ }
+
+ # nothing required on other platforms
+ ""
+
+}
+
+tbbRoot <- function() {
+
+ if (nzchar(TBB_LIB))
+ return(TBB_LIB)
+
+ rArch <- .Platform$r_arch
+ parts <- c("lib", if (nzchar(rArch)) rArch)
+ libDir <- paste(parts, collapse = "/")
+ system.file(libDir, package = "RcppParallel")
+
+}
diff --git a/R/utils.R b/R/utils.R
new file mode 100644
index 000000000..53ced6389
--- /dev/null
+++ b/R/utils.R
@@ -0,0 +1,24 @@
+
+# generate paths consumable by the compilers and linkers
+# in particular, on Windows and Solaris, this means the path _cannot_ be quoted !!
+asBuildPath <- function(path) {
+
+ # normalize paths using forward slashes
+ path <- normalizePath(path, winslash = "/", mustWork = FALSE)
+
+ # prefer short path names if the path has spaces
+ if (is_windows() && grepl(" ", path, fixed = TRUE))
+ path <- utils::shortPathName(path)
+
+ # if we still have spaces, and we're not Windows or Solaris, try quoting
+ if (grepl(" ", path, fixed = TRUE) && !is_solaris())
+ path <- shQuote(path)
+
+ # ensure we use forward slashes, even on Windows
+ path <- chartr("\\", "/", path)
+
+ # return path
+ path
+
+}
+
diff --git a/R/zzz.R b/R/zzz.R
new file mode 100644
index 000000000..54374e097
--- /dev/null
+++ b/R/zzz.R
@@ -0,0 +1,71 @@
+
+# !diagnostics suppress=.dllInfo,.tbbDllInfo,.tbbMallocDllInfo,.tbbMallocProxyDllInfo
+
+# NOTE: we intentionally do _not_ load tbbmalloc_proxy by default, as its
+# intended use is to replace the default allocator, something that may be
+# dangerous to do by default. in addition, TBB's documentation recommends
+# only loading explicitly via e.g. LD_PRELOAD
+.dllInfo <- NULL
+.tbbDllInfo <- NULL
+.tbbMallocDllInfo <- NULL
+.tbbMallocProxyDllInfo <- NULL
+
+loadTbbLibrary <- function(name) {
+ # TBB is statically linked on Windows
+ if (is_windows()) {
+ return(NULL)
+ }
+ path <- tbbLibraryPath(name)
+ if (is.null(path))
+ return(NULL)
+
+ if (!file.exists(path)) {
+ warning("TBB library ", shQuote(name), " not found.")
+ return(NULL)
+ }
+
+ dyn.load(path, local = FALSE, now = TRUE)
+
+}
+
+.onLoad <- function(libname, pkgname) {
+
+ # on Windows, load RcppParallel first
+ if (.Platform$OS.type == "windows") {
+ .dllInfo <<- library.dynam("RcppParallel", pkgname, libname)
+ }
+
+ # load tbb, tbbmalloc
+ .tbbDllInfo <<- loadTbbLibrary("tbb")
+ .tbbMallocDllInfo <<- loadTbbLibrary("tbbmalloc")
+
+ # load tbbmalloc_proxy, but only if requested
+ useTbbMallocProxy <- Sys.getenv("RCPP_PARALLEL_USE_TBBMALLOC_PROXY", unset = "FALSE")
+ if (useTbbMallocProxy %in% c("TRUE", "True", "true", "1"))
+ .tbbMallocProxyDllInfo <<- loadTbbLibrary("tbbmalloc_proxy")
+
+ # load RcppParallel library if available
+ if (.Platform$OS.type != "windows") {
+ .dllInfo <<- library.dynam("RcppParallel", pkgname, libname, local = FALSE)
+ }
+
+}
+
+.onUnload <- function(libpath) {
+
+ # unload the package library
+ if (!is.null(.dllInfo))
+ library.dynam.unload("RcppParallel", libpath)
+
+ # NOTE: we do not explicitly unload tbbmalloc_proxy as switching
+ # the allocator at runtime can cause issues
+
+ # unload tbbmalloc if we loaded it
+ if (!is.null(.tbbMallocDllInfo))
+ dyn.unload(.tbbMallocDllInfo[["path"]])
+
+ # unload tbb if we loaded it
+ if (!is.null(.tbbDllInfo))
+ dyn.unload(.tbbDllInfo[["path"]])
+
+}
diff --git a/README.md b/README.md
index f0c68b576..620e6d21b 100644
--- a/README.md
+++ b/README.md
@@ -1,19 +1,63 @@
-## RcppParallel Package
-[](https://travis-ci.org/RcppCore/RcppParallel)
-[](https://ci.appveyor.com/project/RcppCore/RcppParallel)
-[](https://cran.r-project.org/package=RcppParallel)
+## RcppParallel
-High level functions for doing parallel programming with Rcpp. For example, the `parallelFor` function can be used to convert the work of a standard serial "for" loop into a parallel one and the `parallelReduce` function can be used for accumulating aggregate or other values.
+
+[](https://cran.r-project.org/package=RcppParallel)
+[](https://github.com/RcppCore/RcppParallel/actions/workflows/R-CMD-check.yaml)
+
-The high level interface enables safe and robust parallel programming without direct manipulation of operating system threads. On Windows, OS X, and Linux systems the underlying implementation is based on [Intel TBB](https://www.threadingbuildingblocks.org/) (Threading Building Blocks). On other platforms a less-performant fallback implementation based on the [TinyThread](http://tinythreadpp.bitsnbites.eu/) library is used.
+High level functions for parallel programming with Rcpp. The `parallelFor()` function can be used to convert the work of a standard serial "for" loop into a parallel one, and the `parallelReduce()` function can be used for accumulating aggregate or other values.
+
+The high level interface enables safe and robust parallel programming without direct manipulation of operating system threads. On Windows, macOS, and Linux systems, the underlying implementation is based on [Intel TBB](https://github.com/oneapi-src/oneTBB) (Threading Building Blocks). On other platforms, a less-performant fallback implementation based on the [TinyThread](https://tinythreadpp.bitsnbites.eu/) library is used.
For additional documentation on using RcppParallel see the package website at http://rcppcore.github.io/RcppParallel/.
+
+### Intel TBB
+
+`RcppParallel` supports the new interface of Intel TBB, and can be configured to use an external copy of TBB (e.g., with [`oneTBB`](https://github.com/oneapi-src/oneTBB) or the system TBB library), using the `TBB_LIB` and `TBB_INC` environment variables.
+
+To build the development version of `RcppParallel` with [`oneTBB`](https://github.com/oneapi-src/oneTBB):
+
+- Install [`oneTBB`](https://github.com/oneapi-src/oneTBB).
+
+For example, installing [`oneTBB`](https://github.com/oneapi-src/oneTBB) on Linux 64-bit (`x86_64`) to `$HOME` directory (change if needed!):
+
+```bash
+TBB_RELEASE="https://api.github.com/repos/oneapi-src/oneTBB/releases/latest"
+TBB_TAG=$(curl --silent $TBB_RELEASE | grep -Po '"tag_name": "\K.*?(?=")')
+TBB_VERSION=${TBB_TAG#?}
+
+wget https://github.com/oneapi-src/oneTBB/releases/download/v$TBB_VERSION/oneapi-tbb-$TBB_VERSION-lin.tgz
+tar zxvf oneapi-tbb-$TBB_VERSION-lin.tgz -C $HOME
+
+export TBB="$HOME/oneapi-tbb-$TBB_VERSION"
+```
+Note that you may replace `TBB_VERSION=${TBB_TAG#?}` with a custom version number if needed ( check available releases [here](https://github.com/oneapi-src/oneTBB/releases) ).
+
+- Set the TBB environment variables (specifically: `TBB` for the installation prefix, `TBB_INC` for the directory that includes the header files, and `TBB_LIB` for the libraries directory).
+
+For example, installing [`oneTBB`](https://github.com/oneapi-src/oneTBB) on Linux 64-bit (`x86_64`) to `$HOME` directory (change if needed!):
+
+```bash
+source $TBB/env/vars.sh intel64
+
+export TBB_INC="$TBB/include"
+export TBB_LIB="$TBB/lib/intel64/gcc4.8"
+```
+
+- Build the development version of `RcppParallel`:
+
+```r
+install.packages("remotes")
+remotes::install_github("RcppCore/RcppParallel")
+```
+
+
### License
-The RcppParallel package is made available under the [GPLv2](http://www.gnu.org/licenses/old-licenses/gpl-2.0.html).
+The RcppParallel package is made available under the [GPLv2](http://www.gnu.org/licenses/old-licenses/gpl-2.0.html) license.
-The TinyThread library is licensed under the [zlib/libpng](http://www.opensource.org/licenses/zlib-license.php) license as described [here](https://gitorious.org/tinythread/tinythreadpp/source/master:README.txt).
+The [TinyThread library](https://tinythreadpp.bitsnbites.eu/) is licensed under the [zlib/libpng](https://opensource.org/licenses/zlib-license.php) license.
-The Intel TBB Library is licensed under the Apache 2.0 (as described at https://www.threadingbuildingblocks.org/faq/10).
+The Intel TBB Library is licensed under the Apache 2.0 license, as described at https://github.com/oneapi-src/oneTBB/blob/master/LICENSE.txt.
diff --git a/RcppParallel.Rproj b/RcppParallel.Rproj
index aa82b53fb..2970ea06c 100644
--- a/RcppParallel.Rproj
+++ b/RcppParallel.Rproj
@@ -1,4 +1,5 @@
Version: 1.0
+ProjectId: 8e3d73b0-404c-42f5-b2ef-46f759f65dd4
RestoreWorkspace: No
SaveWorkspace: No
@@ -12,6 +13,10 @@ Encoding: UTF-8
RnwWeave: Sweave
LaTeX: pdfLaTeX
+AutoAppendNewline: Yes
+
BuildType: Package
-PackageInstallArgs: --with-keep.source --clean
+PackageCleanBeforeInstall: No
+PackageInstallArgs: --with-keep.source
PackageCheckArgs: --as-cran
+PackageRoxygenize: rd,collate,namespace
diff --git a/appveyor.yml b/appveyor.yml
deleted file mode 100644
index c6c14384e..000000000
--- a/appveyor.yml
+++ /dev/null
@@ -1,45 +0,0 @@
-# DO NOT CHANGE the "init" and "install" sections below
-
-# Download script file from GitHub
-init:
- ps: |
- $ErrorActionPreference = "Stop"
- Invoke-WebRequest http://raw.github.com/krlmlr/r-appveyor/master/scripts/appveyor-tool.ps1 -OutFile "..\appveyor-tool.ps1"
- Import-Module '..\appveyor-tool.ps1'
-
-install:
- ps: Bootstrap
-
-cache:
- - C:\RLibrary
-
-# Adapt as necessary starting from here
-
-build_script:
- - travis-tool.sh install_deps
-
-test_script:
- - travis-tool.sh run_tests
-
-on_failure:
- - 7z a failure.zip *.Rcheck\*
- - appveyor PushArtifact failure.zip
-
-artifacts:
- - path: '*.Rcheck\**\*.log'
- name: Logs
-
- - path: '*.Rcheck\**\*.out'
- name: Logs
-
- - path: '*.Rcheck\**\*.fail'
- name: Logs
-
- - path: '*.Rcheck\**\*.Rout'
- name: Logs
-
- - path: '\*_*.tar.gz'
- name: Bits
-
- - path: '\*_*.zip'
- name: Bits
diff --git a/cleanup b/cleanup
index 1a49d2249..ddbda5cf6 100755
--- a/cleanup
+++ b/cleanup
@@ -1,3 +1,3 @@
#!/usr/bin/env sh
: "${R_HOME=`R RHOME`}"
-"${R_HOME}/bin/Rscript" tools/config.R cleanup
+"${R_HOME}/bin/Rscript" tools/config.R cleanup "$@"
diff --git a/cleanup.win b/cleanup.win
index 7128030cc..918a2f0c8 100755
--- a/cleanup.win
+++ b/cleanup.win
@@ -1,2 +1,2 @@
#!/usr/bin/env sh
-"${R_HOME}/bin${R_ARCH_BIN}/Rscript.exe" tools/config.R cleanup
+"${R_HOME}/bin${R_ARCH_BIN}/Rscript.exe" tools/config.R cleanup "$@"
diff --git a/configure b/configure
index 0cad1066c..b08715386 100755
--- a/configure
+++ b/configure
@@ -1,3 +1,3 @@
#!/usr/bin/env sh
: "${R_HOME=`R RHOME`}"
-"${R_HOME}/bin/Rscript" tools/config.R configure
+"${R_HOME}/bin/Rscript" tools/config.R configure "$@"
diff --git a/configure.win b/configure.win
index c83ab78b5..a47d1205c 100755
--- a/configure.win
+++ b/configure.win
@@ -1,2 +1,2 @@
#!/usr/bin/env sh
-"${R_HOME}/bin${R_ARCH_BIN}/Rscript.exe" tools/config.R configure
+"${R_HOME}/bin${R_ARCH_BIN}/Rscript.exe" tools/config.R configure "$@"
diff --git a/inst/.gitignore b/inst/.gitignore
index c3af85790..93f665e4d 100644
--- a/inst/.gitignore
+++ b/inst/.gitignore
@@ -1 +1,2 @@
lib/
+libs/
diff --git a/inst/NEWS b/inst/NEWS
deleted file mode 100644
index 0d375c434..000000000
--- a/inst/NEWS
+++ /dev/null
@@ -1,68 +0,0 @@
-RcppParallel 4.4.4
-------------------------------------------------------------------------
-* Fixed an issue when compiling RcppParallel with clang-9 on Fedora
-
-RcppParallel 4.4.3
-------------------------------------------------------------------------
-
-* Suppress gcc-9 warnings related -Wclass-memaccess
-* Added TBB headers for serial TBB operations (#90, @mikejiang)
-* Fixed row iterator constructor (#87, @wtianyi)
-* Fixed compilation on FreeBSD
-
-RcppParallel 4.4.2
-------------------------------------------------------------------------
-
-* Suppress gcc-8 warnings related to -Wclass-memaccess
-* Use PKG_CXXFLAGS rather than PKG_CPPFLAGS
-* Remove unused dependency on the BH package
-
-RcppParallel 4.4.1
-------------------------------------------------------------------------
-
-* Ensure user-specified R configuration passed to TBB
-* Work around warnings emitted by gcc 8
-
-RcppParallel 4.4.0
-------------------------------------------------------------------------
-
-* Respect user-defined compiler settings (e.g. from ~/.R/Makevars).
-* Remove TBB's attempts to suppress compiler diagnostics.
-* Allow setting the number of threads to use via RCPP_PARALLEL_NUM_THREADS
- environment variable.
-* Update to TBB 2018 Update 1.
-* Add native registration of compiled functions.
-
-RcppParallel 4.3.20
-------------------------------------------------------------------------
-
-* Add support for Rtools 3.3 w/ GCC 4.9
-
-RcppParallel 4.3.14
-------------------------------------------------------------------------
-
-* Add support for TBB on Solaris
-* Fix failure to compile on OS X Snow Leopard R toolchain
-* Add const and non-const operator[] for RMatrix class
-
-RcppParallel 4.3.8
-------------------------------------------------------------------------
-
-* Add tbbmalloc library
-* Correctly pass clang to TBB configure when R is using clang
-
-RcppParallel 4.3.6
-------------------------------------------------------------------------
-
-* Support for TBB on Windows
-
-RcppParallel 4.3.3
-------------------------------------------------------------------------
-
-* Update to TBB 4.3 (fixes clang compilation error in platform.h)
-* Forward CXX to TBB Makefile
-
-RcppParallel 4.2.5
-------------------------------------------------------------------------
-
-* Initial release
diff --git a/inst/include/.gitignore b/inst/include/.gitignore
new file mode 100644
index 000000000..4c130be3e
--- /dev/null
+++ b/inst/include/.gitignore
@@ -0,0 +1,7 @@
+
+# These TBB libraries are copied in at configure time.
+/index.html
+/oneapi
+/serial
+/tbb
+
diff --git a/inst/include/RcppParallel.h b/inst/include/RcppParallel.h
index 9b7da04dd..87d6eb5ca 100644
--- a/inst/include/RcppParallel.h
+++ b/inst/include/RcppParallel.h
@@ -6,50 +6,76 @@
#include "RcppParallel/TinyThread.h"
// Use TBB only where it's known to compile and work correctly
-// (NOTE: Windows TBB is temporarily opt-in for packages for
+// (NOTE: Windows TBB is temporarily opt-in for packages for
// compatibility with CRAN packages not previously configured
// to link to TBB in Makevars.win)
#ifndef RCPP_PARALLEL_USE_TBB
-#if defined(__APPLE__) || defined(__gnu_linux__) || ((defined(__sun) && defined(__SVR4) && !defined(__sparc)))
-#define RCPP_PARALLEL_USE_TBB 1
-#include "RcppParallel/TBB.h"
-#else
-#define RCPP_PARALLEL_USE_TBB 0
-#endif
+# if defined(__APPLE__) || defined(__gnu_linux__) || (defined(__sun) && defined(__SVR4) && !defined(__sparc))
+# define RCPP_PARALLEL_USE_TBB 1
+# else
+# define RCPP_PARALLEL_USE_TBB 0
+# endif
#endif
#if RCPP_PARALLEL_USE_TBB
- #include "RcppParallel/TBB.h"
+# include "RcppParallel/TBB.h"
#endif
+#include "RcppParallel/Backend.h"
#include "RcppParallel/RVector.h"
#include "RcppParallel/RMatrix.h"
namespace RcppParallel {
-inline void parallelFor(std::size_t begin, std::size_t end,
- Worker& worker, std::size_t grainSize = 1) {
-
+inline void parallelFor(std::size_t begin,
+ std::size_t end,
+ Worker& worker,
+ std::size_t grainSize = 1,
+ int numThreads = -1)
+{
+ grainSize = resolveValue("RCPP_PARALLEL_GRAIN_SIZE", grainSize, std::size_t(1));
+ numThreads = resolveValue("RCPP_PARALLEL_NUM_THREADS", numThreads, -1);
+
#if RCPP_PARALLEL_USE_TBB
- tbbParallelFor(begin, end, worker, grainSize);
+ if (internal::backend() == internal::BACKEND_TBB)
+ tbbParallelFor(begin, end, worker, grainSize, numThreads);
+ else
+ ttParallelFor(begin, end, worker, grainSize);
#else
ttParallelFor(begin, end, worker, grainSize);
#endif
-
}
template
-inline void parallelReduce(std::size_t begin, std::size_t end,
- Reducer& reducer, std::size_t grainSize = 1) {
-
+inline void parallelReduce(std::size_t begin,
+ std::size_t end,
+ Reducer& reducer,
+ std::size_t grainSize = 1,
+ int numThreads = -1)
+{
+ grainSize = resolveValue("RCPP_PARALLEL_GRAIN_SIZE", grainSize, std::size_t(1));
+ numThreads = resolveValue("RCPP_PARALLEL_NUM_THREADS", numThreads, -1);
+
#if RCPP_PARALLEL_USE_TBB
- tbbParallelReduce(begin, end, reducer, grainSize);
+ if (internal::backend() == internal::BACKEND_TBB)
+ tbbParallelReduce(begin, end, reducer, grainSize, numThreads);
+ else
+ ttParallelReduce(begin, end, reducer, grainSize);
#else
ttParallelReduce(begin, end, reducer, grainSize);
#endif
-
}
-} // namespace RcppParallel
+} // end namespace RcppParallel
+
+// TRUE and FALSE macros that may come with system headers on some systems
+// But conflict with R.h (R_ext/Boolean.h)
+// TRUE and FALSE macros should be undef in RcppParallel.h
+#ifdef TRUE
+ #undef TRUE
+#endif
+#ifdef FALSE
+ #undef FALSE
+#endif
#endif // __RCPP_PARALLEL__
diff --git a/inst/include/RcppParallel/Backend.h b/inst/include/RcppParallel/Backend.h
new file mode 100644
index 000000000..13971b9e0
--- /dev/null
+++ b/inst/include/RcppParallel/Backend.h
@@ -0,0 +1,84 @@
+
+#ifndef __RCPP_PARALLEL_BACKEND__
+#define __RCPP_PARALLEL_BACKEND__
+
+#include
+#include
+
+extern "C" {
+void REprintf(const char*, ...);
+}
+
+namespace RcppParallel {
+namespace internal {
+
+enum backend_type {
+ BACKEND_TBB,
+ BACKEND_TINYTHREAD
+};
+
+#if RCPP_PARALLEL_USE_TBB
+
+inline backend_type defaultBackend()
+{
+ return BACKEND_TBB;
+}
+
+#else
+
+inline backend_type defaultBackend()
+{
+ return BACKEND_TINYTHREAD;
+}
+
+#endif
+
+inline const char* backendToString(backend_type backend)
+{
+ switch (backend)
+ {
+ case BACKEND_TBB:
+ return "tbb";
+ case BACKEND_TINYTHREAD:
+ return "tinythread";
+ }
+
+ // shouldn't be reached but need to silence compiler warnings
+ return "tbb";
+}
+
+inline backend_type backend()
+{
+ const char* requestedBackend = std::getenv("RCPP_PARALLEL_BACKEND");
+ if (requestedBackend == NULL)
+ {
+ return defaultBackend();
+ }
+ else if (std::strcmp(requestedBackend, "tbb") == 0)
+ {
+#if RCPP_PARALLEL_USE_TBB
+ return BACKEND_TBB;
+#else
+ const char* msg =
+ "tbb backend is not available; using tinythread instead";
+
+ REprintf("%s\n", msg);
+ return BACKEND_TINYTHREAD;
+#endif
+ }
+ else if (strcmp(requestedBackend, "tinythread") == 0)
+ {
+ return BACKEND_TINYTHREAD;
+ }
+ else
+ {
+ const char* fmt = "unknown parallel backend '%s'; using '%s' instead\n";
+ REprintf(fmt, requestedBackend, backendToString(defaultBackend()));
+ return defaultBackend();
+ }
+}
+
+} // namespace internal
+} // namespace RcppParallel
+
+#endif /* __RCPP_PARALLEL_BACKEND__ */
diff --git a/inst/include/RcppParallel/Common.h b/inst/include/RcppParallel/Common.h
index b14d3f0cb..ae2b1327d 100644
--- a/inst/include/RcppParallel/Common.h
+++ b/inst/include/RcppParallel/Common.h
@@ -1,34 +1,86 @@
#ifndef __RCPP_PARALLEL_COMMON__
#define __RCPP_PARALLEL_COMMON__
+#include
#include
+#include
+
+#include
+#include
+#include
+#include
namespace RcppParallel {
+template
+inline int resolveValue(const char* envvar,
+ T requestedValue,
+ U defaultValue)
+{
+ // if the requested value is non-zero and not the default, we can use it
+ bool useRequestedValue =
+ requestedValue != static_cast(defaultValue) &&
+ requestedValue > 0;
+
+ if (useRequestedValue)
+ return requestedValue;
+
+ // otherwise, try reading the default from associated envvar
+ // if the environment variable is unset, use the default
+ const char* var = getenv(envvar);
+ if (var == NULL)
+ return defaultValue;
+
+ // try to convert the string to a number
+ // if an error occurs during conversion, just use default
+ errno = 0;
+ char* end;
+ long value = strtol(var, &end, 10);
+
+ // check for conversion failure
+ if (end == var || *end != '\0' || errno == ERANGE)
+ return defaultValue;
+
+ // okay, return the parsed environment variable value
+ return value;
+}
+
+// Tag type used for disambiguating splitting constructors
+struct Split {};
+
// Work executed within a background thread. We implement dynamic
// dispatch using vtables so we can have a stable type to cast
// to from the void* passed to the worker thread (required because
// the tinythreads interface allows to pass only a void* to the
// thread main rather than a generic type / template)
-
-struct Worker
-{
+struct Worker
+{
// construct and destruct (delete virtually)
Worker() {}
virtual ~Worker() {}
-
+
// dispatch work over a range of values
- virtual void operator()(std::size_t begin, std::size_t end) = 0;
-
- // disable copying and assignment
+ virtual void operator()(std::size_t begin, std::size_t end) = 0;
+
private:
+ // disable copying and assignment
Worker(const Worker&);
void operator=(const Worker&);
};
-// Tag type used for disambiguating splitting constructors
+// Used for controlling the stack size for threads / tasks within a scope.
+class ThreadStackSizeControl
+{
+public:
+ ThreadStackSizeControl();
+ ~ThreadStackSizeControl();
+
+private:
+ // COPYING: not copyable
+ ThreadStackSizeControl(const ThreadStackSizeControl&);
+ ThreadStackSizeControl& operator=(const ThreadStackSizeControl&);
+};
-struct Split {};
} // namespace RcppParallel
diff --git a/inst/include/RcppParallel/RMatrix.h b/inst/include/RcppParallel/RMatrix.h
index ca391b79a..576be720f 100644
--- a/inst/include/RcppParallel/RMatrix.h
+++ b/inst/include/RcppParallel/RMatrix.h
@@ -14,16 +14,21 @@ class RMatrix {
public:
template
- class row_iterator
- : public std::iterator {
+ class row_iterator {
public:
- inline row_iterator(Row& row, std::size_t i)
+ using iterator_category = std::random_access_iterator_tag;
+ using value_type = V;
+ using difference_type = std::size_t;
+ using pointer = value_type*;
+ using reference = value_type&;
+
+ inline row_iterator(Row& row, difference_type i)
: start_(row.start_), parentNrow_(row.parent_.nrow()), index_(i)
{
}
- inline row_iterator(V* start, std::size_t parentNrow, std::size_t index)
+ inline row_iterator(pointer start, difference_type parentNrow, difference_type index)
: start_(start), parentNrow_(parentNrow), index_(index)
{
}
@@ -57,23 +62,23 @@ class RMatrix {
return tmp ;
}
- row_iterator operator+(std::size_t n) const {
+ row_iterator operator+(difference_type n) const {
return row_iterator(start_, parentNrow_ ,index_ + n ) ;
}
- row_iterator operator-(std::size_t n) const {
+ row_iterator operator-(difference_type n) const {
return row_iterator(start_, parentNrow_, index_ - n ) ;
}
- std::size_t operator+(const row_iterator& other) const {
+ difference_type operator+(const row_iterator& other) const {
return index_ + other.index_;
}
- std::size_t operator-(const row_iterator& other) const {
+ difference_type operator-(const row_iterator& other) const {
return index_ - other.index_ ;
}
- row_iterator& operator+=(std::size_t n) { index_ += n ; return *this; }
- row_iterator& operator-=(std::size_t n) { index_ -= n ; return *this; }
+ row_iterator& operator+=(difference_type n) { index_ += n ; return *this; }
+ row_iterator& operator-=(difference_type n) { index_ -= n ; return *this; }
bool operator==(const row_iterator& other) const { return index_ == other.index_; }
bool operator!=(const row_iterator& other) const { return index_ != other.index_; }
@@ -83,16 +88,16 @@ class RMatrix {
bool operator>=(const row_iterator& other) const { return index_ >= other.index_; }
- inline V& operator*() { return start_[index_ * parentNrow_]; }
+ inline reference operator*() { return start_[index_ * parentNrow_]; }
- inline V* operator->() { return &(start_[index_ * parentNrow_]); }
+ inline pointer operator->() { return &(start_[index_ * parentNrow_]); }
- inline V& operator[](int i) { return start_[(index_+i) * parentNrow_]; }
+ inline reference operator[](int i) { return start_[(index_+i) * parentNrow_]; }
private:
- V* start_;
- std::size_t parentNrow_;
- std::size_t index_;
+ pointer start_;
+ difference_type parentNrow_;
+ difference_type index_;
};
typedef row_iterator iterator;
@@ -204,7 +209,7 @@ class RMatrix {
{
}
- inline RMatrix(const T* data, std::size_t nrow, std::size_t ncol)
+ inline RMatrix(T* data, std::size_t nrow, std::size_t ncol)
: data_(data), nrow_(nrow), ncol_(ncol)
{
}
diff --git a/inst/include/RcppParallel/TBB.h b/inst/include/RcppParallel/TBB.h
index 0d72178bb..5ac5722d8 100644
--- a/inst/include/RcppParallel/TBB.h
+++ b/inst/include/RcppParallel/TBB.h
@@ -3,74 +3,162 @@
#include "Common.h"
-#include
-#include
+#ifndef TBB_PREVIEW_GLOBAL_CONTROL
+# define TBB_PREVIEW_GLOBAL_CONTROL 1
+#endif
-namespace RcppParallel {
+// For compatibility with existing packages on CRAN.
+#include "tbb/blocked_range.h"
+#include "tbb/concurrent_unordered_set.h"
+#include "tbb/concurrent_unordered_map.h"
+#include "tbb/global_control.h"
+#include "tbb/mutex.h"
+#include "tbb/parallel_for.h"
+#include "tbb/parallel_for_each.h"
+#include "tbb/parallel_reduce.h"
+#include "tbb/parallel_sort.h"
+#include "tbb/spin_mutex.h"
-namespace {
+// For compatibility with older R packages.
+namespace tbb {
-struct TBBWorker
-{
- explicit TBBWorker(Worker& worker) : worker_(worker) {}
+#ifndef __TBB_task_scheduler_init_H
+#define __TBB_task_scheduler_init_H
+
+class task_scheduler_init {
- void operator()(const tbb::blocked_range& r) const {
- worker_(r.begin(), r.end());
+public:
+ task_scheduler_init(
+ int number_of_threads = -1,
+ std::size_t stack_size = 0)
+ {
}
-
-private:
- Worker& worker_;
+
+ static int default_num_threads()
+ {
+ return 2;
+ }
+
+ static const int automatic = -1;
+ static const int deferred = -2;
+
};
-template
-struct TBBReducer
-{
- explicit TBBReducer(Reducer& reducer)
- : pSplitReducer_(NULL), reducer_(reducer)
+#endif
+
+} // end namespace tbb
+
+
+namespace RcppParallel {
+
+// This class is primarily used to implement type erasure. The goals here were:
+//
+// 1. Hide the tbb symbols / implementation details from client R packages.
+// That is, they should get the tools they need only via RcppParallel.
+//
+// 2. Do this in a way that preserves binary compatibility with pre-existing
+// classes that make use of parallelReduce().
+//
+// 3. Ensure that those packages, when re-compiled without source changes,
+// can still function as expected.
+//
+// The downside here is that all the indirection through std::function<>
+// and the requirement for RTTI is probably expensive, but I couldn't find
+// a better way forward that could also preserve binary compatibility with
+// existing pre-built pacakges.
+//
+// Hopefully, in a future release, we can do away with this wrapper, once
+// packages have been rebuilt and no longer implicitly depend on TBB internals.
+struct ReducerWrapper {
+
+ template
+ ReducerWrapper(T* reducer)
+ {
+ self_ = reinterpret_cast(reducer);
+ owned_ = false;
+
+ work_ = [&](void* self, std::size_t begin, std::size_t end)
+ {
+ (*reinterpret_cast(self))(begin, end);
+ };
+
+ split_ = [&](void* object, Split split)
+ {
+ return new T(*reinterpret_cast(object), split);
+ };
+
+ join_ = [&](void* self, void* other)
+ {
+ (*reinterpret_cast(self)).join(*reinterpret_cast(other));
+ };
+
+ deleter_ = [&](void* object)
+ {
+ delete (T*) object;
+ };
+ }
+
+ ~ReducerWrapper()
{
+ if (owned_)
+ {
+ deleter_(self_);
+ self_ = nullptr;
+ }
}
-
- TBBReducer(TBBReducer& tbbReducer, tbb::split)
- : pSplitReducer_(new Reducer(tbbReducer.reducer_, RcppParallel::Split())),
- reducer_(*pSplitReducer_)
+
+ void operator()(std::size_t begin, std::size_t end) const
{
+ work_(self_, begin, end);
}
-
- virtual ~TBBReducer() { delete pSplitReducer_; }
- void operator()(const tbb::blocked_range& r) {
- reducer_(r.begin(), r.end());
+ ReducerWrapper(const ReducerWrapper& rhs, Split split)
+ {
+ self_ = rhs.split_(rhs.self_, split);
+ owned_ = true;
+
+ work_ = rhs.work_;
+ split_ = rhs.split_;
+ join_ = rhs.join_;
+ deleter_ = rhs.deleter_;
}
-
- void join(const TBBReducer& tbbReducer) {
- reducer_.join(tbbReducer.reducer_);
+
+ void join(const ReducerWrapper& rhs) const
+ {
+ join_(self_, rhs.self_);
}
-
+
private:
- Reducer* pSplitReducer_;
- Reducer& reducer_;
+ void* self_ = nullptr;
+ bool owned_ = false;
+
+ std::function work_;
+ std::function split_;
+ std::function join_;
+ std::function deleter_;
};
-
-} // anonymous namespace
+void tbbParallelFor(std::size_t begin,
+ std::size_t end,
+ Worker& worker,
+ std::size_t grainSize = 1,
+ int numThreads = -1);
-inline void tbbParallelFor(std::size_t begin, std::size_t end,
- Worker& worker, std::size_t grainSize = 1) {
-
- TBBWorker tbbWorker(worker);
-
- tbb::parallel_for(tbb::blocked_range(begin, end, grainSize),
- tbbWorker);
-}
+void tbbParallelReduceImpl(std::size_t begin,
+ std::size_t end,
+ ReducerWrapper& wrapper,
+ std::size_t grainSize = 1,
+ int numThreads = -1);
template
-inline void tbbParallelReduce(std::size_t begin, std::size_t end,
- Reducer& reducer, std::size_t grainSize = 1) {
-
- TBBReducer tbbReducer(reducer);
-
- tbb::parallel_reduce(tbb::blocked_range(begin, end, grainSize),
- tbbReducer);
+void tbbParallelReduce(std::size_t begin,
+ std::size_t end,
+ Reducer& reducer,
+ std::size_t grainSize = 1,
+ int numThreads = -1)
+{
+ ReducerWrapper wrapper(&reducer);
+ tbbParallelReduceImpl(begin, end, wrapper, grainSize, numThreads);
}
} // namespace RcppParallel
diff --git a/inst/include/RcppParallel/TinyThread.h b/inst/include/RcppParallel/TinyThread.h
index 809f34bc2..dfa3dcb73 100644
--- a/inst/include/RcppParallel/TinyThread.h
+++ b/inst/include/RcppParallel/TinyThread.h
@@ -2,12 +2,12 @@
#define __RCPP_PARALLEL_TINYTHREAD__
#include
+#include
#include "Common.h"
#include
-#include
#include
@@ -89,10 +89,15 @@ std::vector splitInputRange(const IndexRange& range,
// allocate ranges
std::vector ranges;
std::size_t begin = range.begin();
+ std::size_t end = begin;
while (begin < range.end()) {
- std::size_t end = std::min(begin + grainSize, range.end());
- ranges.push_back(IndexRange(begin, end));
- begin = end;
+ if ((range.end() - (begin + grainSize)) < grainSize)
+ end = range.end();
+ else
+ end = std::min(begin + grainSize, range.end());
+
+ ranges.push_back(IndexRange(begin, end));
+ begin = end;
}
// return ranges
@@ -102,9 +107,11 @@ std::vector splitInputRange(const IndexRange& range,
} // anonymous namespace
// Execute the Worker over the IndexRange in parallel
-inline void ttParallelFor(std::size_t begin, std::size_t end,
- Worker& worker, std::size_t grainSize = 1) {
-
+inline void ttParallelFor(std::size_t begin,
+ std::size_t end,
+ Worker& worker,
+ std::size_t grainSize = 1)
+{
// split the work
IndexRange inputRange(begin, end);
std::vector ranges = splitInputRange(inputRange, grainSize);
@@ -124,9 +131,11 @@ inline void ttParallelFor(std::size_t begin, std::size_t end,
// Execute the IWorker over the range in parallel then join results
template
-inline void ttParallelReduce(std::size_t begin, std::size_t end,
- Reducer& reducer, std::size_t grainSize = 1) {
-
+inline void ttParallelReduce(std::size_t begin,
+ std::size_t end,
+ Reducer& reducer,
+ std::size_t grainSize = 1)
+{
// split the work
IndexRange inputRange(begin, end);
std::vector ranges = splitInputRange(inputRange, grainSize);
diff --git a/inst/include/index.html b/inst/include/index.html
deleted file mode 100644
index b0962e012..000000000
--- a/inst/include/index.html
+++ /dev/null
@@ -1,25 +0,0 @@
-
-
-
-Overview
-Include files for Intel® Threading Building Blocks (Intel® TBB).
-
-Directories
-
-- tbb
-
- Include files for Intel TBB classes and functions.
-
- serial/tbb
-
- Include files for a sequential implementation of the parallel_for algorithm.
-
-
-
-Up to parent directory
-
-Copyright © 2005-2017 Intel Corporation. All Rights Reserved.
-
-Intel is a registered trademark or trademark of Intel Corporation
-or its subsidiaries in the United States and other countries.
-
-* Other names and brands may be claimed as the property of others.
-
-
diff --git a/inst/include/serial/tbb/parallel_for.h b/inst/include/serial/tbb/parallel_for.h
deleted file mode 100644
index e5959c222..000000000
--- a/inst/include/serial/tbb/parallel_for.h
+++ /dev/null
@@ -1,219 +0,0 @@
-/*
- Copyright (c) 2005-2018 Intel Corporation
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
-
-
-
-
-*/
-
-#ifndef __TBB_SERIAL_parallel_for_H
-#define __TBB_SERIAL_parallel_for_H
-
-#include "tbb_annotate.h"
-
-#ifndef __TBB_NORMAL_EXECUTION
-#include "tbb/blocked_range.h"
-#include "tbb/partitioner.h"
-#endif
-
-#if TBB_USE_EXCEPTIONS
-#include
-#include // required to construct std exception classes
-#else
-#include
-#include
-#endif
-
-namespace tbb {
-namespace serial {
-namespace interface9 {
-
-// parallel_for serial annotated implementation
-
-template< typename Range, typename Body, typename Partitioner >
-class start_for : tbb::internal::no_copy {
- Range my_range;
- const Body my_body;
- typename Partitioner::task_partition_type my_partition;
- void execute();
-
- //! Constructor for root task.
- start_for( const Range& range, const Body& body, Partitioner& partitioner ) :
- my_range( range ),
- my_body( body ),
- my_partition( partitioner )
- {
- }
-
- //! Splitting constructor used to generate children.
- /** this becomes left child. Newly constructed object is right child. */
- start_for( start_for& parent_, typename Partitioner::split_type& split_obj ) :
- my_range( parent_.my_range, split_obj ),
- my_body( parent_.my_body ),
- my_partition( parent_.my_partition, split_obj )
- {
- }
-
-public:
- static void run( const Range& range, const Body& body, Partitioner& partitioner ) {
- if( !range.empty() ) {
- ANNOTATE_SITE_BEGIN( tbb_parallel_for );
- {
- start_for a( range, body, partitioner );
- a.execute();
- }
- ANNOTATE_SITE_END( tbb_parallel_for );
- }
- }
-};
-
-template< typename Range, typename Body, typename Partitioner >
-void start_for< Range, Body, Partitioner >::execute() {
- if( !my_range.is_divisible() || !my_partition.is_divisible() ) {
- ANNOTATE_TASK_BEGIN( tbb_parallel_for_range );
- {
- my_body( my_range );
- }
- ANNOTATE_TASK_END( tbb_parallel_for_range );
- } else {
- typename Partitioner::split_type split_obj;
- start_for b( *this, split_obj );
- this->execute(); // Execute the left interval first to keep the serial order.
- b.execute(); // Execute the right interval then.
- }
-}
-
-//! Parallel iteration over range with default partitioner.
-/** @ingroup algorithms **/
-template
-void parallel_for( const Range& range, const Body& body ) {
- serial::interface9::start_for::run(range,body,__TBB_DEFAULT_PARTITIONER());
-}
-
-//! Parallel iteration over range with simple partitioner.
-/** @ingroup algorithms **/
-template
-void parallel_for( const Range& range, const Body& body, const simple_partitioner& partitioner ) {
- serial::interface9::start_for::run(range,body,partitioner);
-}
-
-//! Parallel iteration over range with auto_partitioner.
-/** @ingroup algorithms **/
-template
-void parallel_for( const Range& range, const Body& body, const auto_partitioner& partitioner ) {
- serial::interface9::start_for::run(range,body,partitioner);
-}
-
-//! Parallel iteration over range with static_partitioner.
-/** @ingroup algorithms **/
-template
-void parallel_for( const Range& range, const Body& body, const static_partitioner& partitioner ) {
- serial::interface9::start_for::run(range,body,partitioner);
-}
-
-//! Parallel iteration over range with affinity_partitioner.
-/** @ingroup algorithms **/
-template
-void parallel_for( const Range& range, const Body& body, affinity_partitioner& partitioner ) {
- serial::interface9::start_for::run(range,body,partitioner);
-}
-
-//! Implementation of parallel iteration over stepped range of integers with explicit step and partitioner (ignored)
-template
-void parallel_for_impl(Index first, Index last, Index step, const Function& f, Partitioner& ) {
- if (step <= 0 ) {
-#if TBB_USE_EXCEPTIONS
- throw std::invalid_argument( "nonpositive_step" );
-#else
- std::cerr << "nonpositive step in a call to parallel_for" << std::endl;
- std::abort();
-#endif
- } else if (last > first) {
- // Above "else" avoids "potential divide by zero" warning on some platforms
- ANNOTATE_SITE_BEGIN( tbb_parallel_for );
- for( Index i = first; i < last; i = i + step ) {
- ANNOTATE_TASK_BEGIN( tbb_parallel_for_iteration );
- { f( i ); }
- ANNOTATE_TASK_END( tbb_parallel_for_iteration );
- }
- ANNOTATE_SITE_END( tbb_parallel_for );
- }
-}
-
-//! Parallel iteration over a range of integers with explicit step and default partitioner
-template
-void parallel_for(Index first, Index last, Index step, const Function& f) {
- parallel_for_impl(first, last, step, f, auto_partitioner());
-}
-//! Parallel iteration over a range of integers with explicit step and simple partitioner
-template
-void parallel_for(Index first, Index last, Index step, const Function& f, const simple_partitioner& p) {
- parallel_for_impl(first, last, step, f, p);
-}
-//! Parallel iteration over a range of integers with explicit step and auto partitioner
-template
-void parallel_for(Index first, Index last, Index step, const Function& f, const auto_partitioner& p) {
- parallel_for_impl(first, last, step, f, p);
-}
-//! Parallel iteration over a range of integers with explicit step and static partitioner
-template
-void parallel_for(Index first, Index last, Index step, const Function& f, const static_partitioner& p) {
- parallel_for_impl(first, last, step, f, p);
-}
-//! Parallel iteration over a range of integers with explicit step and affinity partitioner
-template
-void parallel_for(Index first, Index last, Index step, const Function& f, affinity_partitioner& p) {
- parallel_for_impl(first, last, step, f, p);
-}
-
-//! Parallel iteration over a range of integers with default step and default partitioner
-template
-void parallel_for(Index first, Index last, const Function& f) {
- parallel_for_impl(first, last, static_cast(1), f, auto_partitioner());
-}
-//! Parallel iteration over a range of integers with default step and simple partitioner
-template
-void parallel_for(Index first, Index last, const Function& f, const simple_partitioner& p) {
- parallel_for_impl(first, last, static_cast(1), f, p);
-}
-//! Parallel iteration over a range of integers with default step and auto partitioner
-template
- void parallel_for(Index first, Index last, const Function& f, const auto_partitioner& p) {
- parallel_for_impl(first, last, static_cast(1), f, p);
-}
-//! Parallel iteration over a range of integers with default step and static partitioner
-template
-void parallel_for(Index first, Index last, const Function& f, const static_partitioner& p) {
- parallel_for_impl(first, last, static_cast(1), f, p);
-}
-//! Parallel iteration over a range of integers with default step and affinity_partitioner
-template
-void parallel_for(Index first, Index last, const Function& f, affinity_partitioner& p) {
- parallel_for_impl(first, last, static_cast(1), f, p);
-}
-
-} // namespace interfaceX
-
-using interface9::parallel_for;
-
-} // namespace serial
-
-#ifndef __TBB_NORMAL_EXECUTION
-using serial::interface9::parallel_for;
-#endif
-
-} // namespace tbb
-
-#endif /* __TBB_SERIAL_parallel_for_H */
diff --git a/inst/include/tbb/aggregator.h b/inst/include/tbb/aggregator.h
deleted file mode 100644
index 6aecbb748..000000000
--- a/inst/include/tbb/aggregator.h
+++ /dev/null
@@ -1,202 +0,0 @@
-/*
- Copyright (c) 2005-2017 Intel Corporation
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
-
-
-
-
-*/
-
-#ifndef __TBB__aggregator_H
-#define __TBB__aggregator_H
-
-#if !TBB_PREVIEW_AGGREGATOR
-#error Set TBB_PREVIEW_AGGREGATOR before including aggregator.h
-#endif
-
-#include "atomic.h"
-#include "tbb_profiling.h"
-
-namespace tbb {
-namespace interface6 {
-
-using namespace tbb::internal;
-
-class aggregator_operation {
- template friend class aggregator_ext;
- uintptr_t status;
- aggregator_operation* my_next;
-public:
- enum aggregator_operation_status { agg_waiting=0, agg_finished };
- aggregator_operation() : status(agg_waiting), my_next(NULL) {}
- /// Call start before handling this operation
- void start() { call_itt_notify(acquired, &status); }
- /// Call finish when done handling this operation
- /** The operation will be released to its originating thread, and possibly deleted. */
- void finish() { itt_store_word_with_release(status, uintptr_t(agg_finished)); }
- aggregator_operation* next() { return itt_hide_load_word(my_next);}
- void set_next(aggregator_operation* n) { itt_hide_store_word(my_next, n); }
-};
-
-namespace internal {
-
-class basic_operation_base : public aggregator_operation {
- friend class basic_handler;
- virtual void apply_body() = 0;
-public:
- basic_operation_base() : aggregator_operation() {}
- virtual ~basic_operation_base() {}
-};
-
-template
-class basic_operation : public basic_operation_base, no_assign {
- const Body& my_body;
- void apply_body() __TBB_override { my_body(); }
-public:
- basic_operation(const Body& b) : basic_operation_base(), my_body(b) {}
-};
-
-class basic_handler {
-public:
- basic_handler() {}
- void operator()(aggregator_operation* op_list) const {
- while (op_list) {
- // ITT note: &(op_list->status) tag is used to cover accesses to the operation data.
- // The executing thread "acquires" the tag (see start()) and then performs
- // the associated operation w/o triggering a race condition diagnostics.
- // A thread that created the operation is waiting for its status (see execute_impl()),
- // so when this thread is done with the operation, it will "release" the tag
- // and update the status (see finish()) to give control back to the waiting thread.
- basic_operation_base& request = static_cast(*op_list);
- // IMPORTANT: need to advance op_list to op_list->next() before calling request.finish()
- op_list = op_list->next();
- request.start();
- request.apply_body();
- request.finish();
- }
- }
-};
-
-} // namespace internal
-
-//! Aggregator base class and expert interface
-/** An aggregator for collecting operations coming from multiple sources and executing
- them serially on a single thread. */
-template
-class aggregator_ext : tbb::internal::no_copy {
-public:
- aggregator_ext(const handler_type& h) : handler_busy(0), handle_operations(h) { mailbox = NULL; }
-
- //! EXPERT INTERFACE: Enter a user-made operation into the aggregator's mailbox.
- /** Details of user-made operations must be handled by user-provided handler */
- void process(aggregator_operation *op) { execute_impl(*op); }
-
-protected:
- /** Place operation in mailbox, then either handle mailbox or wait for the operation
- to be completed by a different thread. */
- void execute_impl(aggregator_operation& op) {
- aggregator_operation* res;
-
- // ITT note: &(op.status) tag is used to cover accesses to this operation. This
- // thread has created the operation, and now releases it so that the handler
- // thread may handle the associated operation w/o triggering a race condition;
- // thus this tag will be acquired just before the operation is handled in the
- // handle_operations functor.
- call_itt_notify(releasing, &(op.status));
- // insert the operation into the list
- do {
- // ITT may flag the following line as a race; it is a false positive:
- // This is an atomic read; we don't provide itt_hide_load_word for atomics
- op.my_next = res = mailbox; // NOT A RACE
- } while (mailbox.compare_and_swap(&op, res) != res);
- if (!res) { // first in the list; handle the operations
- // ITT note: &mailbox tag covers access to the handler_busy flag, which this
- // waiting handler thread will try to set before entering handle_operations.
- call_itt_notify(acquired, &mailbox);
- start_handle_operations();
- __TBB_ASSERT(op.status, NULL);
- }
- else { // not first; wait for op to be ready
- call_itt_notify(prepare, &(op.status));
- spin_wait_while_eq(op.status, uintptr_t(aggregator_operation::agg_waiting));
- itt_load_word_with_acquire(op.status);
- }
- }
-
-
-private:
- //! An atomically updated list (aka mailbox) of aggregator_operations
- atomic mailbox;
-
- //! Controls thread access to handle_operations
- /** Behaves as boolean flag where 0=false, 1=true */
- uintptr_t handler_busy;
-
- handler_type handle_operations;
-
- //! Trigger the handling of operations when the handler is free
- void start_handle_operations() {
- aggregator_operation *pending_operations;
-
- // ITT note: &handler_busy tag covers access to mailbox as it is passed
- // between active and waiting handlers. Below, the waiting handler waits until
- // the active handler releases, and the waiting handler acquires &handler_busy as
- // it becomes the active_handler. The release point is at the end of this
- // function, when all operations in mailbox have been handled by the
- // owner of this aggregator.
- call_itt_notify(prepare, &handler_busy);
- // get handler_busy: only one thread can possibly spin here at a time
- spin_wait_until_eq(handler_busy, uintptr_t(0));
- call_itt_notify(acquired, &handler_busy);
- // acquire fence not necessary here due to causality rule and surrounding atomics
- __TBB_store_with_release(handler_busy, uintptr_t(1));
-
- // ITT note: &mailbox tag covers access to the handler_busy flag itself.
- // Capturing the state of the mailbox signifies that handler_busy has been
- // set and a new active handler will now process that list's operations.
- call_itt_notify(releasing, &mailbox);
- // grab pending_operations
- pending_operations = mailbox.fetch_and_store(NULL);
-
- // handle all the operations
- handle_operations(pending_operations);
-
- // release the handler
- itt_store_word_with_release(handler_busy, uintptr_t(0));
- }
-};
-
-//! Basic aggregator interface
-class aggregator : private aggregator_ext {
-public:
- aggregator() : aggregator_ext(internal::basic_handler()) {}
- //! BASIC INTERFACE: Enter a function for exclusive execution by the aggregator.
- /** The calling thread stores the function object in a basic_operation and
- places the operation in the aggregator's mailbox */
- template
- void execute(const Body& b) {
- internal::basic_operation op(b);
- this->execute_impl(op);
- }
-};
-
-} // namespace interface6
-
-using interface6::aggregator;
-using interface6::aggregator_ext;
-using interface6::aggregator_operation;
-
-} // namespace tbb
-
-#endif // __TBB__aggregator_H
diff --git a/inst/include/tbb/aligned_space.h b/inst/include/tbb/aligned_space.h
deleted file mode 100644
index 56fd85f34..000000000
--- a/inst/include/tbb/aligned_space.h
+++ /dev/null
@@ -1,47 +0,0 @@
-/*
- Copyright (c) 2005-2017 Intel Corporation
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
-
-
-
-
-*/
-
-#ifndef __TBB_aligned_space_H
-#define __TBB_aligned_space_H
-
-#include "tbb_stddef.h"
-#include "tbb_machine.h"
-
-namespace tbb {
-
-//! Block of space aligned sufficiently to construct an array T with N elements.
-/** The elements are not constructed or destroyed by this class.
- @ingroup memory_allocation */
-template
-class aligned_space {
-private:
- typedef __TBB_TypeWithAlignmentAtLeastAsStrict(T) element_type;
- element_type array[(sizeof(T)*N+sizeof(element_type)-1)/sizeof(element_type)];
-public:
- //! Pointer to beginning of array
- T* begin() {return internal::punned_cast(this);}
-
- //! Pointer to one past last element in array.
- T* end() {return begin()+N;}
-};
-
-} // namespace tbb
-
-#endif /* __TBB_aligned_space_H */
diff --git a/inst/include/tbb/atomic.h b/inst/include/tbb/atomic.h
deleted file mode 100644
index 72ec534e3..000000000
--- a/inst/include/tbb/atomic.h
+++ /dev/null
@@ -1,558 +0,0 @@
-/*
- Copyright (c) 2005-2017 Intel Corporation
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
-
-
-
-
-*/
-
-#ifndef __TBB_atomic_H
-#define __TBB_atomic_H
-
-#include
-
-#if _MSC_VER
-#define __TBB_LONG_LONG __int64
-#else
-#define __TBB_LONG_LONG long long
-#endif /* _MSC_VER */
-
-#include "tbb_machine.h"
-
-#if _MSC_VER && !__INTEL_COMPILER
- // Suppress overzealous compiler warnings till the end of the file
- #pragma warning (push)
- #pragma warning (disable: 4244 4267 4512)
-#endif
-
-namespace tbb {
-
-//! Specifies memory semantics.
-enum memory_semantics {
- //! Sequential consistency
- full_fence,
- //! Acquire
- acquire,
- //! Release
- release,
- //! No ordering
- relaxed
-};
-
-//! @cond INTERNAL
-namespace internal {
-
-#if __TBB_ALIGNAS_PRESENT
- #define __TBB_DECL_ATOMIC_FIELD(t,f,a) alignas(a) t f;
-#elif __TBB_ATTRIBUTE_ALIGNED_PRESENT
- #define __TBB_DECL_ATOMIC_FIELD(t,f,a) t f __attribute__ ((aligned(a)));
-#elif __TBB_DECLSPEC_ALIGN_PRESENT
- #define __TBB_DECL_ATOMIC_FIELD(t,f,a) __declspec(align(a)) t f;
-#else
- #error Do not know syntax for forcing alignment.
-#endif
-
-template
-struct atomic_rep; // Primary template declared, but never defined.
-
-template<>
-struct atomic_rep<1> { // Specialization
- typedef int8_t word;
-};
-template<>
-struct atomic_rep<2> { // Specialization
- typedef int16_t word;
-};
-template<>
-struct atomic_rep<4> { // Specialization
-#if _MSC_VER && !_WIN64
- // Work-around that avoids spurious /Wp64 warnings
- typedef intptr_t word;
-#else
- typedef int32_t word;
-#endif
-};
-#if __TBB_64BIT_ATOMICS
-template<>
-struct atomic_rep<8> { // Specialization
- typedef int64_t word;
-};
-#endif
-
-template
-struct aligned_storage;
-
-//the specializations are needed to please MSVC syntax of __declspec(align()) which accept _literal_ constants only
-#if __TBB_ATOMIC_CTORS
- #define ATOMIC_STORAGE_PARTIAL_SPECIALIZATION(S) \
- template \
- struct aligned_storage { \
- __TBB_DECL_ATOMIC_FIELD(value_type,my_value,S) \
- aligned_storage() = default ; \
- constexpr aligned_storage(value_type value):my_value(value){} \
- }; \
-
-#else
- #define ATOMIC_STORAGE_PARTIAL_SPECIALIZATION(S) \
- template \
- struct aligned_storage { \
- __TBB_DECL_ATOMIC_FIELD(value_type,my_value,S) \
- }; \
-
-#endif
-
-template
-struct aligned_storage {
- value_type my_value;
-#if __TBB_ATOMIC_CTORS
- aligned_storage() = default ;
- constexpr aligned_storage(value_type value):my_value(value){}
-#endif
-};
-
-ATOMIC_STORAGE_PARTIAL_SPECIALIZATION(2)
-ATOMIC_STORAGE_PARTIAL_SPECIALIZATION(4)
-#if __TBB_64BIT_ATOMICS
-ATOMIC_STORAGE_PARTIAL_SPECIALIZATION(8)
-#endif
-
-template
-struct atomic_traits; // Primary template declared, but not defined.
-
-#define __TBB_DECL_FENCED_ATOMIC_PRIMITIVES(S,M) \
- template<> struct atomic_traits { \
- typedef atomic_rep::word word; \
- inline static word compare_and_swap( volatile void* location, word new_value, word comparand ) { \
- return __TBB_machine_cmpswp##S##M(location,new_value,comparand); \
- } \
- inline static word fetch_and_add( volatile void* location, word addend ) { \
- return __TBB_machine_fetchadd##S##M(location,addend); \
- } \
- inline static word fetch_and_store( volatile void* location, word value ) { \
- return __TBB_machine_fetchstore##S##M(location,value); \
- } \
- };
-
-#define __TBB_DECL_ATOMIC_PRIMITIVES(S) \
- template \
- struct atomic_traits { \
- typedef atomic_rep::word word; \
- inline static word compare_and_swap( volatile void* location, word new_value, word comparand ) { \
- return __TBB_machine_cmpswp##S(location,new_value,comparand); \
- } \
- inline static word fetch_and_add( volatile void* location, word addend ) { \
- return __TBB_machine_fetchadd##S(location,addend); \
- } \
- inline static word fetch_and_store( volatile void* location, word value ) { \
- return __TBB_machine_fetchstore##S(location,value); \
- } \
- };
-
-template
-struct atomic_load_store_traits; // Primary template declaration
-
-#define __TBB_DECL_ATOMIC_LOAD_STORE_PRIMITIVES(M) \
- template<> struct atomic_load_store_traits { \
- template \
- inline static T load( const volatile T& location ) { \
- return __TBB_load_##M( location ); \
- } \
- template \
- inline static void store( volatile T& location, T value ) { \
- __TBB_store_##M( location, value ); \
- } \
- }
-
-#if __TBB_USE_FENCED_ATOMICS
-__TBB_DECL_FENCED_ATOMIC_PRIMITIVES(1,full_fence)
-__TBB_DECL_FENCED_ATOMIC_PRIMITIVES(2,full_fence)
-__TBB_DECL_FENCED_ATOMIC_PRIMITIVES(4,full_fence)
-__TBB_DECL_FENCED_ATOMIC_PRIMITIVES(1,acquire)
-__TBB_DECL_FENCED_ATOMIC_PRIMITIVES(2,acquire)
-__TBB_DECL_FENCED_ATOMIC_PRIMITIVES(4,acquire)
-__TBB_DECL_FENCED_ATOMIC_PRIMITIVES(1,release)
-__TBB_DECL_FENCED_ATOMIC_PRIMITIVES(2,release)
-__TBB_DECL_FENCED_ATOMIC_PRIMITIVES(4,release)
-__TBB_DECL_FENCED_ATOMIC_PRIMITIVES(1,relaxed)
-__TBB_DECL_FENCED_ATOMIC_PRIMITIVES(2,relaxed)
-__TBB_DECL_FENCED_ATOMIC_PRIMITIVES(4,relaxed)
-#if __TBB_64BIT_ATOMICS
-__TBB_DECL_FENCED_ATOMIC_PRIMITIVES(8,full_fence)
-__TBB_DECL_FENCED_ATOMIC_PRIMITIVES(8,acquire)
-__TBB_DECL_FENCED_ATOMIC_PRIMITIVES(8,release)
-__TBB_DECL_FENCED_ATOMIC_PRIMITIVES(8,relaxed)
-#endif
-#else /* !__TBB_USE_FENCED_ATOMICS */
-__TBB_DECL_ATOMIC_PRIMITIVES(1)
-__TBB_DECL_ATOMIC_PRIMITIVES(2)
-__TBB_DECL_ATOMIC_PRIMITIVES(4)
-#if __TBB_64BIT_ATOMICS
-__TBB_DECL_ATOMIC_PRIMITIVES(8)
-#endif
-#endif /* !__TBB_USE_FENCED_ATOMICS */
-
-__TBB_DECL_ATOMIC_LOAD_STORE_PRIMITIVES(full_fence);
-__TBB_DECL_ATOMIC_LOAD_STORE_PRIMITIVES(acquire);
-__TBB_DECL_ATOMIC_LOAD_STORE_PRIMITIVES(release);
-__TBB_DECL_ATOMIC_LOAD_STORE_PRIMITIVES(relaxed);
-
-//! Additive inverse of 1 for type T.
-/** Various compilers issue various warnings if -1 is used with various integer types.
- The baroque expression below avoids all the warnings (we hope). */
-#define __TBB_MINUS_ONE(T) (T(T(0)-T(1)))
-
-//! Base class that provides basic functionality for atomic without fetch_and_add.
-/** Works for any type T that has the same size as an integral type, has a trivial constructor/destructor,
- and can be copied/compared by memcpy/memcmp. */
-template
-struct atomic_impl {
-protected:
- aligned_storage my_storage;
-private:
- //TODO: rechecks on recent versions of gcc if union is still the _only_ way to do a conversion without warnings
- //! Union type used to convert type T to underlying integral type.
- template
- union converter {
- typedef typename atomic_rep::word bits_type;
- converter(){}
- converter(value_type a_value) : value(a_value) {}
- value_type value;
- bits_type bits;
- };
-
- template
- static typename converter::bits_type to_bits(value_t value){
- return converter(value).bits;
- }
- template
- static value_t to_value(typename converter::bits_type bits){
- converter u;
- u.bits = bits;
- return u.value;
- }
-
- template
- union ptr_converter; //Primary template declared, but never defined.
-
- template
- union ptr_converter {
- ptr_converter(){}
- ptr_converter(value_t* a_value) : value(a_value) {}
- value_t* value;
- uintptr_t bits;
- };
- //TODO: check if making to_bits accepting reference (thus unifying it with to_bits_ref)
- //does not hurt performance
- template
- static typename converter::bits_type & to_bits_ref(value_t& value){
- //TODO: this #ifdef is temporary workaround, as union conversion seems to fail
- //on suncc for 64 bit types for 32 bit target
- #if !__SUNPRO_CC
- return *(typename converter::bits_type*)ptr_converter(&value).bits;
- #else
- return *(typename converter::bits_type*)(&value);
- #endif
- }
-
-
-public:
- typedef T value_type;
-
-#if __TBB_ATOMIC_CTORS
- atomic_impl() = default ;
- constexpr atomic_impl(value_type value):my_storage(value){}
-#endif
- template
- value_type fetch_and_store( value_type value ) {
- return to_value(
- internal::atomic_traits::fetch_and_store( &my_storage.my_value, to_bits(value) )
- );
- }
-
- value_type fetch_and_store( value_type value ) {
- return fetch_and_store(value);
- }
-
- template
- value_type compare_and_swap( value_type value, value_type comparand ) {
- return to_value(
- internal::atomic_traits::compare_and_swap( &my_storage.my_value, to_bits(value), to_bits(comparand) )
- );
- }
-
- value_type compare_and_swap( value_type value, value_type comparand ) {
- return compare_and_swap(value,comparand);
- }
-
- operator value_type() const volatile { // volatile qualifier here for backwards compatibility
- return to_value(
- __TBB_load_with_acquire( to_bits_ref(my_storage.my_value) )
- );
- }
-
- template
- value_type load () const {
- return to_value(
- internal::atomic_load_store_traits::load( to_bits_ref(my_storage.my_value) )
- );
- }
-
- value_type load () const {
- return load();
- }
-
- template
- void store ( value_type value ) {
- internal::atomic_load_store_traits::store( to_bits_ref(my_storage.my_value), to_bits(value));
- }
-
- void store ( value_type value ) {
- store( value );
- }
-
-protected:
- value_type store_with_release( value_type rhs ) {
- //TODO: unify with store
- __TBB_store_with_release( to_bits_ref(my_storage.my_value), to_bits(rhs) );
- return rhs;
- }
-};
-
-//! Base class that provides basic functionality for atomic with fetch_and_add.
-/** I is the underlying type.
- D is the difference type.
- StepType should be char if I is an integral type, and T if I is a T*. */
-template
-struct atomic_impl_with_arithmetic: atomic_impl {
-public:
- typedef I value_type;
-#if __TBB_ATOMIC_CTORS
- atomic_impl_with_arithmetic() = default ;
- constexpr atomic_impl_with_arithmetic(value_type value): atomic_impl(value){}
-#endif
- template
- value_type fetch_and_add( D addend ) {
- return value_type(internal::atomic_traits::fetch_and_add( &this->my_storage.my_value, addend*sizeof(StepType) ));
- }
-
- value_type fetch_and_add( D addend ) {
- return fetch_and_add(addend);
- }
-
- template
- value_type fetch_and_increment() {
- return fetch_and_add(1);
- }
-
- value_type fetch_and_increment() {
- return fetch_and_add(1);
- }
-
- template
- value_type fetch_and_decrement() {
- return fetch_and_add(__TBB_MINUS_ONE(D));
- }
-
- value_type fetch_and_decrement() {
- return fetch_and_add(__TBB_MINUS_ONE(D));
- }
-
-public:
- value_type operator+=( D value ) {
- return fetch_and_add(value)+value;
- }
-
- value_type operator-=( D value ) {
- // Additive inverse of value computed using binary minus,
- // instead of unary minus, for sake of avoiding compiler warnings.
- return operator+=(D(0)-value);
- }
-
- value_type operator++() {
- return fetch_and_add(1)+1;
- }
-
- value_type operator--() {
- return fetch_and_add(__TBB_MINUS_ONE(D))-1;
- }
-
- value_type operator++(int) {
- return fetch_and_add(1);
- }
-
- value_type operator--(int) {
- return fetch_and_add(__TBB_MINUS_ONE(D));
- }
-};
-
-} /* Internal */
-//! @endcond
-
-//! Primary template for atomic.
-/** See the Reference for details.
- @ingroup synchronization */
-template
-struct atomic: internal::atomic_impl {
-#if __TBB_ATOMIC_CTORS
- atomic() = default;
- constexpr atomic(T arg): internal::atomic_impl(arg) {}
-#endif
- T operator=( T rhs ) {
- // "this" required here in strict ISO C++ because store_with_release is a dependent name
- return this->store_with_release(rhs);
- }
- atomic& operator=( const atomic& rhs ) {this->store_with_release(rhs); return *this;}
-};
-
-#if __TBB_ATOMIC_CTORS
- #define __TBB_DECL_ATOMIC(T) \
- template<> struct atomic: internal::atomic_impl_with_arithmetic { \
- atomic() = default; \
- constexpr atomic(T arg): internal::atomic_impl_with_arithmetic(arg) {} \
- \
- T operator=( T rhs ) {return store_with_release(rhs);} \
- atomic& operator=( const atomic& rhs ) {store_with_release(rhs); return *this;} \
- };
-#else
- #define __TBB_DECL_ATOMIC(T) \
- template<> struct atomic: internal::atomic_impl_with_arithmetic { \
- T operator=( T rhs ) {return store_with_release(rhs);} \
- atomic& operator=( const atomic& rhs ) {store_with_release(rhs); return *this;} \
- };
-#endif
-
-#if __TBB_64BIT_ATOMICS
-//TODO: consider adding non-default (and atomic) copy constructor for 32bit platform
-__TBB_DECL_ATOMIC(__TBB_LONG_LONG)
-__TBB_DECL_ATOMIC(unsigned __TBB_LONG_LONG)
-#else
-// test_atomic will verify that sizeof(long long)==8
-#endif
-__TBB_DECL_ATOMIC(long)
-__TBB_DECL_ATOMIC(unsigned long)
-
-#if _MSC_VER && !_WIN64
-#if __TBB_ATOMIC_CTORS
-/* Special version of __TBB_DECL_ATOMIC that avoids gratuitous warnings from cl /Wp64 option.
- It is identical to __TBB_DECL_ATOMIC(unsigned) except that it replaces operator=(T)
- with an operator=(U) that explicitly converts the U to a T. Types T and U should be
- type synonyms on the platform. Type U should be the wider variant of T from the
- perspective of /Wp64. */
-#define __TBB_DECL_ATOMIC_ALT(T,U) \
- template<> struct atomic: internal::atomic_impl_with_arithmetic { \
- atomic() = default ; \
- constexpr atomic(T arg): internal::atomic_impl_with_arithmetic(arg) {} \
- T operator=( U rhs ) {return store_with_release(T(rhs));} \
- atomic& operator=( const atomic& rhs ) {store_with_release(rhs); return *this;} \
- };
-#else
-#define __TBB_DECL_ATOMIC_ALT(T,U) \
- template<> struct atomic: internal::atomic_impl_with_arithmetic { \
- T operator=( U rhs ) {return store_with_release(T(rhs));} \
- atomic& operator=( const atomic& rhs ) {store_with_release(rhs); return *this;} \
- };
-#endif
-__TBB_DECL_ATOMIC_ALT(unsigned,size_t)
-__TBB_DECL_ATOMIC_ALT(int,ptrdiff_t)
-#else
-__TBB_DECL_ATOMIC(unsigned)
-__TBB_DECL_ATOMIC(int)
-#endif /* _MSC_VER && !_WIN64 */
-
-__TBB_DECL_ATOMIC(unsigned short)
-__TBB_DECL_ATOMIC(short)
-__TBB_DECL_ATOMIC(char)
-__TBB_DECL_ATOMIC(signed char)
-__TBB_DECL_ATOMIC(unsigned char)
-
-#if !_MSC_VER || defined(_NATIVE_WCHAR_T_DEFINED)
-__TBB_DECL_ATOMIC(wchar_t)
-#endif /* _MSC_VER||!defined(_NATIVE_WCHAR_T_DEFINED) */
-
-//! Specialization for atomic with arithmetic and operator->.
-template struct atomic: internal::atomic_impl_with_arithmetic {
-#if __TBB_ATOMIC_CTORS
- atomic() = default ;
- constexpr atomic(T* arg): internal::atomic_impl_with_arithmetic(arg) {}
-#endif
- T* operator=( T* rhs ) {
- // "this" required here in strict ISO C++ because store_with_release is a dependent name
- return this->store_with_release(rhs);
- }
- atomic& operator=( const atomic& rhs ) {
- this->store_with_release(rhs); return *this;
- }
- T* operator->() const {
- return (*this);
- }
-};
-
-//! Specialization for atomic, for sake of not allowing arithmetic or operator->.
-template<> struct atomic: internal::atomic_impl {
-#if __TBB_ATOMIC_CTORS
- atomic() = default ;
- constexpr atomic(void* arg): internal::atomic_impl(arg) {}
-#endif
- void* operator=( void* rhs ) {
- // "this" required here in strict ISO C++ because store_with_release is a dependent name
- return this->store_with_release(rhs);
- }
- atomic& operator=( const atomic& rhs ) {
- this->store_with_release(rhs); return *this;
- }
-};
-
-// Helpers to workaround ugly syntax of calling template member function of a
-// template class with template argument dependent on template parameters.
-
-template
-T load ( const atomic& a ) { return a.template load(); }
-
-template
-void store ( atomic& a, T value ) { a.template store(value); }
-
-namespace interface6{
-//! Make an atomic for use in an initialization (list), as an alternative to zero-initialization or normal assignment.
-template
-atomic make_atomic(T t) {
- atomic a;
- store(a,t);
- return a;
-}
-}
-using interface6::make_atomic;
-
-namespace internal {
-template
-void swap(atomic & lhs, atomic & rhs){
- T tmp = load(lhs);
- store(lhs,load(rhs));
- store(rhs,tmp);
-}
-
-// only to aid in the gradual conversion of ordinary variables to proper atomics
-template
-inline atomic& as_atomic( T& t ) {
- return (atomic&)t;
-}
-} // namespace tbb::internal
-
-} // namespace tbb
-
-#if _MSC_VER && !__INTEL_COMPILER
- #pragma warning (pop)
-#endif // warnings are restored
-
-#endif /* __TBB_atomic_H */
diff --git a/inst/include/tbb/cache_aligned_allocator.h b/inst/include/tbb/cache_aligned_allocator.h
deleted file mode 100644
index d435e785c..000000000
--- a/inst/include/tbb/cache_aligned_allocator.h
+++ /dev/null
@@ -1,137 +0,0 @@
-/*
- Copyright (c) 2005-2017 Intel Corporation
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
-
-
-
-
-*/
-
-#ifndef __TBB_cache_aligned_allocator_H
-#define __TBB_cache_aligned_allocator_H
-
-#include
-#include "tbb_stddef.h"
-#if __TBB_ALLOCATOR_CONSTRUCT_VARIADIC
- #include // std::forward
-#endif
-
-namespace tbb {
-
-//! @cond INTERNAL
-namespace internal {
- //! Cache/sector line size.
- /** @ingroup memory_allocation */
- size_t __TBB_EXPORTED_FUNC NFS_GetLineSize();
-
- //! Allocate memory on cache/sector line boundary.
- /** @ingroup memory_allocation */
- void* __TBB_EXPORTED_FUNC NFS_Allocate( size_t n_element, size_t element_size, void* hint );
-
- //! Free memory allocated by NFS_Allocate.
- /** Freeing a NULL pointer is allowed, but has no effect.
- @ingroup memory_allocation */
- void __TBB_EXPORTED_FUNC NFS_Free( void* );
-}
-//! @endcond
-
-#if _MSC_VER && !defined(__INTEL_COMPILER)
- // Workaround for erroneous "unreferenced parameter" warning in method destroy.
- #pragma warning (push)
- #pragma warning (disable: 4100)
-#endif
-
-//! Meets "allocator" requirements of ISO C++ Standard, Section 20.1.5
-/** The members are ordered the same way they are in section 20.4.1
- of the ISO C++ standard.
- @ingroup memory_allocation */
-template
-class cache_aligned_allocator {
-public:
- typedef typename internal::allocator_type::value_type value_type;
- typedef value_type* pointer;
- typedef const value_type* const_pointer;
- typedef value_type& reference;
- typedef const value_type& const_reference;
- typedef size_t size_type;
- typedef ptrdiff_t difference_type;
- template struct rebind {
- typedef cache_aligned_allocator other;
- };
-
- cache_aligned_allocator() throw() {}
- cache_aligned_allocator( const cache_aligned_allocator& ) throw() {}
- template cache_aligned_allocator(const cache_aligned_allocator&) throw() {}
-
- pointer address(reference x) const {return &x;}
- const_pointer address(const_reference x) const {return &x;}
-
- //! Allocate space for n objects, starting on a cache/sector line.
- pointer allocate( size_type n, const void* hint=0 ) {
- // The "hint" argument is always ignored in NFS_Allocate thus const_cast shouldn't hurt
- return pointer(internal::NFS_Allocate( n, sizeof(value_type), const_cast(hint) ));
- }
-
- //! Free block of memory that starts on a cache line
- void deallocate( pointer p, size_type ) {
- internal::NFS_Free(p);
- }
-
- //! Largest value for which method allocate might succeed.
- size_type max_size() const throw() {
- return (~size_t(0)-internal::NFS_MaxLineSize)/sizeof(value_type);
- }
-
- //! Copy-construct value at location pointed to by p.
-#if __TBB_ALLOCATOR_CONSTRUCT_VARIADIC
- template
- void construct(U *p, Args&&... args)
- { ::new((void *)p) U(std::forward(args)...); }
-#else // __TBB_ALLOCATOR_CONSTRUCT_VARIADIC
-#if __TBB_CPP11_RVALUE_REF_PRESENT
- void construct( pointer p, value_type&& value ) {::new((void*)(p)) value_type(std::move(value));}
-#endif
- void construct( pointer p, const value_type& value ) {::new((void*)(p)) value_type(value);}
-#endif // __TBB_ALLOCATOR_CONSTRUCT_VARIADIC
-
- //! Destroy value at location pointed to by p.
- void destroy( pointer p ) {p->~value_type();}
-};
-
-#if _MSC_VER && !defined(__INTEL_COMPILER)
- #pragma warning (pop)
-#endif // warning 4100 is back
-
-//! Analogous to std::allocator, as defined in ISO C++ Standard, Section 20.4.1
-/** @ingroup memory_allocation */
-template<>
-class cache_aligned_allocator {
-public:
- typedef void* pointer;
- typedef const void* const_pointer;
- typedef void value_type;
- template struct rebind {
- typedef cache_aligned_allocator other;
- };
-};
-
-template
-inline bool operator==( const cache_aligned_allocator&, const cache_aligned_allocator& ) {return true;}
-
-template
-inline bool operator!=( const cache_aligned_allocator&, const cache_aligned_allocator& ) {return false;}
-
-} // namespace tbb
-
-#endif /* __TBB_cache_aligned_allocator_H */
diff --git a/inst/include/tbb/combinable.h b/inst/include/tbb/combinable.h
deleted file mode 100644
index 0063dbb46..000000000
--- a/inst/include/tbb/combinable.h
+++ /dev/null
@@ -1,85 +0,0 @@
-/*
- Copyright (c) 2005-2017 Intel Corporation
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
-
-
-
-
-*/
-
-#ifndef __TBB_combinable_H
-#define __TBB_combinable_H
-
-#include "enumerable_thread_specific.h"
-#include "cache_aligned_allocator.h"
-
-namespace tbb {
-/** \name combinable
- **/
-//@{
-//! Thread-local storage with optional reduction
-/** @ingroup containers */
- template
- class combinable {
-
- private:
- typedef typename tbb::cache_aligned_allocator my_alloc;
- typedef typename tbb::enumerable_thread_specific my_ets_type;
- my_ets_type my_ets;
-
- public:
-
- combinable() { }
-
- template
- explicit combinable( finit _finit) : my_ets(_finit) { }
-
- //! destructor
- ~combinable() { }
-
- combinable( const combinable& other) : my_ets(other.my_ets) { }
-
-#if __TBB_ETS_USE_CPP11
- combinable( combinable&& other) : my_ets( std::move(other.my_ets)) { }
-#endif
-
- combinable & operator=( const combinable & other) {
- my_ets = other.my_ets;
- return *this;
- }
-
-#if __TBB_ETS_USE_CPP11
- combinable & operator=( combinable && other) {
- my_ets=std::move(other.my_ets);
- return *this;
- }
-#endif
-
- void clear() { my_ets.clear(); }
-
- T& local() { return my_ets.local(); }
-
- T& local(bool & exists) { return my_ets.local(exists); }
-
- // combine_func_t has signature T(T,T) or T(const T&, const T&)
- template
- T combine(combine_func_t f_combine) { return my_ets.combine(f_combine); }
-
- // combine_func_t has signature void(T) or void(const T&)
- template
- void combine_each(combine_func_t f_combine) { my_ets.combine_each(f_combine); }
-
- };
-} // namespace tbb
-#endif /* __TBB_combinable_H */
diff --git a/inst/include/tbb/compat/condition_variable b/inst/include/tbb/compat/condition_variable
deleted file mode 100644
index 43edfc032..000000000
--- a/inst/include/tbb/compat/condition_variable
+++ /dev/null
@@ -1,476 +0,0 @@
-/*
- Copyright (c) 2005-2017 Intel Corporation
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
-
-
-
-
-*/
-
-#ifndef __TBB_condition_variable_H
-#define __TBB_condition_variable_H
-
-#if _WIN32||_WIN64
-#include "../machine/windows_api.h"
-
-namespace tbb {
-namespace interface5 {
-namespace internal {
-struct condition_variable_using_event
-{
- //! Event for blocking waiting threads.
- HANDLE event;
- //! Protects invariants involving n_waiters, release_count, and epoch.
- CRITICAL_SECTION mutex;
- //! Number of threads waiting on this condition variable
- int n_waiters;
- //! Number of threads remaining that should no longer wait on this condition variable.
- int release_count;
- //! To keep threads from waking up prematurely with earlier signals.
- unsigned epoch;
-};
-}}} // namespace tbb::interface5::internal
-
-#ifndef CONDITION_VARIABLE_INIT
-typedef void* CONDITION_VARIABLE;
-typedef CONDITION_VARIABLE* PCONDITION_VARIABLE;
-#endif
-
-#else /* if not _WIN32||_WIN64 */
-#include // some systems need it for ETIMEDOUT
-#include
-#if __linux__
-#include
-#else /* generic Unix */
-#include
-#endif
-#endif /* _WIN32||_WIN64 */
-
-#include "../tbb_stddef.h"
-#include "../mutex.h"
-#include "../tbb_thread.h"
-#include "../tbb_exception.h"
-#include "../tbb_profiling.h"
-
-namespace tbb {
-
-namespace interface5 {
-
-// C++0x standard working draft 30.4.3
-// Lock tag types
-struct defer_lock_t { }; //! do not acquire ownership of the mutex
-struct try_to_lock_t { }; //! try to acquire ownership of the mutex without blocking
-struct adopt_lock_t { }; //! assume the calling thread has already
-const defer_lock_t defer_lock = {};
-const try_to_lock_t try_to_lock = {};
-const adopt_lock_t adopt_lock = {};
-
-// C++0x standard working draft 30.4.3.1
-//! lock_guard
-template
-class lock_guard : tbb::internal::no_copy {
-public:
- //! mutex type
- typedef M mutex_type;
-
- //! Constructor
- /** precondition: If mutex_type is not a recursive mutex, the calling thread
- does not own the mutex m. */
- explicit lock_guard(mutex_type& m) : pm(m) {m.lock();}
-
- //! Adopt_lock constructor
- /** precondition: the calling thread owns the mutex m. */
- lock_guard(mutex_type& m, adopt_lock_t) : pm(m) {}
-
- //! Destructor
- ~lock_guard() { pm.unlock(); }
-private:
- mutex_type& pm;
-};
-
-// C++0x standard working draft 30.4.3.2
-//! unique_lock
-template
-class unique_lock : tbb::internal::no_copy {
- friend class condition_variable;
-public:
- typedef M mutex_type;
-
- // 30.4.3.2.1 construct/copy/destroy
- // NB: Without constructors that take an r-value reference to a unique_lock, the following constructor is of little use.
- //! Constructor
- /** postcondition: pm==0 && owns==false */
- unique_lock() : pm(NULL), owns(false) {}
-
- //! Constructor
- /** precondition: if mutex_type is not a recursive mutex, the calling thread
- does not own the mutex m. If the precondition is not met, a deadlock occurs.
- postcondition: pm==&m and owns==true */
- explicit unique_lock(mutex_type& m) : pm(&m) {m.lock(); owns=true;}
-
- //! Defer_lock constructor
- /** postcondition: pm==&m and owns==false */
- unique_lock(mutex_type& m, defer_lock_t) : pm(&m), owns(false) {}
-
- //! Try_to_lock constructor
- /** precondition: if mutex_type is not a recursive mutex, the calling thread
- does not own the mutex m. If the precondition is not met, a deadlock occurs.
- postcondition: pm==&m and owns==res where res is the value returned by
- the call to m.try_lock(). */
- unique_lock(mutex_type& m, try_to_lock_t) : pm(&m) {owns = m.try_lock();}
-
- //! Adopt_lock constructor
- /** precondition: the calling thread owns the mutex. If it does not, mutex->unlock() would fail.
- postcondition: pm==&m and owns==true */
- unique_lock(mutex_type& m, adopt_lock_t) : pm(&m), owns(true) {}
-
- //! Timed unique_lock acquisition.
- /** To avoid requiring support for namespace chrono, this method deviates from the working draft in that
- it uses tbb::tick_count::interval_t to specify the time duration. */
- unique_lock(mutex_type& m, const tick_count::interval_t &i) : pm(&m) {owns = try_lock_for( i );}
-
-#if __TBB_CPP11_RVALUE_REF_PRESENT
- //! Move constructor
- /** postconditions: pm == src_p.pm and owns == src_p.owns (where src_p is the state of src just prior to this
- construction), src.pm == 0 and src.owns == false. */
- unique_lock(unique_lock && src): pm(NULL), owns(false) {this->swap(src);}
-
- //! Move assignment
- /** effects: If owns calls pm->unlock().
- Postconditions: pm == src_p.pm and owns == src_p.owns (where src_p is the state of src just prior to this
- assignment), src.pm == 0 and src.owns == false. */
- unique_lock& operator=(unique_lock && src) {
- if (owns)
- this->unlock();
- pm = NULL;
- this->swap(src);
- return *this;
- }
-#endif // __TBB_CPP11_RVALUE_REF_PRESENT
-
- //! Destructor
- ~unique_lock() { if( owns ) pm->unlock(); }
-
- // 30.4.3.2.2 locking
- //! Lock the mutex and own it.
- void lock() {
- if( pm ) {
- if( !owns ) {
- pm->lock();
- owns = true;
- } else
- throw_exception_v4( tbb::internal::eid_possible_deadlock );
- } else
- throw_exception_v4( tbb::internal::eid_operation_not_permitted );
- __TBB_ASSERT( owns, NULL );
- }
-
- //! Try to lock the mutex.
- /** If successful, note that this lock owns it. Otherwise, set it false. */
- bool try_lock() {
- if( pm ) {
- if( !owns )
- owns = pm->try_lock();
- else
- throw_exception_v4( tbb::internal::eid_possible_deadlock );
- } else
- throw_exception_v4( tbb::internal::eid_operation_not_permitted );
- return owns;
- }
-
- //! Try to lock the mutex.
- bool try_lock_for( const tick_count::interval_t &i );
-
- //! Unlock the mutex
- /** And note that this lock no longer owns it. */
- void unlock() {
- if( owns ) {
- pm->unlock();
- owns = false;
- } else
- throw_exception_v4( tbb::internal::eid_operation_not_permitted );
- __TBB_ASSERT( !owns, NULL );
- }
-
- // 30.4.3.2.3 modifiers
- //! Swap the two unique locks
- void swap(unique_lock& u) {
- mutex_type* t_pm = u.pm; u.pm = pm; pm = t_pm;
- bool t_owns = u.owns; u.owns = owns; owns = t_owns;
- }
-
- //! Release control over the mutex.
- mutex_type* release() {
- mutex_type* o_pm = pm;
- pm = NULL;
- owns = false;
- return o_pm;
- }
-
- // 30.4.3.2.4 observers
- //! Does this lock own the mutex?
- bool owns_lock() const { return owns; }
-
- // TODO: Un-comment 'explicit' when the last non-C++0x compiler support is dropped
- //! Does this lock own the mutex?
- /*explicit*/ operator bool() const { return owns; }
-
- //! Return the mutex that this lock currently has.
- mutex_type* mutex() const { return pm; }
-
-private:
- mutex_type* pm;
- bool owns;
-};
-
-template
-bool unique_lock::try_lock_for( const tick_count::interval_t &i)
-{
- const int unique_lock_tick = 100; /* microseconds; 0.1 milliseconds */
- // the smallest wait-time is 0.1 milliseconds.
- bool res = pm->try_lock();
- int duration_in_micro;
- if( !res && (duration_in_micro=int(i.seconds()*1e6))>unique_lock_tick ) {
- tick_count::interval_t i_100( double(unique_lock_tick)/1e6 /* seconds */); // 100 microseconds = 0.1*10E-3
- do {
- this_tbb_thread::sleep(i_100); // sleep for 100 micro seconds
- duration_in_micro -= unique_lock_tick;
- res = pm->try_lock();
- } while( !res && duration_in_micro>unique_lock_tick );
- }
- return (owns=res);
-}
-
-//! Swap the two unique locks that have the mutexes of same type
-template
-void swap(unique_lock& x, unique_lock