diff --git a/.Rbuildignore b/.Rbuildignore
index 2eb0e769e..7109ad47f 100644
--- a/.Rbuildignore
+++ b/.Rbuildignore
@@ -1,12 +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
+^\.Rprofile$
+^\.Rproj\.user$
+^appveyor\.yml$
+^check$
^doc$
+^gen$
+^libs$
+^inst/lib$
+^inst/libs$
+^revdep$
^src/.*\.o$
-^gen/
+^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 5381a8478..240c3f21c 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,8 +1,20 @@
+.Rprofile
.Rproj.user
.Rhistory
.RData
.DS_Store
-src-i386/
-src-x64/
-.Rprofile
+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 f604db80b..000000000
--- a/.travis.yml
+++ /dev/null
@@ -1,18 +0,0 @@
-language: cpp
-
-before_install:
- - curl -OL http://raw.github.com/craigcitro/r-travis/master/scripts/travis-tool.sh
- - chmod 755 ./travis-tool.sh
- - ./travis-tool.sh bootstrap
- - ./travis-tool.sh install_aptget r-cran-rcpp r-cran-bh r-cran-runit
-
-script:
- - R CMD INSTALL .
- - cd tests && Rscript doRUnit.R
-
-notifications:
- email:
- on_success: change
- on_failure: change
-
-
diff --git a/DESCRIPTION b/DESCRIPTION
index ab041b835..d51de8a09 100644
--- a/DESCRIPTION
+++ b/DESCRIPTION
@@ -1,35 +1,39 @@
Package: RcppParallel
Type: Package
Title: Parallel Programming Tools for 'Rcpp'
-Version: 4.3.20
+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
-LinkingTo: BH (>= 1.60.0-1)
-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
-Collate:
- 'build.R'
- 'hooks.R'
- 'options.R'
- 'skeleton.R'
+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
+RoxygenNote: 7.3.2
+Encoding: UTF-8
diff --git a/NAMESPACE b/NAMESPACE
index 182084768..94da28d51 100644
--- a/NAMESPACE
+++ b/NAMESPACE
@@ -1,8 +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 8ea8e4e8c..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
@@ -12,23 +53,33 @@ setThreadOptions <- function(numThreads = "auto", stackSize = "auto") {
# validate and resolve stackSize
if (identical(stackSize, "auto"))
- stackSize = 0L
+ stackSize <- 0L
else if (!is.numeric(stackSize))
stop("stackSize must be an integer")
else
stackSize <- as.integer(stackSize)
- # Call setThreadOptions if using tbb
- if (!is.null(dllInfo)) {
- invisible(.Call("setThreadOptions", numThreads, stackSize,
- PACKAGE = "RcppParallel"))
- }
-
- if (numThreads != -1)
+ # 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 b29fd57b5..620e6d21b 100644
--- a/README.md
+++ b/README.md
@@ -1,31 +1,63 @@
-## RcppParallel Package
-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.
+## RcppParallel
-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.
+
+[](https://cran.r-project.org/package=RcppParallel)
+[](https://github.com/RcppCore/RcppParallel/actions/workflows/R-CMD-check.yaml)
+
+
+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/.
-### License
-The RcppParallel package is made available under the [GPLv2](http://www.gnu.org/licenses/old-licenses/gpl-2.0.html).
+### 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):
-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).
+- Install [`oneTBB`](https://github.com/oneapi-src/oneTBB).
-The Intel TBB Library is licensed under the GPLv2 (as described at https://www.threadingbuildingblocks.org/Licensing):
+For example, installing [`oneTBB`](https://github.com/oneapi-src/oneTBB) on Linux 64-bit (`x86_64`) to `$HOME` directory (change if needed!):
-TBB and other open-source software available from this site is licensed under GPLv2 with the (libstdc++) runtime exception. Specifically, the TBB open-source license is the same license used by the GNU libstdc++ library in gcc 4.2.1 (and earlier). For a complete description of the license, please visit the official GNU website for [GPLv2](http://www.gnu.org/licenses/old-licenses/gpl-2.0.html) and for the [runtime exception](https://www.threadingbuildingblocks.org/licensing#runtime-exception).
+```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#?}
-**Runtime Exception**
+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"
```
-As a special exception, you may use this file as part of a free software
-library without restriction. Specifically, if other files instantiate
-templates or use macros or inline functions from this file, or you compile
-this file and link it with other files to produce an executable, this
-file does not by itself cause the resulting executable to be covered by
-the GNU General Public License. This exception does not however
-invalidate any other reasons why the executable file might be covered by
-the GNU General Public License.
+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) license.
+
+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 license, as described at https://github.com/oneapi-src/oneTBB/blob/master/LICENSE.txt.
diff --git a/RcppParallel.Rproj b/RcppParallel.Rproj
index 93cf43dd0..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
+PackageCleanBeforeInstall: No
PackageInstallArgs: --with-keep.source
PackageCheckArgs: --as-cran
+PackageRoxygenize: rd,collate,namespace
diff --git a/cleanup b/cleanup
new file mode 100755
index 000000000..ddbda5cf6
--- /dev/null
+++ b/cleanup
@@ -0,0 +1,3 @@
+#!/usr/bin/env sh
+: "${R_HOME=`R RHOME`}"
+"${R_HOME}/bin/Rscript" tools/config.R cleanup "$@"
diff --git a/cleanup.win b/cleanup.win
new file mode 100755
index 000000000..918a2f0c8
--- /dev/null
+++ b/cleanup.win
@@ -0,0 +1,2 @@
+#!/usr/bin/env sh
+"${R_HOME}/bin${R_ARCH_BIN}/Rscript.exe" tools/config.R cleanup "$@"
diff --git a/configure b/configure
new file mode 100755
index 000000000..b08715386
--- /dev/null
+++ b/configure
@@ -0,0 +1,3 @@
+#!/usr/bin/env sh
+: "${R_HOME=`R RHOME`}"
+"${R_HOME}/bin/Rscript" tools/config.R configure "$@"
diff --git a/configure.win b/configure.win
new file mode 100755
index 000000000..a47d1205c
--- /dev/null
+++ b/configure.win
@@ -0,0 +1,2 @@
+#!/usr/bin/env sh
+"${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 2484520f3..000000000
--- a/inst/NEWS
+++ /dev/null
@@ -1,39 +0,0 @@
-RcppParallel 4.3.21 (unreleased)
-------------------------------------------------------------------------
-
-* Allow setting the number of threads to use via RCPP_PARALLEL_NUM_THREADS
- environment variable.
-
-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 f4d57c01a..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(std::size_t 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 54d55b310..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,19 +107,19 @@ 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) {
-
- using namespace tthread;
-
+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);
// create threads
- std::vector threads;
+ std::vector threads;
for (std::size_t i = 0; i
-inline void ttParallelReduce(std::size_t begin, std::size_t end,
- Reducer& reducer, std::size_t grainSize = 1) {
-
- using namespace tthread;
-
+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);
// create threads (split for each thread and track the allocated workers)
- std::vector threads;
+ std::vector threads;
std::vector workers;
for (std::size_t i = 0; i 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;
- /*override*/ void apply_body() { 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 in the queue
- 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 d2015972d..000000000
--- a/inst/include/tbb/aligned_space.h
+++ /dev/null
@@ -1,47 +0,0 @@
-/*
- Copyright 2005-2014 Intel Corporation. All Rights Reserved.
-
- This file is part of Threading Building Blocks. Threading Building Blocks is free software;
- you can redistribute it and/or modify it under the terms of the GNU General Public License
- version 2 as published by the Free Software Foundation. Threading Building Blocks is
- distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the
- implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the GNU General Public License for more details. You should have received a copy of
- the GNU General Public License along with Threading Building Blocks; if not, write to the
- Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
-
- As a special exception, you may use this file as part of a free software library without
- restriction. Specifically, if other files instantiate templates or use macros or inline
- functions from this file, or you compile this file and link it with other files to produce
- an executable, this file does not by itself cause the resulting executable to be covered
- by the GNU General Public License. This exception does not however invalidate any other
- reasons why the executable file might be covered by the GNU General Public 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 45bf31740..000000000
--- a/inst/include/tbb/atomic.h
+++ /dev/null
@@ -1,556 +0,0 @@
-/*
- Copyright 2005-2014 Intel Corporation. All Rights Reserved.
-
- This file is part of Threading Building Blocks. Threading Building Blocks is free software;
- you can redistribute it and/or modify it under the terms of the GNU General Public License
- version 2 as published by the Free Software Foundation. Threading Building Blocks is
- distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the
- implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the GNU General Public License for more details. You should have received a copy of
- the GNU General Public License along with Threading Building Blocks; if not, write to the
- Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
-
- As a special exception, you may use this file as part of a free software library without
- restriction. Specifically, if other files instantiate templates or use macros or inline
- functions from this file, or you compile this file and link it with other files to produce
- an executable, this file does not by itself cause the resulting executable to be covered
- by the GNU General Public License. This exception does not however invalidate any other
- reasons why the executable file might be covered by the GNU General Public 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 defined(_MSC_VER) && !defined(__INTEL_COMPILER)
- // Workaround for overzealous compiler warnings
- #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_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 4244, 4267 are back
-
-#endif /* __TBB_atomic_H */
diff --git a/inst/include/tbb/blocked_range2d.h b/inst/include/tbb/blocked_range2d.h
deleted file mode 100644
index 230a94ae7..000000000
--- a/inst/include/tbb/blocked_range2d.h
+++ /dev/null
@@ -1,108 +0,0 @@
-/*
- Copyright 2005-2014 Intel Corporation. All Rights Reserved.
-
- This file is part of Threading Building Blocks. Threading Building Blocks is free software;
- you can redistribute it and/or modify it under the terms of the GNU General Public License
- version 2 as published by the Free Software Foundation. Threading Building Blocks is
- distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the
- implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the GNU General Public License for more details. You should have received a copy of
- the GNU General Public License along with Threading Building Blocks; if not, write to the
- Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
-
- As a special exception, you may use this file as part of a free software library without
- restriction. Specifically, if other files instantiate templates or use macros or inline
- functions from this file, or you compile this file and link it with other files to produce
- an executable, this file does not by itself cause the resulting executable to be covered
- by the GNU General Public License. This exception does not however invalidate any other
- reasons why the executable file might be covered by the GNU General Public License.
-*/
-
-#ifndef __TBB_blocked_range2d_H
-#define __TBB_blocked_range2d_H
-
-#include "tbb_stddef.h"
-#include "blocked_range.h"
-
-namespace tbb {
-
-//! A 2-dimensional range that models the Range concept.
-/** @ingroup algorithms */
-template
-class blocked_range2d {
-public:
- //! Type for size of an iteration range
- typedef blocked_range row_range_type;
- typedef blocked_range col_range_type;
-
-private:
- row_range_type my_rows;
- col_range_type my_cols;
-
-public:
-
- blocked_range2d( RowValue row_begin, RowValue row_end, typename row_range_type::size_type row_grainsize,
- ColValue col_begin, ColValue col_end, typename col_range_type::size_type col_grainsize ) :
- my_rows(row_begin,row_end,row_grainsize),
- my_cols(col_begin,col_end,col_grainsize)
- {
- }
-
- blocked_range2d( RowValue row_begin, RowValue row_end,
- ColValue col_begin, ColValue col_end ) :
- my_rows(row_begin,row_end),
- my_cols(col_begin,col_end)
- {
- }
-
- //! True if range is empty
- bool empty() const {
- // Yes, it is a logical OR here, not AND.
- return my_rows.empty() || my_cols.empty();
- }
-
- //! True if range is divisible into two pieces.
- bool is_divisible() const {
- return my_rows.is_divisible() || my_cols.is_divisible();
- }
-
- blocked_range2d( blocked_range2d& r, split ) :
- my_rows(r.my_rows),
- my_cols(r.my_cols)
- {
- split split_obj;
- do_split(r, split_obj);
- }
-
-#if __TBB_USE_PROPORTIONAL_SPLIT_IN_BLOCKED_RANGES
- //! Static field to support proportional split
- static const bool is_divisible_in_proportion = true;
-
- blocked_range2d( blocked_range2d& r, proportional_split& proportion ) :
- my_rows(r.my_rows),
- my_cols(r.my_cols)
- {
- do_split(r, proportion);
- }
-#endif /* __TBB_USE_PROPORTIONAL_SPLIT_IN_BLOCKED_RANGES */
-
- template
- void do_split( blocked_range2d& r, Split& split_obj )
- {
- if( my_rows.size()*double(my_cols.grainsize()) < my_cols.size()*double(my_rows.grainsize()) ) {
- my_cols.my_begin = col_range_type::do_split(r.my_cols, split_obj);
- } else {
- my_rows.my_begin = row_range_type::do_split(r.my_rows, split_obj);
- }
- }
-
- //! The rows of the iteration space
- const row_range_type& rows() const {return my_rows;}
-
- //! The columns of the iteration space
- const col_range_type& cols() const {return my_cols;}
-};
-
-} // namespace tbb
-
-#endif /* __TBB_blocked_range2d_H */
diff --git a/inst/include/tbb/cache_aligned_allocator.h b/inst/include/tbb/cache_aligned_allocator.h
deleted file mode 100644
index 253ef7b2e..000000000
--- a/inst/include/tbb/cache_aligned_allocator.h
+++ /dev/null
@@ -1,137 +0,0 @@
-/*
- Copyright 2005-2014 Intel Corporation. All Rights Reserved.
-
- This file is part of Threading Building Blocks. Threading Building Blocks is free software;
- you can redistribute it and/or modify it under the terms of the GNU General Public License
- version 2 as published by the Free Software Foundation. Threading Building Blocks is
- distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the
- implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the GNU General Public License for more details. You should have received a copy of
- the GNU General Public License along with Threading Building Blocks; if not, write to the
- Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
-
- As a special exception, you may use this file as part of a free software library without
- restriction. Specifically, if other files instantiate templates or use macros or inline
- functions from this file, or you compile this file and link it with other files to produce
- an executable, this file does not by itself cause the resulting executable to be covered
- by the GNU General Public License. This exception does not however invalidate any other
- reasons why the executable file might be covered by the GNU General Public 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 566606d6f..000000000
--- a/inst/include/tbb/combinable.h
+++ /dev/null
@@ -1,72 +0,0 @@
-/*
- Copyright 2005-2014 Intel Corporation. All Rights Reserved.
-
- This file is part of Threading Building Blocks. Threading Building Blocks is free software;
- you can redistribute it and/or modify it under the terms of the GNU General Public License
- version 2 as published by the Free Software Foundation. Threading Building Blocks is
- distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the
- implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the GNU General Public License for more details. You should have received a copy of
- the GNU General Public License along with Threading Building Blocks; if not, write to the
- Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
-
- As a special exception, you may use this file as part of a free software library without
- restriction. Specifically, if other files instantiate templates or use macros or inline
- functions from this file, or you compile this file and link it with other files to produce
- an executable, this file does not by itself cause the resulting executable to be covered
- by the GNU General Public License. This exception does not however invalidate any other
- reasons why the executable file might be covered by the GNU General Public 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
- combinable( finit _finit) : my_ets(_finit) { }
-
- //! destructor
- ~combinable() {
- }
-
- combinable(const combinable& other) : my_ets(other.my_ets) { }
-
- combinable & operator=( const combinable & other) { my_ets = other.my_ets; return *this; }
-
- 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 89c2ccf55..000000000
--- a/inst/include/tbb/compat/condition_variable
+++ /dev/null
@@ -1,457 +0,0 @@
-/*
- Copyright 2005-2014 Intel Corporation. All Rights Reserved.
-
- This file is part of Threading Building Blocks. Threading Building Blocks is free software;
- you can redistribute it and/or modify it under the terms of the GNU General Public License
- version 2 as published by the Free Software Foundation. Threading Building Blocks is
- distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the
- implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the GNU General Public License for more details. You should have received a copy of
- the GNU General Public License along with Threading Building Blocks; if not, write to the
- Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
-
- As a special exception, you may use this file as part of a free software library without
- restriction. Specifically, if other files instantiate templates or use macros or inline
- functions from this file, or you compile this file and link it with other files to produce
- an executable, this file does not by itself cause the resulting executable to be covered
- by the GNU General Public License. This exception does not however invalidate any other
- reasons why the executable file might be covered by the GNU General Public 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 );}
-
- //! 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& y) { x.swap( y ); }
-
-namespace internal {
-
-#if _WIN32||_WIN64
-union condvar_impl_t {
- condition_variable_using_event cv_event;
- CONDITION_VARIABLE cv_native;
-};
-void __TBB_EXPORTED_FUNC internal_initialize_condition_variable( condvar_impl_t& cv );
-void __TBB_EXPORTED_FUNC internal_destroy_condition_variable( condvar_impl_t& cv );
-void __TBB_EXPORTED_FUNC internal_condition_variable_notify_one( condvar_impl_t& cv );
-void __TBB_EXPORTED_FUNC internal_condition_variable_notify_all( condvar_impl_t& cv );
-bool __TBB_EXPORTED_FUNC internal_condition_variable_wait( condvar_impl_t& cv, mutex* mtx, const tick_count::interval_t* i = NULL );
-
-#else /* if !(_WIN32||_WIN64), i.e., POSIX threads */
-typedef pthread_cond_t condvar_impl_t;
-#endif
-
-} // namespace internal
-
-//! cv_status
-/** C++0x standard working draft 30.5 */
-enum cv_status { no_timeout, timeout };
-
-//! condition variable
-/** C++0x standard working draft 30.5.1
- @ingroup synchronization */
-class condition_variable : tbb::internal::no_copy {
-public:
- //! Constructor
- condition_variable() {
-#if _WIN32||_WIN64
- internal_initialize_condition_variable( my_cv );
-#else
- pthread_cond_init( &my_cv, NULL );
-#endif
- }
-
- //! Destructor
- ~condition_variable() {
- //precondition: There shall be no thread blocked on *this.
-#if _WIN32||_WIN64
- internal_destroy_condition_variable( my_cv );
-#else
- pthread_cond_destroy( &my_cv );
-#endif
- }
-
- //! Notify one thread and wake it up
- void notify_one() {
-#if _WIN32||_WIN64
- internal_condition_variable_notify_one( my_cv );
-#else
- pthread_cond_signal( &my_cv );
-#endif
- }
-
- //! Notify all threads
- void notify_all() {
-#if _WIN32||_WIN64
- internal_condition_variable_notify_all( my_cv );
-#else
- pthread_cond_broadcast( &my_cv );
-#endif
- }
-
- //! Release the mutex associated with the lock and wait on this condition variable
- void wait(unique_lock& lock);
-
- //! Wait on this condition variable while pred is false
- template
- void wait(unique_lock& lock, Predicate pred) {
- while( !pred() )
- wait( lock );
- }
-
- //! Timed version of wait()
- cv_status wait_for(unique_lock& lock, const tick_count::interval_t &i );
-
- //! Timed version of the predicated wait
- /** The loop terminates when pred() returns true or when the time duration specified by rel_time (i) has elapsed. */
- template
- bool wait_for(unique_lock& lock, const tick_count::interval_t &i, Predicate pred)
- {
- while( !pred() ) {
- cv_status st = wait_for( lock, i );
- if( st==timeout )
- return pred();
- }
- return true;
- }
-
- // C++0x standard working draft. 30.2.3
- typedef internal::condvar_impl_t* native_handle_type;
-
- native_handle_type native_handle() { return (native_handle_type) &my_cv; }
-
-private:
- internal::condvar_impl_t my_cv;
-};
-
-
-#if _WIN32||_WIN64
-inline void condition_variable::wait( unique_lock& lock )
-{
- __TBB_ASSERT( lock.owns, NULL );
- lock.owns = false;
- if( !internal_condition_variable_wait( my_cv, lock.mutex() ) ) {
- int ec = GetLastError();
- // on Windows 7, SleepConditionVariableCS() may return ERROR_TIMEOUT while the doc says it returns WAIT_TIMEOUT
- __TBB_ASSERT_EX( ec!=WAIT_TIMEOUT&&ec!=ERROR_TIMEOUT, NULL );
- lock.owns = true;
- throw_exception_v4( tbb::internal::eid_condvar_wait_failed );
- }
- lock.owns = true;
-}
-
-inline cv_status condition_variable::wait_for( unique_lock& lock, const tick_count::interval_t& i )
-{
- cv_status rc = no_timeout;
- __TBB_ASSERT( lock.owns, NULL );
- lock.owns = false;
- // condvar_wait could be SleepConditionVariableCS (or SleepConditionVariableSRW) or our own pre-vista cond_var_wait()
- if( !internal_condition_variable_wait( my_cv, lock.mutex(), &i ) ) {
- int ec = GetLastError();
- if( ec==WAIT_TIMEOUT || ec==ERROR_TIMEOUT )
- rc = timeout;
- else {
- lock.owns = true;
- throw_exception_v4( tbb::internal::eid_condvar_wait_failed );
- }
- }
- lock.owns = true;
- return rc;
-}
-
-#else /* !(_WIN32||_WIN64) */
-inline void condition_variable::wait( unique_lock& lock )
-{
- __TBB_ASSERT( lock.owns, NULL );
- lock.owns = false;
- if( pthread_cond_wait( &my_cv, lock.mutex()->native_handle() ) ) {
- lock.owns = true;
- throw_exception_v4( tbb::internal::eid_condvar_wait_failed );
- }
- // upon successful return, the mutex has been locked and is owned by the calling thread.
- lock.owns = true;
-}
-
-inline cv_status condition_variable::wait_for( unique_lock& lock, const tick_count::interval_t& i )
-{
-#if __linux__
- struct timespec req;
- double sec = i.seconds();
- clock_gettime( CLOCK_REALTIME, &req );
- req.tv_sec += static_cast(sec);
- req.tv_nsec += static_cast( (sec - static_cast(sec))*1e9 );
-#else /* generic Unix */
- struct timeval tv;
- struct timespec req;
- double sec = i.seconds();
- int status = gettimeofday(&tv, NULL);
- __TBB_ASSERT_EX( status==0, "gettimeofday failed" );
- req.tv_sec = tv.tv_sec + static_cast(sec);
- req.tv_nsec = tv.tv_usec*1000 + static_cast( (sec - static_cast(sec))*1e9 );
-#endif /*(choice of OS) */
- if( req.tv_nsec>=1e9 ) {
- req.tv_sec += 1;
- req.tv_nsec -= static_cast(1e9);
- }
- __TBB_ASSERT( 0<=req.tv_nsec && req.tv_nsec<1e9, NULL );
-
- int ec;
- cv_status rc = no_timeout;
- __TBB_ASSERT( lock.owns, NULL );
- lock.owns = false;
- if( ( ec=pthread_cond_timedwait( &my_cv, lock.mutex()->native_handle(), &req ) ) ) {
- if( ec==ETIMEDOUT )
- rc = timeout;
- else {
- __TBB_ASSERT( lock.try_lock()==false, NULL );
- lock.owns = true;
- throw_exception_v4( tbb::internal::eid_condvar_wait_failed );
- }
- }
- lock.owns = true;
- return rc;
-}
-#endif /* !(_WIN32||_WIN64) */
-
-} // namespace interface5
-
-__TBB_DEFINE_PROFILING_SET_NAME(interface5::condition_variable)
-
-} // namespace tbb
-
-#if TBB_IMPLEMENT_CPP0X
-
-namespace std {
-
-using tbb::interface5::defer_lock_t;
-using tbb::interface5::try_to_lock_t;
-using tbb::interface5::adopt_lock_t;
-using tbb::interface5::defer_lock;
-using tbb::interface5::try_to_lock;
-using tbb::interface5::adopt_lock;
-using tbb::interface5::lock_guard;
-using tbb::interface5::unique_lock;
-using tbb::interface5::swap; /* this is for void std::swap(unique_lock&,unique_lock&) */
-using tbb::interface5::condition_variable;
-using tbb::interface5::cv_status;
-using tbb::interface5::timeout;
-using tbb::interface5::no_timeout;
-
-} // namespace std
-
-#endif /* TBB_IMPLEMENT_CPP0X */
-
-#endif /* __TBB_condition_variable_H */
diff --git a/inst/include/tbb/compat/ppl.h b/inst/include/tbb/compat/ppl.h
deleted file mode 100644
index 9012e0acd..000000000
--- a/inst/include/tbb/compat/ppl.h
+++ /dev/null
@@ -1,62 +0,0 @@
-/*
- Copyright 2005-2014 Intel Corporation. All Rights Reserved.
-
- This file is part of Threading Building Blocks. Threading Building Blocks is free software;
- you can redistribute it and/or modify it under the terms of the GNU General Public License
- version 2 as published by the Free Software Foundation. Threading Building Blocks is
- distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the
- implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the GNU General Public License for more details. You should have received a copy of
- the GNU General Public License along with Threading Building Blocks; if not, write to the
- Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
-
- As a special exception, you may use this file as part of a free software library without
- restriction. Specifically, if other files instantiate templates or use macros or inline
- functions from this file, or you compile this file and link it with other files to produce
- an executable, this file does not by itself cause the resulting executable to be covered
- by the GNU General Public License. This exception does not however invalidate any other
- reasons why the executable file might be covered by the GNU General Public License.
-*/
-
-#ifndef __TBB_compat_ppl_H
-#define __TBB_compat_ppl_H
-
-#include "../task_group.h"
-#include "../parallel_invoke.h"
-#include "../parallel_for_each.h"
-#include "../parallel_for.h"
-#include "../tbb_exception.h"
-#include "../critical_section.h"
-#include "../reader_writer_lock.h"
-#include "../combinable.h"
-
-namespace Concurrency {
-
-#if __TBB_TASK_GROUP_CONTEXT
- using tbb::task_handle;
- using tbb::task_group_status;
- using tbb::task_group;
- using tbb::structured_task_group;
- using tbb::invalid_multiple_scheduling;
- using tbb::missing_wait;
- using tbb::make_task;
-
- using tbb::not_complete;
- using tbb::complete;
- using tbb::canceled;
-
- using tbb::is_current_task_group_canceling;
-#endif /* __TBB_TASK_GROUP_CONTEXT */
-
- using tbb::parallel_invoke;
- using tbb::strict_ppl::parallel_for;
- using tbb::parallel_for_each;
- using tbb::critical_section;
- using tbb::reader_writer_lock;
- using tbb::combinable;
-
- using tbb::improper_lock;
-
-} // namespace Concurrency
-
-#endif /* __TBB_compat_ppl_H */
diff --git a/inst/include/tbb/compat/thread b/inst/include/tbb/compat/thread
deleted file mode 100644
index 64197bfc0..000000000
--- a/inst/include/tbb/compat/thread
+++ /dev/null
@@ -1,46 +0,0 @@
-/*
- Copyright 2005-2014 Intel Corporation. All Rights Reserved.
-
- This file is part of Threading Building Blocks. Threading Building Blocks is free software;
- you can redistribute it and/or modify it under the terms of the GNU General Public License
- version 2 as published by the Free Software Foundation. Threading Building Blocks is
- distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the
- implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the GNU General Public License for more details. You should have received a copy of
- the GNU General Public License along with Threading Building Blocks; if not, write to the
- Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
-
- As a special exception, you may use this file as part of a free software library without
- restriction. Specifically, if other files instantiate templates or use macros or inline
- functions from this file, or you compile this file and link it with other files to produce
- an executable, this file does not by itself cause the resulting executable to be covered
- by the GNU General Public License. This exception does not however invalidate any other
- reasons why the executable file might be covered by the GNU General Public License.
-*/
-
-#ifndef __TBB_thread_H
-#define __TBB_thread_H
-
-#include "../tbb_thread.h"
-
-#if TBB_IMPLEMENT_CPP0X
-
-namespace std {
-
-typedef tbb::tbb_thread thread;
-
-namespace this_thread {
- using tbb::this_tbb_thread::get_id;
- using tbb::this_tbb_thread::yield;
-
- inline void sleep_for(const tbb::tick_count::interval_t& rel_time) {
- tbb::internal::thread_sleep_v3( rel_time );
- }
-
-}
-
-}
-
-#endif /* TBB_IMPLEMENT_CPP0X */
-
-#endif /* __TBB_thread_H */
diff --git a/inst/include/tbb/compat/tuple b/inst/include/tbb/compat/tuple
deleted file mode 100644
index 00b7809ca..000000000
--- a/inst/include/tbb/compat/tuple
+++ /dev/null
@@ -1,488 +0,0 @@
-/*
- Copyright 2005-2014 Intel Corporation. All Rights Reserved.
-
- This file is part of Threading Building Blocks. Threading Building Blocks is free software;
- you can redistribute it and/or modify it under the terms of the GNU General Public License
- version 2 as published by the Free Software Foundation. Threading Building Blocks is
- distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the
- implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the GNU General Public License for more details. You should have received a copy of
- the GNU General Public License along with Threading Building Blocks; if not, write to the
- Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
-
- As a special exception, you may use this file as part of a free software library without
- restriction. Specifically, if other files instantiate templates or use macros or inline
- functions from this file, or you compile this file and link it with other files to produce
- an executable, this file does not by itself cause the resulting executable to be covered
- by the GNU General Public License. This exception does not however invalidate any other
- reasons why the executable file might be covered by the GNU General Public License.
-*/
-
-#ifndef __TBB_tuple_H
-#define __TBB_tuple_H
-
-#include
-#include "../tbb_stddef.h"
-
-// build preprocessor variables for varying number of arguments
-// Need the leading comma so the empty __TBB_T_PACK will not cause a syntax error.
-#if __TBB_VARIADIC_MAX <= 5
-#define __TBB_T_PACK
-#define __TBB_U_PACK
-#define __TBB_TYPENAME_T_PACK
-#define __TBB_TYPENAME_U_PACK
-#define __TBB_NULL_TYPE_PACK
-#define __TBB_REF_T_PARAM_PACK
-#define __TBB_CONST_REF_T_PARAM_PACK
-#define __TBB_T_PARAM_LIST_PACK
-#define __TBB_CONST_NULL_REF_PACK
-//
-#elif __TBB_VARIADIC_MAX == 6
-#define __TBB_T_PACK ,__T5
-#define __TBB_U_PACK ,__U5
-#define __TBB_TYPENAME_T_PACK , typename __T5
-#define __TBB_TYPENAME_U_PACK , typename __U5
-#define __TBB_NULL_TYPE_PACK , null_type
-#define __TBB_REF_T_PARAM_PACK ,__T5& t5
-#define __TBB_CONST_REF_T_PARAM_PACK ,const __T5& t5
-#define __TBB_T_PARAM_LIST_PACK ,t5
-#define __TBB_CONST_NULL_REF_PACK , const null_type&
-//
-#elif __TBB_VARIADIC_MAX == 7
-#define __TBB_T_PACK ,__T5, __T6
-#define __TBB_U_PACK ,__U5, __U6
-#define __TBB_TYPENAME_T_PACK , typename __T5 , typename __T6
-#define __TBB_TYPENAME_U_PACK , typename __U5 , typename __U6
-#define __TBB_NULL_TYPE_PACK , null_type, null_type
-#define __TBB_REF_T_PARAM_PACK ,__T5& t5, __T6& t6
-#define __TBB_CONST_REF_T_PARAM_PACK ,const __T5& t5, const __T6& t6
-#define __TBB_T_PARAM_LIST_PACK ,t5 ,t6
-#define __TBB_CONST_NULL_REF_PACK , const null_type&, const null_type&
-//
-#elif __TBB_VARIADIC_MAX == 8
-#define __TBB_T_PACK ,__T5, __T6, __T7
-#define __TBB_U_PACK ,__U5, __U6, __U7
-#define __TBB_TYPENAME_T_PACK , typename __T5 , typename __T6, typename __T7
-#define __TBB_TYPENAME_U_PACK , typename __U5 , typename __U6, typename __U7
-#define __TBB_NULL_TYPE_PACK , null_type, null_type, null_type
-#define __TBB_REF_T_PARAM_PACK ,__T5& t5, __T6& t6, __T7& t7
-#define __TBB_CONST_REF_T_PARAM_PACK , const __T5& t5, const __T6& t6, const __T7& t7
-#define __TBB_T_PARAM_LIST_PACK ,t5 ,t6 ,t7
-#define __TBB_CONST_NULL_REF_PACK , const null_type&, const null_type&, const null_type&
-//
-#elif __TBB_VARIADIC_MAX == 9
-#define __TBB_T_PACK ,__T5, __T6, __T7, __T8
-#define __TBB_U_PACK ,__U5, __U6, __U7, __U8
-#define __TBB_TYPENAME_T_PACK , typename __T5, typename __T6, typename __T7, typename __T8
-#define __TBB_TYPENAME_U_PACK , typename __U5, typename __U6, typename __U7, typename __U8
-#define __TBB_NULL_TYPE_PACK , null_type, null_type, null_type, null_type
-#define __TBB_REF_T_PARAM_PACK ,__T5& t5, __T6& t6, __T7& t7, __T8& t8
-#define __TBB_CONST_REF_T_PARAM_PACK , const __T5& t5, const __T6& t6, const __T7& t7, const __T8& t8
-#define __TBB_T_PARAM_LIST_PACK ,t5 ,t6 ,t7 ,t8
-#define __TBB_CONST_NULL_REF_PACK , const null_type&, const null_type&, const null_type&, const null_type&
-//
-#elif __TBB_VARIADIC_MAX >= 10
-#define __TBB_T_PACK ,__T5, __T6, __T7, __T8, __T9
-#define __TBB_U_PACK ,__U5, __U6, __U7, __U8, __U9
-#define __TBB_TYPENAME_T_PACK , typename __T5, typename __T6, typename __T7, typename __T8, typename __T9
-#define __TBB_TYPENAME_U_PACK , typename __U5, typename __U6, typename __U7, typename __U8, typename __U9
-#define __TBB_NULL_TYPE_PACK , null_type, null_type, null_type, null_type, null_type
-#define __TBB_REF_T_PARAM_PACK ,__T5& t5, __T6& t6, __T7& t7, __T8& t8, __T9& t9
-#define __TBB_CONST_REF_T_PARAM_PACK , const __T5& t5, const __T6& t6, const __T7& t7, const __T8& t8, const __T9& t9
-#define __TBB_T_PARAM_LIST_PACK ,t5 ,t6 ,t7 ,t8 ,t9
-#define __TBB_CONST_NULL_REF_PACK , const null_type&, const null_type&, const null_type&, const null_type&, const null_type&
-#endif
-
-
-
-namespace tbb {
-namespace interface5 {
-
-namespace internal {
-struct null_type { };
-}
-using internal::null_type;
-
-// tuple forward declaration
-template = 6
-, typename __T5=null_type
-#if __TBB_VARIADIC_MAX >= 7
-, typename __T6=null_type
-#if __TBB_VARIADIC_MAX >= 8
-, typename __T7=null_type
-#if __TBB_VARIADIC_MAX >= 9
-, typename __T8=null_type
-#if __TBB_VARIADIC_MAX >= 10
-, typename __T9=null_type
-#endif
-#endif
-#endif
-#endif
-#endif
->
-class tuple;
-
-namespace internal {
-
-// const null_type temp
-inline const null_type cnull() { return null_type(); }
-
-// cons forward declaration
-template struct cons;
-
-// type of a component of the cons
-template
-struct component {
- typedef typename __T::tail_type next;
- typedef typename component<__N-1,next>::type type;
-};
-
-template
-struct component<0,__T> {
- typedef typename __T::head_type type;
-};
-
-template<>
-struct component<0,null_type> {
- typedef null_type type;
-};
-
-// const version of component
-
-template
-struct component<__N, const __T>
-{
- typedef typename __T::tail_type next;
- typedef const typename component<__N-1,next>::type type;
-};
-
-template
-struct component<0, const __T>
-{
- typedef const typename __T::head_type type;
-};
-
-
-// helper class for getting components of cons
-template< int __N>
-struct get_helper {
-template
-inline static typename component<__N, cons<__HT,__TT> >::type& get(cons<__HT,__TT>& ti) {
- return get_helper<__N-1>::get(ti.tail);
-}
-template
-inline static typename component<__N, cons<__HT,__TT> >::type const& get(const cons<__HT,__TT>& ti) {
- return get_helper<__N-1>::get(ti.tail);
-}
-};
-
-template<>
-struct get_helper<0> {
-template