Compare commits
3
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
6f0562a18b | ||
|
|
4a86cd6d48 | ||
|
|
1d5d04ce10 |
@@ -2,6 +2,31 @@
|
||||
The list of most significant changes made over time in
|
||||
Intel(R) Threading Building Blocks (Intel(R) TBB).
|
||||
|
||||
Intel TBB 2017 Update 5
|
||||
TBB_INTERFACE_VERSION == 9105
|
||||
|
||||
Changes (w.r.t. Intel TBB 2017 Update 4):
|
||||
|
||||
- Added support for Microsoft* Visual Studio* 2017.
|
||||
- Added graph/matmult example to demonstrate support for compute offload
|
||||
to Intel(R) Graphics Technology in the flow graph API.
|
||||
- The "compiler" build option now allows to specify a full path to the
|
||||
compiler.
|
||||
|
||||
Changes affecting backward compatibility:
|
||||
|
||||
- Constructors for many classes, including graph nodes, concurrent
|
||||
containers, thread-local containers, etc., are declared explicit and
|
||||
cannot be used for implicit conversions anymore.
|
||||
|
||||
Bugs fixed:
|
||||
|
||||
- Added a workaround for bug 16657 in the GNU C Library (glibc)
|
||||
affecting the debug version of tbb::mutex.
|
||||
- Fixed a crash in pool_identify() called for an object allocated in
|
||||
another thread.
|
||||
|
||||
------------------------------------------------------------------------
|
||||
Intel TBB 2017 Update 4
|
||||
TBB_INTERFACE_VERSION == 9104
|
||||
|
||||
@@ -2288,7 +2313,8 @@ Packaging:
|
||||
are provided separately on Intel(R) Premier.
|
||||
|
||||
------------------------------------------------------------------------
|
||||
Intel and Cilk are registered trademarks or trademarks of Intel Corporation or its
|
||||
subsidiaries in the United States and other countries.
|
||||
Intel, the Intel logo, Xeon, Intel Xeon Phi, and Cilk are registered
|
||||
trademarks or trademarks of Intel Corporation or its subsidiaries in
|
||||
the United States and other countries.
|
||||
|
||||
* Other names and brands may be claimed as the property of others.
|
||||
|
||||
@@ -1,18 +1,17 @@
|
||||
# Intel(R) Threading Building Blocks 2017 Update 4
|
||||
[] (https://github.com/01org/tbb/releases/tag/2017_U4)
|
||||
# Intel(R) Threading Building Blocks 2017 Update 5
|
||||
[](https://github.com/01org/tbb/releases/tag/2017_U5)
|
||||
[](LICENSE)
|
||||
|
||||
Intel(R) Threading Building Blocks (Intel(R) TBB) lets you easily write parallel C++ programs that take
|
||||
full advantage of multicore performance, that are portable, composable and have future-proof scalability.
|
||||
|
||||
## Release Information
|
||||
Here are the latest [Changes] (CHANGES) and [Release Notes]
|
||||
(doc/Release_Notes.txt) (contains system requirements and known issues).
|
||||
Here are the latest [Changes](CHANGES) and [Release Notes](doc/Release_Notes.txt) (contains system requirements and known issues).
|
||||
|
||||
## Documentation
|
||||
* Intel(R) TBB [tutorial] (https://software.intel.com/en-us/tbb-tutorial)
|
||||
* Intel(R) TBB general documentation: [stable] (https://software.intel.com/en-us/tbb-documentation)
|
||||
and [latest] (https://www.threadingbuildingblocks.org/docs/help/index.htm)
|
||||
* Intel(R) TBB [tutorial](https://software.intel.com/en-us/tbb-tutorial)
|
||||
* Intel(R) TBB general documentation: [stable](https://software.intel.com/en-us/tbb-documentation)
|
||||
and [latest](https://www.threadingbuildingblocks.org/docs/help/index.htm)
|
||||
|
||||
## Support
|
||||
Please report issues and suggestions via
|
||||
@@ -20,10 +19,10 @@ Please report issues and suggestions via
|
||||
[Intel(R) TBB forum](http://software.intel.com/en-us/forums/intel-threading-building-blocks/).
|
||||
|
||||
## How to Contribute
|
||||
Please, read the instructions on the official [Intel(R) TBB open source site] (https://www.threadingbuildingblocks.org/submit-contribution).
|
||||
Please, read the instructions on the official [Intel(R) TBB open source site](https://www.threadingbuildingblocks.org/submit-contribution).
|
||||
|
||||
## Engineering team contacts
|
||||
* [E-mail us.] (mailto:inteltbbdevelopers@intel.com)
|
||||
* [E-mail us.](mailto:inteltbbdevelopers@intel.com)
|
||||
|
||||
------------------------------------------------------------------------
|
||||
Intel and the Intel logo are trademarks of Intel Corporation or its subsidiaries in the U.S. and/or other countries.
|
||||
|
||||
+8
-6
@@ -100,12 +100,14 @@ $(TWICE_LINKED_TESTS): LINK_FILES+=$(@:.$(TEST_EXT)=_secondary.$(OBJ))
|
||||
test_dynamic_link%.$(TEST_EXT): LINK_TBB.LIB =
|
||||
test_dynamic_link.$(TEST_EXT): LIBS += $(LIBDL)
|
||||
|
||||
TEST_BIG_OBJ = test_opencl_node.$(TEST_EXT) test_join_node.$(TEST_EXT) test_atomic.$(TEST_EXT)
|
||||
|
||||
ifeq (windows_windows,$(tbb_os)_$(target))
|
||||
ifneq (gcc,$(compiler))
|
||||
$(TEST_BIG_OBJ): override CXXFLAGS += /bigobj
|
||||
endif
|
||||
# Resolving issue with the number of sections that an object file can contain
|
||||
ifneq (,$(BIGOBJ_KEY))
|
||||
TEST_BIGOBJ = test_opencl_node.$(TEST_EXT) \
|
||||
test_join_node.$(TEST_EXT) \
|
||||
test_atomic.$(TEST_EXT) \
|
||||
test_concurrent_unordered_set.$(TEST_EXT) \
|
||||
test_concurrent_unordered_map.$(TEST_EXT)
|
||||
$(TEST_BIGOBJ): override CXXFLAGS += $(BIGOBJ_KEY)
|
||||
endif
|
||||
|
||||
# TODO: remove repetition of .$(TEST_EXT) in the list bellow
|
||||
|
||||
+8
-8
@@ -45,7 +45,7 @@ endif
|
||||
|
||||
ifdef cpp0x
|
||||
$(warning "Warning: deprecated cpp0x=$(cpp0x) is used, stdver must be used instead. Building in stdver=c++0x mode.")
|
||||
export stdver ?= c++0x
|
||||
export stdver?=c++0x
|
||||
override cpp0x=
|
||||
endif
|
||||
|
||||
@@ -54,13 +54,13 @@ ifneq (,$(stdver))
|
||||
$(warning "Warning: unexpected stdver=$(stdver) is used.")
|
||||
endif
|
||||
|
||||
CXX_STD_FLAGS = -std=$(stdver) -D_TBB_CPP0X
|
||||
CXX_STD_FLAGS=-std=$(stdver) -D_TBB_CPP0X
|
||||
endif
|
||||
|
||||
# The requested option is added unconditionally.
|
||||
# If it is not supported, a compiler warning or error is expected.
|
||||
# Note that CXX_STD_FLAGS can be changed in <os>.<compiler>.inc.
|
||||
CXX_ONLY_FLAGS += $(CXX_STD_FLAGS)
|
||||
CXX_ONLY_FLAGS+=$(CXX_STD_FLAGS)
|
||||
|
||||
ifeq (,$(wildcard $(tbb_root)/build/$(tbb_os).inc))
|
||||
$(error "$(tbb_os)" is not supported. Add build/$(tbb_os).inc file with os-specific settings )
|
||||
@@ -100,23 +100,23 @@ cross_cfg = $(if $(crosstest),$(call flip_cfg,$(1)),$(1))
|
||||
# Setting default configuration to release
|
||||
cfg?=release
|
||||
|
||||
compiler_name=$(notdir $(compiler))
|
||||
ifdef BUILDING_PHASE
|
||||
|
||||
ifndef target
|
||||
target:=$(tbb_os)
|
||||
endif
|
||||
# process host/target compiler-dependent build configuration
|
||||
ifeq (,$(wildcard $(tbb_root)/build/$(target).$(compiler).inc))
|
||||
$(error "$(compiler)" is not supported on $(target). Add build/$(target).$(compiler).inc file with compiler-specific settings. )
|
||||
ifeq (,$(wildcard $(tbb_root)/build/$(target).$(compiler_name).inc))
|
||||
$(error "$(compiler_name)" is not supported on $(target). Add build/$(target).$(compiler_name).inc file with compiler-specific settings. )
|
||||
endif
|
||||
include $(tbb_root)/build/$(target).$(compiler).inc
|
||||
include $(tbb_root)/build/$(target).$(compiler_name).inc
|
||||
endif
|
||||
|
||||
ifneq ($(BUILDING_PHASE),1)
|
||||
# definitions for top-level Makefiles
|
||||
origin_build_dir:=$(origin tbb_build_dir)
|
||||
tbb_build_dir?=$(tbb_root)$(SLASH)build
|
||||
export tbb_build_prefix?=$(tbb_os)_$(arch)_$(compiler)_$(runtime)$(CPF_SUFFIX)
|
||||
export tbb_build_prefix?=$(tbb_os)_$(arch)_$(compiler_name)_$(runtime)$(CPF_SUFFIX)
|
||||
work_dir=$(tbb_build_dir)$(SLASH)$(tbb_build_prefix)
|
||||
endif # BUILDING_PHASE != 1
|
||||
|
||||
|
||||
+154
-147
@@ -16,166 +16,173 @@
|
||||
//
|
||||
//
|
||||
|
||||
function readAllFromFile(fname) {
|
||||
var fso = new ActiveXObject("Scripting.FileSystemObject");
|
||||
var file = null;
|
||||
try {
|
||||
file = fso.OpenTextFile(fname, 1, 0);
|
||||
return (file.readAll());
|
||||
} finally {
|
||||
// Close the file in the finally section to guarantee that it will be closed in any case
|
||||
// (if the exception is thrown or not).
|
||||
file.Close();
|
||||
}
|
||||
}
|
||||
|
||||
function doWork() {
|
||||
var WshShell = WScript.CreateObject("WScript.Shell");
|
||||
var WshShell = WScript.CreateObject("WScript.Shell");
|
||||
|
||||
var fso = new ActiveXObject("Scripting.FileSystemObject");
|
||||
var tmpExec = WshShell.Run("cmd /c echo int main(){return 0;} >detect.c", 0, true);
|
||||
|
||||
var tmpExec;
|
||||
tmpExec = WshShell.Run("cmd /c echo int main(){return 0;} >detect.c", 0, true);
|
||||
// The next block deals with GCC (MinGW)
|
||||
if (WScript.Arguments.Count() > 1) {
|
||||
var compilerPath = WScript.Arguments(1);
|
||||
// The RegExp matches everything up to and including the last slash (it uses a greedy approach.)
|
||||
var compilerName = compilerPath.replace(/^.*[\/\\]/, "");
|
||||
if (compilerName.match(/gcc/i) != null) {
|
||||
if (WScript.Arguments(0) == "/arch") {
|
||||
// Get predefined macros
|
||||
tmpExec = WshShell.Run("cmd /C " + compilerPath + " -dM -E detect.c > detect.map", 0, true);
|
||||
var defs = readAllFromFile("detect.map");
|
||||
//detect target architecture
|
||||
var intel64 = /x86_64|amd64/mgi;
|
||||
var ia32 = /i386/mgi;
|
||||
if (defs.match(intel64)) {
|
||||
WScript.Echo("intel64");
|
||||
} else if (defs.match(ia32)) {
|
||||
WScript.Echo("ia32");
|
||||
} else {
|
||||
WScript.Echo("unknown");
|
||||
}
|
||||
} else {
|
||||
tmpExec = WshShell.Exec(compilerPath + " -dumpversion");
|
||||
var gccVersion = tmpExec.StdOut.ReadLine();
|
||||
if (WScript.Arguments(0) == "/runtime") {
|
||||
WScript.Echo("mingw" + gccVersion);
|
||||
}
|
||||
else if (WScript.Arguments(0) == "/minversion") {
|
||||
// Comparing strings, not numbers; will not work for two-digit versions
|
||||
if (gccVersion >= WScript.Arguments(2)) {
|
||||
WScript.Echo("ok");
|
||||
} else {
|
||||
WScript.Echo("fail");
|
||||
}
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// The next block deals with GCC (MinGW)
|
||||
if ( WScript.Arguments.Count() > 1 && WScript.Arguments(1) == "gcc" ) {
|
||||
if ( WScript.Arguments(0) == "/arch" ) {
|
||||
// Get predefined macros
|
||||
tmpExec = WshShell.Run("cmd /C gcc -dM -E detect.c > detect.map", 0, true);
|
||||
var file = fso.OpenTextFile("detect.map", 1, 0);
|
||||
var defs = file.readAll();
|
||||
file.Close();
|
||||
//Compile binary
|
||||
tmpExec = WshShell.Exec("cl /MD detect.c /link /MAP");
|
||||
while (tmpExec.Status == 0) {
|
||||
WScript.Sleep(100);
|
||||
}
|
||||
//compiler banner that includes version and target arch was printed to stderr
|
||||
var clVersion = tmpExec.StdErr.ReadAll();
|
||||
|
||||
//detect target architecture
|
||||
var intel64=/x86_64|amd64/mgi;
|
||||
var ia32=/i386/mgi;
|
||||
if ( defs.match(intel64) ) {
|
||||
WScript.Echo( "intel64" );
|
||||
} else if ( defs.match(ia32) ) {
|
||||
WScript.Echo( "ia32" );
|
||||
} else {
|
||||
WScript.Echo( "unknown" );
|
||||
}
|
||||
} else {
|
||||
tmpExec = WshShell.Exec("gcc -dumpversion");
|
||||
var gcc_version = tmpExec.StdOut.ReadLine();
|
||||
if ( WScript.Arguments(0) == "/runtime" ) {
|
||||
WScript.Echo( "mingw"+gcc_version );
|
||||
}
|
||||
else if ( WScript.Arguments(0) == "/minversion" ) {
|
||||
// Comparing strings, not numbers; will not work for two-digit versions
|
||||
if ( gcc_version >= WScript.Arguments(2) ) {
|
||||
WScript.Echo( "ok" );
|
||||
} else {
|
||||
WScript.Echo( "fail" );
|
||||
}
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
if (WScript.Arguments(0) == "/arch") {
|
||||
//detect target architecture
|
||||
var intel64 = /AMD64|EM64T|x64/mgi;
|
||||
var ia32 = /[80|\s]x86/mgi;
|
||||
var arm = /ARM/mgi;
|
||||
if (clVersion.match(intel64)) {
|
||||
WScript.Echo("intel64");
|
||||
} else if (clVersion.match(ia32)) {
|
||||
WScript.Echo("ia32");
|
||||
} else if (clVersion.match(arm)) {
|
||||
WScript.Echo("armv7");
|
||||
} else {
|
||||
WScript.Echo("unknown");
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
//Compile binary
|
||||
tmpExec = WshShell.Exec("cl /MD detect.c /link /MAP");
|
||||
while ( tmpExec.Status == 0 ) {
|
||||
WScript.Sleep(100);
|
||||
}
|
||||
//compiler banner that includes version and target arch was printed to stderr
|
||||
var clVersion = tmpExec.StdErr.ReadAll();
|
||||
if (WScript.Arguments(0) == "/runtime") {
|
||||
//read map-file
|
||||
var mapContext = readAllFromFile("detect.map");
|
||||
//detect runtime
|
||||
var vc71 = /MSVCR71\.DLL/mgi;
|
||||
var vc80 = /MSVCR80\.DLL/mgi;
|
||||
var vc90 = /MSVCR90\.DLL/mgi;
|
||||
var vc100 = /MSVCR100\.DLL/mgi;
|
||||
var vc110 = /MSVCR110\.DLL/mgi;
|
||||
var vc120 = /MSVCR120\.DLL/mgi;
|
||||
var vc140 = /VCRUNTIME140\.DLL/mgi;
|
||||
var psdk = /MSVCRT\.DLL/mgi;
|
||||
if (mapContext.match(vc71)) {
|
||||
WScript.Echo("vc7.1");
|
||||
} else if (mapContext.match(vc80)) {
|
||||
WScript.Echo("vc8");
|
||||
} else if (mapContext.match(vc90)) {
|
||||
WScript.Echo("vc9");
|
||||
} else if (mapContext.match(vc100)) {
|
||||
WScript.Echo("vc10");
|
||||
} else if (mapContext.match(vc110)) {
|
||||
WScript.Echo("vc11");
|
||||
} else if (mapContext.match(vc120)) {
|
||||
WScript.Echo("vc12");
|
||||
} else if (mapContext.match(vc140)) {
|
||||
WScript.Echo("vc14");
|
||||
} else {
|
||||
WScript.Echo("unknown");
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
if ( WScript.Arguments(0) == "/arch" ) {
|
||||
//detect target architecture
|
||||
var intel64=/AMD64|EM64T|x64/mgi;
|
||||
var ia32=/[80|\s]x86/mgi;
|
||||
var arm=/ARM/mgi;
|
||||
if ( clVersion.match(intel64) ) {
|
||||
WScript.Echo( "intel64" );
|
||||
} else if ( clVersion.match(ia32) ) {
|
||||
WScript.Echo( "ia32" );
|
||||
} else if ( clVersion.match(arm) ) {
|
||||
WScript.Echo( "armv7" );
|
||||
} else {
|
||||
WScript.Echo( "unknown" );
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
if ( WScript.Arguments(0) == "/runtime" ) {
|
||||
//read map-file
|
||||
var map = fso.OpenTextFile("detect.map", 1, 0);
|
||||
var mapContext = map.readAll();
|
||||
map.Close();
|
||||
|
||||
//detect runtime
|
||||
var vc71=/MSVCR71\.DLL/mgi;
|
||||
var vc80=/MSVCR80\.DLL/mgi;
|
||||
var vc90=/MSVCR90\.DLL/mgi;
|
||||
var vc100=/MSVCR100\.DLL/mgi;
|
||||
var vc110=/MSVCR110\.DLL/mgi;
|
||||
var vc120=/MSVCR120\.DLL/mgi;
|
||||
var vc140=/VCRUNTIME140\.DLL/mgi;
|
||||
var psdk=/MSVCRT\.DLL/mgi;
|
||||
if ( mapContext.match(vc71) ) {
|
||||
WScript.Echo( "vc7.1" );
|
||||
} else if ( mapContext.match(vc80) ) {
|
||||
WScript.Echo( "vc8" );
|
||||
} else if ( mapContext.match(vc90) ) {
|
||||
WScript.Echo( "vc9" );
|
||||
} else if ( mapContext.match(vc100) ) {
|
||||
WScript.Echo( "vc10" );
|
||||
} else if ( mapContext.match(vc110) ) {
|
||||
WScript.Echo( "vc11" );
|
||||
} else if ( mapContext.match(vc120) ) {
|
||||
WScript.Echo( "vc12" );
|
||||
} else if ( mapContext.match(vc140) ) {
|
||||
WScript.Echo( "vc14" );
|
||||
} else {
|
||||
WScript.Echo( "unknown" );
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
if ( WScript.Arguments(0) == "/minversion" ) {
|
||||
var compiler_version;
|
||||
if ( WScript.Arguments(1) == "cl" ) {
|
||||
compiler_version = clVersion.match(/Compiler Version ([0-9.]+)\s/mi)[1];
|
||||
// compiler_version is in xx.xx.xxxxx.xx format, i.e. a string.
|
||||
// It will compare well with major.minor versions where major has two digits,
|
||||
// which is sufficient as the versions of interest start from 13 (for VC7).
|
||||
} else if ( WScript.Arguments(1) == "icl" ) {
|
||||
// Get predefined ICL macros
|
||||
tmpExec = WshShell.Run("cmd /C icl /QdM /E detect.c > detect.map", 0, true);
|
||||
var file = fso.OpenTextFile("detect.map", 1, 0);
|
||||
var defs = file.readAll();
|
||||
file.Close();
|
||||
// In #define __INTEL_COMPILER XXYY, XX is the major ICL version, YY is minor
|
||||
compiler_version = defs.match(/__INTEL_COMPILER[ \t]*([0-9]+).*$/mi)[1]/100;
|
||||
// compiler version is a number; it compares well with another major.minor
|
||||
// version number, where major has one, two, and perhaps more digits (9.1, 11, etc).
|
||||
}
|
||||
if ( compiler_version >= WScript.Arguments(2) ) {
|
||||
WScript.Echo( "ok" );
|
||||
} else {
|
||||
WScript.Echo( "fail" );
|
||||
}
|
||||
return;
|
||||
}
|
||||
if (WScript.Arguments(0) == "/minversion") {
|
||||
var compilerVersion;
|
||||
if (WScript.Arguments(1) == "cl") {
|
||||
compilerVersion = clVersion.match(/Compiler Version ([0-9.]+)\s/mi)[1];
|
||||
// compilerVersion is in xx.xx.xxxxx.xx format, i.e. a string.
|
||||
// It will compare well with major.minor versions where major has two digits,
|
||||
// which is sufficient as the versions of interest start from 13 (for VC7).
|
||||
} else if (WScript.Arguments(1) == "icl") {
|
||||
// Get predefined ICL macros
|
||||
tmpExec = WshShell.Run("cmd /C icl /QdM /E detect.c > detect.map", 0, true);
|
||||
var defs = readAllFromFile("detect.map");
|
||||
// In #define __INTEL_COMPILER XXYY, XX is the major ICL version, YY is minor
|
||||
compilerVersion = defs.match(/__INTEL_COMPILER[ \t]*([0-9]+).*$/mi)[1] / 100;
|
||||
// compiler version is a number; it compares well with another major.minor
|
||||
// version number, where major has one, two, and perhaps more digits (9.1, 11, etc).
|
||||
}
|
||||
if (compilerVersion >= WScript.Arguments(2)) {
|
||||
WScript.Echo("ok");
|
||||
} else {
|
||||
WScript.Echo("fail");
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
function doClean() {
|
||||
var fso = new ActiveXObject("Scripting.FileSystemObject");
|
||||
// delete intermediate files
|
||||
if ( fso.FileExists("detect.c") )
|
||||
fso.DeleteFile ("detect.c", false);
|
||||
if ( fso.FileExists("detect.obj") )
|
||||
fso.DeleteFile ("detect.obj", false);
|
||||
if ( fso.FileExists("detect.map") )
|
||||
fso.DeleteFile ("detect.map", false);
|
||||
if ( fso.FileExists("detect.exe") )
|
||||
fso.DeleteFile ("detect.exe", false);
|
||||
if ( fso.FileExists("detect.exe.manifest") )
|
||||
fso.DeleteFile ("detect.exe.manifest", false);
|
||||
var fso = new ActiveXObject("Scripting.FileSystemObject");
|
||||
// delete intermediate files
|
||||
if (fso.FileExists("detect.c"))
|
||||
fso.DeleteFile("detect.c", false);
|
||||
if (fso.FileExists("detect.obj"))
|
||||
fso.DeleteFile("detect.obj", false);
|
||||
if (fso.FileExists("detect.map"))
|
||||
fso.DeleteFile("detect.map", false);
|
||||
if (fso.FileExists("detect.exe"))
|
||||
fso.DeleteFile("detect.exe", false);
|
||||
if (fso.FileExists("detect.exe.manifest"))
|
||||
fso.DeleteFile("detect.exe.manifest", false);
|
||||
}
|
||||
|
||||
if ( WScript.Arguments.Count() > 0 ) {
|
||||
|
||||
try {
|
||||
doWork();
|
||||
} catch( error ) {
|
||||
WScript.Echo( "unknown" );
|
||||
}
|
||||
doClean();
|
||||
if (WScript.Arguments.Count() > 0) {
|
||||
|
||||
try {
|
||||
doWork();
|
||||
} catch (error) {
|
||||
WScript.Echo("unknown");
|
||||
}
|
||||
doClean();
|
||||
|
||||
} else {
|
||||
WScript.Echo( "Supported options:\n"
|
||||
+ "\t/arch [compiler]\n"
|
||||
+ "\t/runtime [compiler]\n"
|
||||
+ "\t/minversion compiler version" );
|
||||
WScript.Echo("Supported options:\n"
|
||||
+ "\t/arch [compiler]\n"
|
||||
+ "\t/runtime [compiler]\n"
|
||||
+ "\t/minversion compiler version");
|
||||
}
|
||||
|
||||
|
||||
@@ -33,13 +33,13 @@ ifneq (,$(stdver))
|
||||
endif
|
||||
|
||||
ifeq ($(arch), ia32)
|
||||
LIB_LINK_FLAGS += /SAFESEH
|
||||
LIB_LINK_FLAGS += /SAFESEH
|
||||
endif
|
||||
|
||||
ifeq ($(runtime), vc_mt)
|
||||
MS_CRT_KEY = /MT$(if $(findstring debug,$(cfg)),d)
|
||||
MS_CRT_KEY = /MT$(if $(findstring debug,$(cfg)),d)
|
||||
else
|
||||
MS_CRT_KEY = /MD$(if $(findstring debug,$(cfg)),d)
|
||||
MS_CRT_KEY = /MD$(if $(findstring debug,$(cfg)),d)
|
||||
endif
|
||||
EH_FLAGS = /EHsc /GR
|
||||
|
||||
@@ -71,6 +71,7 @@ DEFINE_KEY = /D
|
||||
OUTPUT_KEY = /Fe
|
||||
OUTPUTOBJ_KEY = /Fo
|
||||
WARNING_AS_ERROR_KEY = /WX
|
||||
BIGOBJ_KEY = /bigobj
|
||||
|
||||
ifeq ($(runtime),vc7.1)
|
||||
WARNING_KEY = /W3
|
||||
|
||||
@@ -65,6 +65,7 @@ DYLIB_KEY = -shared
|
||||
LIBDL =
|
||||
EXPORT_KEY = -Wl,--version-script,
|
||||
LIBS = -lpsapi
|
||||
BIGOBJ_KEY = -Wa,-mbig-obj
|
||||
|
||||
#------------------------------------------------------------------------------
|
||||
# End of compiler-specific variables
|
||||
|
||||
@@ -81,6 +81,7 @@ DYLIB_KEY = /DLL
|
||||
EXPORT_KEY = /DEF:
|
||||
NODEFAULTLIB_KEY = /Zl
|
||||
NOINTRINSIC_KEY = /Oi-
|
||||
BIGOBJ_KEY = /bigobj
|
||||
|
||||
|
||||
ifneq (,$(codecov))
|
||||
|
||||
@@ -70,7 +70,7 @@ Software - Supported Operating Systems
|
||||
Intel(R) Cluster Ready
|
||||
Red Hat* Enterprise Linux* 6, 7
|
||||
SuSE* Linux* Enterprise Server 11, 12
|
||||
Ubuntu* 12.04 LTS, 13.10, 14.04 LTS, 15.04, 16.04 LTS
|
||||
Ubuntu* 12.04 LTS, 14.04 LTS, 15.04, 16.04 LTS
|
||||
WindRiver* Linux 7
|
||||
Yocto 1.7, 1.9 (2.0), 2.1
|
||||
Systems with OS X* or macOS* operating systems
|
||||
@@ -122,8 +122,9 @@ Library Issues
|
||||
------------------------------------------------------------------------
|
||||
(C) 2017 Intel Corporation
|
||||
|
||||
Intel, the Intel logo, Intel Core, Xeon, Xeon Phi and Pentium are
|
||||
trademarks of Intel Corporation in the U.S. and/or other countries.
|
||||
Intel, the Intel logo, Intel Core, Intel Atom, Xeon, Intel Xeon Phi and
|
||||
Pentium are trademarks of Intel Corporation in the U.S. and/or other
|
||||
countries.
|
||||
|
||||
* Other names and brands may be claimed as the property of others.
|
||||
|
||||
|
||||
@@ -133,7 +133,7 @@ class </td><td class="memItemRight" valign="bottom"><b>internal::observer_l
|
||||
</table>
|
||||
</td>
|
||||
<td class="mlabels-right">
|
||||
<span class="mlabels"><span class="mlabel">inline</span></span> </td>
|
||||
<span class="mlabels"><span class="mlabel">inline</span><span class="mlabel">explicit</span></span> </td>
|
||||
</tr>
|
||||
</table>
|
||||
</div><div class="memdoc">
|
||||
@@ -160,7 +160,7 @@ class </td><td class="memItemRight" valign="bottom"><b>internal::observer_l
|
||||
</table>
|
||||
</td>
|
||||
<td class="mlabels-right">
|
||||
<span class="mlabels"><span class="mlabel">inline</span></span> </td>
|
||||
<span class="mlabels"><span class="mlabel">inline</span><span class="mlabel">explicit</span></span> </td>
|
||||
</tr>
|
||||
</table>
|
||||
</div><div class="memdoc">
|
||||
|
||||
@@ -46,7 +46,7 @@
|
||||
<table class="directory">
|
||||
<tr bgcolor="#f0f0f0" class="even"><td class="entry"><b>clear</b>() (defined in <a class="el" href="a00033.html">tbb::combinable< T ></a>)</td><td class="entry"><a class="el" href="a00033.html">tbb::combinable< T ></a></td><td class="entry"><span class="mlabel">inline</span></td></tr>
|
||||
<tr bgcolor="#f0f0f0"><td class="entry"><b>combinable</b>() (defined in <a class="el" href="a00033.html">tbb::combinable< T ></a>)</td><td class="entry"><a class="el" href="a00033.html">tbb::combinable< T ></a></td><td class="entry"><span class="mlabel">inline</span></td></tr>
|
||||
<tr bgcolor="#f0f0f0" class="even"><td class="entry"><b>combinable</b>(finit _finit) (defined in <a class="el" href="a00033.html">tbb::combinable< T ></a>)</td><td class="entry"><a class="el" href="a00033.html">tbb::combinable< T ></a></td><td class="entry"><span class="mlabel">inline</span></td></tr>
|
||||
<tr bgcolor="#f0f0f0" class="even"><td class="entry"><b>combinable</b>(finit _finit) (defined in <a class="el" href="a00033.html">tbb::combinable< T ></a>)</td><td class="entry"><a class="el" href="a00033.html">tbb::combinable< T ></a></td><td class="entry"><span class="mlabel">inline</span><span class="mlabel">explicit</span></td></tr>
|
||||
<tr bgcolor="#f0f0f0"><td class="entry"><b>combinable</b>(const combinable &other) (defined in <a class="el" href="a00033.html">tbb::combinable< T ></a>)</td><td class="entry"><a class="el" href="a00033.html">tbb::combinable< T ></a></td><td class="entry"><span class="mlabel">inline</span></td></tr>
|
||||
<tr bgcolor="#f0f0f0" class="even"><td class="entry"><b>combinable</b>(combinable &&other) (defined in <a class="el" href="a00033.html">tbb::combinable< T ></a>)</td><td class="entry"><a class="el" href="a00033.html">tbb::combinable< T ></a></td><td class="entry"><span class="mlabel">inline</span></td></tr>
|
||||
<tr bgcolor="#f0f0f0"><td class="entry"><b>combine</b>(combine_func_t f_combine) (defined in <a class="el" href="a00033.html">tbb::combinable< T ></a>)</td><td class="entry"><a class="el" href="a00033.html">tbb::combinable< T ></a></td><td class="entry"><span class="mlabel">inline</span></td></tr>
|
||||
|
||||
@@ -54,7 +54,7 @@
|
||||
<tr><td class="entry"><a class="el" href="a00158.html#ac99258407f382d84568a510075074fc7">process_item</a>()</td><td class="entry"><a class="el" href="a00158.html">tbb::thread_bound_filter</a></td><td class="entry"></td></tr>
|
||||
<tr bgcolor="#f0f0f0" class="even"><td class="entry"><b>result_type</b> enum name (defined in <a class="el" href="a00158.html">tbb::thread_bound_filter</a>)</td><td class="entry"><a class="el" href="a00158.html">tbb::thread_bound_filter</a></td><td class="entry"></td></tr>
|
||||
<tr bgcolor="#f0f0f0"><td class="entry"><b>success</b> enum value (defined in <a class="el" href="a00158.html">tbb::thread_bound_filter</a>)</td><td class="entry"><a class="el" href="a00158.html">tbb::thread_bound_filter</a></td><td class="entry"></td></tr>
|
||||
<tr bgcolor="#f0f0f0" class="even"><td class="entry"><b>thread_bound_filter</b>(mode filter_mode) (defined in <a class="el" href="a00158.html">tbb::thread_bound_filter</a>)</td><td class="entry"><a class="el" href="a00158.html">tbb::thread_bound_filter</a></td><td class="entry"><span class="mlabel">inline</span><span class="mlabel">protected</span></td></tr>
|
||||
<tr bgcolor="#f0f0f0" class="even"><td class="entry"><b>thread_bound_filter</b>(mode filter_mode) (defined in <a class="el" href="a00158.html">tbb::thread_bound_filter</a>)</td><td class="entry"><a class="el" href="a00158.html">tbb::thread_bound_filter</a></td><td class="entry"><span class="mlabel">inline</span><span class="mlabel">explicit</span><span class="mlabel">protected</span></td></tr>
|
||||
<tr><td class="entry"><a class="el" href="a00158.html#a12cfa43c620066a8783529cc8519c6f9">try_process_item</a>()</td><td class="entry"><a class="el" href="a00158.html">tbb::thread_bound_filter</a></td><td class="entry"></td></tr>
|
||||
</table></div><!-- contents -->
|
||||
<hr>
|
||||
|
||||
@@ -46,7 +46,7 @@
|
||||
<table class="directory">
|
||||
<tr bgcolor="#f0f0f0" class="even"><td class="entry"><b>built_predecessors</b>() __TBB_override (defined in <a class="el" href="a00049.html">tbb::flow::interface9::continue_receiver</a>)</td><td class="entry"><a class="el" href="a00049.html">tbb::flow::interface9::continue_receiver</a></td><td class="entry"><span class="mlabel">inline</span><span class="mlabel">virtual</span></td></tr>
|
||||
<tr bgcolor="#f0f0f0"><td class="entry"><b>built_predecessors_type</b> typedef (defined in <a class="el" href="a00049.html">tbb::flow::interface9::continue_receiver</a>)</td><td class="entry"><a class="el" href="a00049.html">tbb::flow::interface9::continue_receiver</a></td><td class="entry"></td></tr>
|
||||
<tr class="even"><td class="entry"><a class="el" href="a00049.html#a1e72842b80f083994dd44bdb53e2284b">continue_receiver</a>(int number_of_predecessors=0)</td><td class="entry"><a class="el" href="a00049.html">tbb::flow::interface9::continue_receiver</a></td><td class="entry"><span class="mlabel">inline</span></td></tr>
|
||||
<tr class="even"><td class="entry"><a class="el" href="a00049.html#a1e72842b80f083994dd44bdb53e2284b">continue_receiver</a>(int number_of_predecessors=0)</td><td class="entry"><a class="el" href="a00049.html">tbb::flow::interface9::continue_receiver</a></td><td class="entry"><span class="mlabel">inline</span><span class="mlabel">explicit</span></td></tr>
|
||||
<tr><td class="entry"><a class="el" href="a00049.html#a3483cef04880be4c4c3907936af9afae">continue_receiver</a>(const continue_receiver &src)</td><td class="entry"><a class="el" href="a00049.html">tbb::flow::interface9::continue_receiver</a></td><td class="entry"><span class="mlabel">inline</span></td></tr>
|
||||
<tr bgcolor="#f0f0f0" class="even"><td class="entry"><b>copy_predecessors</b>(predecessor_list_type &v) __TBB_override (defined in <a class="el" href="a00049.html">tbb::flow::interface9::continue_receiver</a>)</td><td class="entry"><a class="el" href="a00049.html">tbb::flow::interface9::continue_receiver</a></td><td class="entry"><span class="mlabel">inline</span><span class="mlabel">virtual</span></td></tr>
|
||||
<tr><td class="entry"><a class="el" href="a00049.html#ace97f82507453a8f3bc234d8de9f960d">execute</a>()=0</td><td class="entry"><a class="el" href="a00049.html">tbb::flow::interface9::continue_receiver</a></td><td class="entry"><span class="mlabel">protected</span><span class="mlabel">pure virtual</span></td></tr>
|
||||
|
||||
@@ -55,7 +55,7 @@
|
||||
<tr bgcolor="#f0f0f0" class="even"><td class="entry"><b>begin</b>() const (defined in <a class="el" href="a00036.html">tbb::interface5::concurrent_hash_map< Key, T, HashCompare, A ></a>)</td><td class="entry"><a class="el" href="a00036.html">tbb::interface5::concurrent_hash_map< Key, T, HashCompare, A ></a></td><td class="entry"><span class="mlabel">inline</span></td></tr>
|
||||
<tr><td class="entry"><a class="el" href="a00036.html#aa067a2a4db1d96f38555369a89deee64">bucket_count</a>() const </td><td class="entry"><a class="el" href="a00036.html">tbb::interface5::concurrent_hash_map< Key, T, HashCompare, A ></a></td><td class="entry"><span class="mlabel">inline</span></td></tr>
|
||||
<tr class="even"><td class="entry"><a class="el" href="a00036.html#ab8295bc260b5e4df883fef11574b84c6">clear</a>()</td><td class="entry"><a class="el" href="a00036.html">tbb::interface5::concurrent_hash_map< Key, T, HashCompare, A ></a></td><td class="entry"></td></tr>
|
||||
<tr><td class="entry"><a class="el" href="a00036.html#aa3a9767b525144a2afb69ed125714c53">concurrent_hash_map</a>(const allocator_type &a=allocator_type())</td><td class="entry"><a class="el" href="a00036.html">tbb::interface5::concurrent_hash_map< Key, T, HashCompare, A ></a></td><td class="entry"><span class="mlabel">inline</span></td></tr>
|
||||
<tr><td class="entry"><a class="el" href="a00036.html#aa3a9767b525144a2afb69ed125714c53">concurrent_hash_map</a>(const allocator_type &a=allocator_type())</td><td class="entry"><a class="el" href="a00036.html">tbb::interface5::concurrent_hash_map< Key, T, HashCompare, A ></a></td><td class="entry"><span class="mlabel">inline</span><span class="mlabel">explicit</span></td></tr>
|
||||
<tr class="even"><td class="entry"><a class="el" href="a00036.html#aae76e1252b56b107685f8746e0f6a1f4">concurrent_hash_map</a>(size_type n, const allocator_type &a=allocator_type())</td><td class="entry"><a class="el" href="a00036.html">tbb::interface5::concurrent_hash_map< Key, T, HashCompare, A ></a></td><td class="entry"><span class="mlabel">inline</span></td></tr>
|
||||
<tr><td class="entry"><a class="el" href="a00036.html#a8a73b86f9a5e9836b38713e56c546654">concurrent_hash_map</a>(const concurrent_hash_map &table, const allocator_type &a=allocator_type())</td><td class="entry"><a class="el" href="a00036.html">tbb::interface5::concurrent_hash_map< Key, T, HashCompare, A ></a></td><td class="entry"><span class="mlabel">inline</span></td></tr>
|
||||
<tr class="even"><td class="entry"><a class="el" href="a00036.html#a2bd04845683b15a590913a72a19fa3dc">concurrent_hash_map</a>(concurrent_hash_map &&table)</td><td class="entry"><a class="el" href="a00036.html">tbb::interface5::concurrent_hash_map< Key, T, HashCompare, A ></a></td><td class="entry"><span class="mlabel">inline</span></td></tr>
|
||||
|
||||
@@ -48,7 +48,7 @@
|
||||
<tr bgcolor="#f0f0f0"><td class="entry"><b>at</b>(const key_type &key) (defined in <a class="el" href="a00040.html">tbb::interface5::concurrent_unordered_map< Key, T, Hasher, Key_equality, Allocator ></a>)</td><td class="entry"><a class="el" href="a00040.html">tbb::interface5::concurrent_unordered_map< Key, T, Hasher, Key_equality, Allocator ></a></td><td class="entry"><span class="mlabel">inline</span></td></tr>
|
||||
<tr bgcolor="#f0f0f0" class="even"><td class="entry"><b>at</b>(const key_type &key) const (defined in <a class="el" href="a00040.html">tbb::interface5::concurrent_unordered_map< Key, T, Hasher, Key_equality, Allocator ></a>)</td><td class="entry"><a class="el" href="a00040.html">tbb::interface5::concurrent_unordered_map< Key, T, Hasher, Key_equality, Allocator ></a></td><td class="entry"><span class="mlabel">inline</span></td></tr>
|
||||
<tr bgcolor="#f0f0f0"><td class="entry"><b>concurrent_unordered_map</b>(size_type n_of_buckets=base_type::initial_bucket_number, const hasher &_Hasher=hasher(), const key_equal &_Key_equality=key_equal(), const allocator_type &a=allocator_type()) (defined in <a class="el" href="a00040.html">tbb::interface5::concurrent_unordered_map< Key, T, Hasher, Key_equality, Allocator ></a>)</td><td class="entry"><a class="el" href="a00040.html">tbb::interface5::concurrent_unordered_map< Key, T, Hasher, Key_equality, Allocator ></a></td><td class="entry"><span class="mlabel">inline</span><span class="mlabel">explicit</span></td></tr>
|
||||
<tr bgcolor="#f0f0f0" class="even"><td class="entry"><b>concurrent_unordered_map</b>(const Allocator &a) (defined in <a class="el" href="a00040.html">tbb::interface5::concurrent_unordered_map< Key, T, Hasher, Key_equality, Allocator ></a>)</td><td class="entry"><a class="el" href="a00040.html">tbb::interface5::concurrent_unordered_map< Key, T, Hasher, Key_equality, Allocator ></a></td><td class="entry"><span class="mlabel">inline</span></td></tr>
|
||||
<tr bgcolor="#f0f0f0" class="even"><td class="entry"><b>concurrent_unordered_map</b>(const Allocator &a) (defined in <a class="el" href="a00040.html">tbb::interface5::concurrent_unordered_map< Key, T, Hasher, Key_equality, Allocator ></a>)</td><td class="entry"><a class="el" href="a00040.html">tbb::interface5::concurrent_unordered_map< Key, T, Hasher, Key_equality, Allocator ></a></td><td class="entry"><span class="mlabel">inline</span><span class="mlabel">explicit</span></td></tr>
|
||||
<tr bgcolor="#f0f0f0"><td class="entry"><b>concurrent_unordered_map</b>(Iterator first, Iterator last, size_type n_of_buckets=base_type::initial_bucket_number, const hasher &_Hasher=hasher(), const key_equal &_Key_equality=key_equal(), const allocator_type &a=allocator_type()) (defined in <a class="el" href="a00040.html">tbb::interface5::concurrent_unordered_map< Key, T, Hasher, Key_equality, Allocator ></a>)</td><td class="entry"><a class="el" href="a00040.html">tbb::interface5::concurrent_unordered_map< Key, T, Hasher, Key_equality, Allocator ></a></td><td class="entry"><span class="mlabel">inline</span></td></tr>
|
||||
<tr class="even"><td class="entry"><a class="el" href="a00040.html#a788a7225915574c1a349abc0f1f653c7">concurrent_unordered_map</a>(std::initializer_list< value_type > il, size_type n_of_buckets=base_type::initial_bucket_number, const hasher &_Hasher=hasher(), const key_equal &_Key_equality=key_equal(), const allocator_type &a=allocator_type())</td><td class="entry"><a class="el" href="a00040.html">tbb::interface5::concurrent_unordered_map< Key, T, Hasher, Key_equality, Allocator ></a></td><td class="entry"><span class="mlabel">inline</span></td></tr>
|
||||
<tr bgcolor="#f0f0f0"><td class="entry"><b>concurrent_unordered_map</b>(const concurrent_unordered_map &table) (defined in <a class="el" href="a00040.html">tbb::interface5::concurrent_unordered_map< Key, T, Hasher, Key_equality, Allocator ></a>)</td><td class="entry"><a class="el" href="a00040.html">tbb::interface5::concurrent_unordered_map< Key, T, Hasher, Key_equality, Allocator ></a></td><td class="entry"><span class="mlabel">inline</span></td></tr>
|
||||
|
||||
@@ -46,7 +46,7 @@
|
||||
<table class="directory">
|
||||
<tr bgcolor="#f0f0f0" class="even"><td class="entry"><b>allocator_type</b> typedef (defined in <a class="el" href="a00042.html">tbb::interface5::concurrent_unordered_multimap< Key, T, Hasher, Key_equality, Allocator ></a>)</td><td class="entry"><a class="el" href="a00042.html">tbb::interface5::concurrent_unordered_multimap< Key, T, Hasher, Key_equality, Allocator ></a></td><td class="entry"></td></tr>
|
||||
<tr bgcolor="#f0f0f0"><td class="entry"><b>concurrent_unordered_multimap</b>(size_type n_of_buckets=base_type::initial_bucket_number, const hasher &_Hasher=hasher(), const key_equal &_Key_equality=key_equal(), const allocator_type &a=allocator_type()) (defined in <a class="el" href="a00042.html">tbb::interface5::concurrent_unordered_multimap< Key, T, Hasher, Key_equality, Allocator ></a>)</td><td class="entry"><a class="el" href="a00042.html">tbb::interface5::concurrent_unordered_multimap< Key, T, Hasher, Key_equality, Allocator ></a></td><td class="entry"><span class="mlabel">inline</span><span class="mlabel">explicit</span></td></tr>
|
||||
<tr bgcolor="#f0f0f0" class="even"><td class="entry"><b>concurrent_unordered_multimap</b>(const Allocator &a) (defined in <a class="el" href="a00042.html">tbb::interface5::concurrent_unordered_multimap< Key, T, Hasher, Key_equality, Allocator ></a>)</td><td class="entry"><a class="el" href="a00042.html">tbb::interface5::concurrent_unordered_multimap< Key, T, Hasher, Key_equality, Allocator ></a></td><td class="entry"><span class="mlabel">inline</span></td></tr>
|
||||
<tr bgcolor="#f0f0f0" class="even"><td class="entry"><b>concurrent_unordered_multimap</b>(const Allocator &a) (defined in <a class="el" href="a00042.html">tbb::interface5::concurrent_unordered_multimap< Key, T, Hasher, Key_equality, Allocator ></a>)</td><td class="entry"><a class="el" href="a00042.html">tbb::interface5::concurrent_unordered_multimap< Key, T, Hasher, Key_equality, Allocator ></a></td><td class="entry"><span class="mlabel">inline</span><span class="mlabel">explicit</span></td></tr>
|
||||
<tr bgcolor="#f0f0f0"><td class="entry"><b>concurrent_unordered_multimap</b>(Iterator first, Iterator last, size_type n_of_buckets=base_type::initial_bucket_number, const hasher &_Hasher=hasher(), const key_equal &_Key_equality=key_equal(), const allocator_type &a=allocator_type()) (defined in <a class="el" href="a00042.html">tbb::interface5::concurrent_unordered_multimap< Key, T, Hasher, Key_equality, Allocator ></a>)</td><td class="entry"><a class="el" href="a00042.html">tbb::interface5::concurrent_unordered_multimap< Key, T, Hasher, Key_equality, Allocator ></a></td><td class="entry"><span class="mlabel">inline</span></td></tr>
|
||||
<tr class="even"><td class="entry"><a class="el" href="a00042.html#a5957d29e5fa9f8c53538de3f7a41ebc9">concurrent_unordered_multimap</a>(std::initializer_list< value_type > il, size_type n_of_buckets=base_type::initial_bucket_number, const hasher &_Hasher=hasher(), const key_equal &_Key_equality=key_equal(), const allocator_type &a=allocator_type())</td><td class="entry"><a class="el" href="a00042.html">tbb::interface5::concurrent_unordered_multimap< Key, T, Hasher, Key_equality, Allocator ></a></td><td class="entry"><span class="mlabel">inline</span></td></tr>
|
||||
<tr bgcolor="#f0f0f0"><td class="entry"><b>concurrent_unordered_multimap</b>(const concurrent_unordered_multimap &table) (defined in <a class="el" href="a00042.html">tbb::interface5::concurrent_unordered_multimap< Key, T, Hasher, Key_equality, Allocator ></a>)</td><td class="entry"><a class="el" href="a00042.html">tbb::interface5::concurrent_unordered_multimap< Key, T, Hasher, Key_equality, Allocator ></a></td><td class="entry"><span class="mlabel">inline</span></td></tr>
|
||||
|
||||
@@ -46,7 +46,7 @@
|
||||
<table class="directory">
|
||||
<tr bgcolor="#f0f0f0" class="even"><td class="entry"><b>allocator_type</b> typedef (defined in <a class="el" href="a00044.html">tbb::interface5::concurrent_unordered_set< Key, Hasher, Key_equality, Allocator ></a>)</td><td class="entry"><a class="el" href="a00044.html">tbb::interface5::concurrent_unordered_set< Key, Hasher, Key_equality, Allocator ></a></td><td class="entry"></td></tr>
|
||||
<tr bgcolor="#f0f0f0"><td class="entry"><b>concurrent_unordered_set</b>(size_type n_of_buckets=base_type::initial_bucket_number, const hasher &a_hasher=hasher(), const key_equal &a_keyeq=key_equal(), const allocator_type &a=allocator_type()) (defined in <a class="el" href="a00044.html">tbb::interface5::concurrent_unordered_set< Key, Hasher, Key_equality, Allocator ></a>)</td><td class="entry"><a class="el" href="a00044.html">tbb::interface5::concurrent_unordered_set< Key, Hasher, Key_equality, Allocator ></a></td><td class="entry"><span class="mlabel">inline</span><span class="mlabel">explicit</span></td></tr>
|
||||
<tr bgcolor="#f0f0f0" class="even"><td class="entry"><b>concurrent_unordered_set</b>(const Allocator &a) (defined in <a class="el" href="a00044.html">tbb::interface5::concurrent_unordered_set< Key, Hasher, Key_equality, Allocator ></a>)</td><td class="entry"><a class="el" href="a00044.html">tbb::interface5::concurrent_unordered_set< Key, Hasher, Key_equality, Allocator ></a></td><td class="entry"><span class="mlabel">inline</span></td></tr>
|
||||
<tr bgcolor="#f0f0f0" class="even"><td class="entry"><b>concurrent_unordered_set</b>(const Allocator &a) (defined in <a class="el" href="a00044.html">tbb::interface5::concurrent_unordered_set< Key, Hasher, Key_equality, Allocator ></a>)</td><td class="entry"><a class="el" href="a00044.html">tbb::interface5::concurrent_unordered_set< Key, Hasher, Key_equality, Allocator ></a></td><td class="entry"><span class="mlabel">inline</span><span class="mlabel">explicit</span></td></tr>
|
||||
<tr bgcolor="#f0f0f0"><td class="entry"><b>concurrent_unordered_set</b>(Iterator first, Iterator last, size_type n_of_buckets=base_type::initial_bucket_number, const hasher &a_hasher=hasher(), const key_equal &a_keyeq=key_equal(), const allocator_type &a=allocator_type()) (defined in <a class="el" href="a00044.html">tbb::interface5::concurrent_unordered_set< Key, Hasher, Key_equality, Allocator ></a>)</td><td class="entry"><a class="el" href="a00044.html">tbb::interface5::concurrent_unordered_set< Key, Hasher, Key_equality, Allocator ></a></td><td class="entry"><span class="mlabel">inline</span></td></tr>
|
||||
<tr class="even"><td class="entry"><a class="el" href="a00044.html#a6f6d5ecff239ff13000848e925904fe7">concurrent_unordered_set</a>(std::initializer_list< value_type > il, size_type n_of_buckets=base_type::initial_bucket_number, const hasher &a_hasher=hasher(), const key_equal &a_keyeq=key_equal(), const allocator_type &a=allocator_type())</td><td class="entry"><a class="el" href="a00044.html">tbb::interface5::concurrent_unordered_set< Key, Hasher, Key_equality, Allocator ></a></td><td class="entry"><span class="mlabel">inline</span></td></tr>
|
||||
<tr bgcolor="#f0f0f0"><td class="entry"><b>concurrent_unordered_set</b>(const concurrent_unordered_set &table) (defined in <a class="el" href="a00044.html">tbb::interface5::concurrent_unordered_set< Key, Hasher, Key_equality, Allocator ></a>)</td><td class="entry"><a class="el" href="a00044.html">tbb::interface5::concurrent_unordered_set< Key, Hasher, Key_equality, Allocator ></a></td><td class="entry"><span class="mlabel">inline</span></td></tr>
|
||||
|
||||
@@ -46,7 +46,7 @@
|
||||
<table class="directory">
|
||||
<tr bgcolor="#f0f0f0" class="even"><td class="entry"><b>allocator_type</b> typedef (defined in <a class="el" href="a00043.html">tbb::interface5::concurrent_unordered_multiset< Key, Hasher, Key_equality, Allocator ></a>)</td><td class="entry"><a class="el" href="a00043.html">tbb::interface5::concurrent_unordered_multiset< Key, Hasher, Key_equality, Allocator ></a></td><td class="entry"></td></tr>
|
||||
<tr bgcolor="#f0f0f0"><td class="entry"><b>concurrent_unordered_multiset</b>(size_type n_of_buckets=base_type::initial_bucket_number, const hasher &_Hasher=hasher(), const key_equal &_Key_equality=key_equal(), const allocator_type &a=allocator_type()) (defined in <a class="el" href="a00043.html">tbb::interface5::concurrent_unordered_multiset< Key, Hasher, Key_equality, Allocator ></a>)</td><td class="entry"><a class="el" href="a00043.html">tbb::interface5::concurrent_unordered_multiset< Key, Hasher, Key_equality, Allocator ></a></td><td class="entry"><span class="mlabel">inline</span><span class="mlabel">explicit</span></td></tr>
|
||||
<tr bgcolor="#f0f0f0" class="even"><td class="entry"><b>concurrent_unordered_multiset</b>(const Allocator &a) (defined in <a class="el" href="a00043.html">tbb::interface5::concurrent_unordered_multiset< Key, Hasher, Key_equality, Allocator ></a>)</td><td class="entry"><a class="el" href="a00043.html">tbb::interface5::concurrent_unordered_multiset< Key, Hasher, Key_equality, Allocator ></a></td><td class="entry"><span class="mlabel">inline</span></td></tr>
|
||||
<tr bgcolor="#f0f0f0" class="even"><td class="entry"><b>concurrent_unordered_multiset</b>(const Allocator &a) (defined in <a class="el" href="a00043.html">tbb::interface5::concurrent_unordered_multiset< Key, Hasher, Key_equality, Allocator ></a>)</td><td class="entry"><a class="el" href="a00043.html">tbb::interface5::concurrent_unordered_multiset< Key, Hasher, Key_equality, Allocator ></a></td><td class="entry"><span class="mlabel">inline</span><span class="mlabel">explicit</span></td></tr>
|
||||
<tr bgcolor="#f0f0f0"><td class="entry"><b>concurrent_unordered_multiset</b>(Iterator first, Iterator last, size_type n_of_buckets=base_type::initial_bucket_number, const hasher &_Hasher=hasher(), const key_equal &_Key_equality=key_equal(), const allocator_type &a=allocator_type()) (defined in <a class="el" href="a00043.html">tbb::interface5::concurrent_unordered_multiset< Key, Hasher, Key_equality, Allocator ></a>)</td><td class="entry"><a class="el" href="a00043.html">tbb::interface5::concurrent_unordered_multiset< Key, Hasher, Key_equality, Allocator ></a></td><td class="entry"><span class="mlabel">inline</span></td></tr>
|
||||
<tr class="even"><td class="entry"><a class="el" href="a00043.html#a15631f048043195863c66bad6533bccb">concurrent_unordered_multiset</a>(std::initializer_list< value_type > il, size_type n_of_buckets=base_type::initial_bucket_number, const hasher &a_hasher=hasher(), const key_equal &a_keyeq=key_equal(), const allocator_type &a=allocator_type())</td><td class="entry"><a class="el" href="a00043.html">tbb::interface5::concurrent_unordered_multiset< Key, Hasher, Key_equality, Allocator ></a></td><td class="entry"><span class="mlabel">inline</span></td></tr>
|
||||
<tr bgcolor="#f0f0f0"><td class="entry"><b>concurrent_unordered_multiset</b>(const concurrent_unordered_multiset &table) (defined in <a class="el" href="a00043.html">tbb::interface5::concurrent_unordered_multiset< Key, Hasher, Key_equality, Allocator ></a>)</td><td class="entry"><a class="el" href="a00043.html">tbb::interface5::concurrent_unordered_multiset< Key, Hasher, Key_equality, Allocator ></a></td><td class="entry"><span class="mlabel">inline</span></td></tr>
|
||||
|
||||
@@ -60,9 +60,9 @@
|
||||
<tr><td class="entry"><a class="el" href="a00058.html#a5ed0248f10a7aa5045d2cda77dad9588">end</a>() const </td><td class="entry"><a class="el" href="a00058.html">tbb::interface6::enumerable_thread_specific< T, Allocator, ETS_key_type ></a></td><td class="entry"><span class="mlabel">inline</span></td></tr>
|
||||
<tr bgcolor="#f0f0f0" class="even"><td class="entry"><b>enumerable_thread_specific</b> (defined in <a class="el" href="a00058.html">tbb::interface6::enumerable_thread_specific< T, Allocator, ETS_key_type ></a>)</td><td class="entry"><a class="el" href="a00058.html">tbb::interface6::enumerable_thread_specific< T, Allocator, ETS_key_type ></a></td><td class="entry"><span class="mlabel">friend</span></td></tr>
|
||||
<tr><td class="entry"><a class="el" href="a00058.html#ad95ccef01367c0b6d75f6f91f5bf5315">enumerable_thread_specific</a>()</td><td class="entry"><a class="el" href="a00058.html">tbb::interface6::enumerable_thread_specific< T, Allocator, ETS_key_type ></a></td><td class="entry"><span class="mlabel">inline</span></td></tr>
|
||||
<tr class="even"><td class="entry"><a class="el" href="a00058.html#aafd6049aa255826c712aaba778524a7c">enumerable_thread_specific</a>(Finit finit)</td><td class="entry"><a class="el" href="a00058.html">tbb::interface6::enumerable_thread_specific< T, Allocator, ETS_key_type ></a></td><td class="entry"><span class="mlabel">inline</span></td></tr>
|
||||
<tr><td class="entry"><a class="el" href="a00058.html#a6f0249ee95fa56665da4b6984f3a685a">enumerable_thread_specific</a>(const T &exemplar)</td><td class="entry"><a class="el" href="a00058.html">tbb::interface6::enumerable_thread_specific< T, Allocator, ETS_key_type ></a></td><td class="entry"><span class="mlabel">inline</span></td></tr>
|
||||
<tr bgcolor="#f0f0f0" class="even"><td class="entry"><b>enumerable_thread_specific</b>(T &&exemplar) (defined in <a class="el" href="a00058.html">tbb::interface6::enumerable_thread_specific< T, Allocator, ETS_key_type ></a>)</td><td class="entry"><a class="el" href="a00058.html">tbb::interface6::enumerable_thread_specific< T, Allocator, ETS_key_type ></a></td><td class="entry"><span class="mlabel">inline</span></td></tr>
|
||||
<tr class="even"><td class="entry"><a class="el" href="a00058.html#aafd6049aa255826c712aaba778524a7c">enumerable_thread_specific</a>(Finit finit)</td><td class="entry"><a class="el" href="a00058.html">tbb::interface6::enumerable_thread_specific< T, Allocator, ETS_key_type ></a></td><td class="entry"><span class="mlabel">inline</span><span class="mlabel">explicit</span></td></tr>
|
||||
<tr><td class="entry"><a class="el" href="a00058.html#a6f0249ee95fa56665da4b6984f3a685a">enumerable_thread_specific</a>(const T &exemplar)</td><td class="entry"><a class="el" href="a00058.html">tbb::interface6::enumerable_thread_specific< T, Allocator, ETS_key_type ></a></td><td class="entry"><span class="mlabel">inline</span><span class="mlabel">explicit</span></td></tr>
|
||||
<tr bgcolor="#f0f0f0" class="even"><td class="entry"><b>enumerable_thread_specific</b>(T &&exemplar) (defined in <a class="el" href="a00058.html">tbb::interface6::enumerable_thread_specific< T, Allocator, ETS_key_type ></a>)</td><td class="entry"><a class="el" href="a00058.html">tbb::interface6::enumerable_thread_specific< T, Allocator, ETS_key_type ></a></td><td class="entry"><span class="mlabel">inline</span><span class="mlabel">explicit</span></td></tr>
|
||||
<tr><td class="entry"><a class="el" href="a00058.html#aa636348d57b1fc5127c7d642af51f6da">enumerable_thread_specific</a>(P1 &&arg1, P &&...args)</td><td class="entry"><a class="el" href="a00058.html">tbb::interface6::enumerable_thread_specific< T, Allocator, ETS_key_type ></a></td><td class="entry"><span class="mlabel">inline</span></td></tr>
|
||||
<tr bgcolor="#f0f0f0" class="even"><td class="entry"><b>enumerable_thread_specific</b>(const enumerable_thread_specific &other) (defined in <a class="el" href="a00058.html">tbb::interface6::enumerable_thread_specific< T, Allocator, ETS_key_type ></a>)</td><td class="entry"><a class="el" href="a00058.html">tbb::interface6::enumerable_thread_specific< T, Allocator, ETS_key_type ></a></td><td class="entry"><span class="mlabel">inline</span></td></tr>
|
||||
<tr bgcolor="#f0f0f0"><td class="entry"><b>enumerable_thread_specific</b>(const enumerable_thread_specific< T, Alloc, Cachetype > &other) (defined in <a class="el" href="a00058.html">tbb::interface6::enumerable_thread_specific< T, Allocator, ETS_key_type ></a>)</td><td class="entry"><a class="el" href="a00058.html">tbb::interface6::enumerable_thread_specific< T, Allocator, ETS_key_type ></a></td><td class="entry"><span class="mlabel">inline</span></td></tr>
|
||||
|
||||
@@ -54,7 +54,7 @@
|
||||
<tr bgcolor="#f0f0f0"><td class="entry"><b>end</b>() (defined in <a class="el" href="a00063.html">tbb::interface6::flattened2d< Container ></a>)</td><td class="entry"><a class="el" href="a00063.html">tbb::interface6::flattened2d< Container ></a></td><td class="entry"><span class="mlabel">inline</span></td></tr>
|
||||
<tr bgcolor="#f0f0f0" class="even"><td class="entry"><b>end</b>() const (defined in <a class="el" href="a00063.html">tbb::interface6::flattened2d< Container ></a>)</td><td class="entry"><a class="el" href="a00063.html">tbb::interface6::flattened2d< Container ></a></td><td class="entry"><span class="mlabel">inline</span></td></tr>
|
||||
<tr bgcolor="#f0f0f0"><td class="entry"><b>flattened2d</b>(const Container &c, typename Container::const_iterator b, typename Container::const_iterator e) (defined in <a class="el" href="a00063.html">tbb::interface6::flattened2d< Container ></a>)</td><td class="entry"><a class="el" href="a00063.html">tbb::interface6::flattened2d< Container ></a></td><td class="entry"><span class="mlabel">inline</span></td></tr>
|
||||
<tr bgcolor="#f0f0f0" class="even"><td class="entry"><b>flattened2d</b>(const Container &c) (defined in <a class="el" href="a00063.html">tbb::interface6::flattened2d< Container ></a>)</td><td class="entry"><a class="el" href="a00063.html">tbb::interface6::flattened2d< Container ></a></td><td class="entry"><span class="mlabel">inline</span></td></tr>
|
||||
<tr bgcolor="#f0f0f0" class="even"><td class="entry"><b>flattened2d</b>(const Container &c) (defined in <a class="el" href="a00063.html">tbb::interface6::flattened2d< Container ></a>)</td><td class="entry"><a class="el" href="a00063.html">tbb::interface6::flattened2d< Container ></a></td><td class="entry"><span class="mlabel">inline</span><span class="mlabel">explicit</span></td></tr>
|
||||
<tr bgcolor="#f0f0f0"><td class="entry"><b>iterator</b> typedef (defined in <a class="el" href="a00063.html">tbb::interface6::flattened2d< Container ></a>)</td><td class="entry"><a class="el" href="a00063.html">tbb::interface6::flattened2d< Container ></a></td><td class="entry"></td></tr>
|
||||
<tr bgcolor="#f0f0f0" class="even"><td class="entry"><b>pointer</b> typedef (defined in <a class="el" href="a00063.html">tbb::interface6::flattened2d< Container ></a>)</td><td class="entry"><a class="el" href="a00063.html">tbb::interface6::flattened2d< Container ></a></td><td class="entry"></td></tr>
|
||||
<tr bgcolor="#f0f0f0"><td class="entry"><b>reference</b> typedef (defined in <a class="el" href="a00063.html">tbb::interface6::flattened2d< Container ></a>)</td><td class="entry"><a class="el" href="a00063.html">tbb::interface6::flattened2d< Container ></a></td><td class="entry"></td></tr>
|
||||
|
||||
@@ -57,7 +57,7 @@
|
||||
<tr bgcolor="#f0f0f0" class="even"><td class="entry"><b>difference_type</b> typedef (defined in <a class="el" href="a00077.html">tbb::interface6::memory_pool_allocator< T, P ></a>)</td><td class="entry"><a class="el" href="a00077.html">tbb::interface6::memory_pool_allocator< T, P ></a></td><td class="entry"></td></tr>
|
||||
<tr><td class="entry"><a class="el" href="a00077.html#a2bded8e3fb2cec32b48771e7a1bbb838">max_size</a>() const </td><td class="entry"><a class="el" href="a00077.html">tbb::interface6::memory_pool_allocator< T, P ></a></td><td class="entry"><span class="mlabel">inline</span></td></tr>
|
||||
<tr bgcolor="#f0f0f0" class="even"><td class="entry"><b>memory_pool_allocator</b> (defined in <a class="el" href="a00077.html">tbb::interface6::memory_pool_allocator< T, P ></a>)</td><td class="entry"><a class="el" href="a00077.html">tbb::interface6::memory_pool_allocator< T, P ></a></td><td class="entry"><span class="mlabel">friend</span></td></tr>
|
||||
<tr bgcolor="#f0f0f0"><td class="entry"><b>memory_pool_allocator</b>(pool_type &pool) (defined in <a class="el" href="a00077.html">tbb::interface6::memory_pool_allocator< T, P ></a>)</td><td class="entry"><a class="el" href="a00077.html">tbb::interface6::memory_pool_allocator< T, P ></a></td><td class="entry"><span class="mlabel">inline</span></td></tr>
|
||||
<tr bgcolor="#f0f0f0"><td class="entry"><b>memory_pool_allocator</b>(pool_type &pool) (defined in <a class="el" href="a00077.html">tbb::interface6::memory_pool_allocator< T, P ></a>)</td><td class="entry"><a class="el" href="a00077.html">tbb::interface6::memory_pool_allocator< T, P ></a></td><td class="entry"><span class="mlabel">inline</span><span class="mlabel">explicit</span></td></tr>
|
||||
<tr bgcolor="#f0f0f0" class="even"><td class="entry"><b>memory_pool_allocator</b>(const memory_pool_allocator &src) (defined in <a class="el" href="a00077.html">tbb::interface6::memory_pool_allocator< T, P ></a>)</td><td class="entry"><a class="el" href="a00077.html">tbb::interface6::memory_pool_allocator< T, P ></a></td><td class="entry"><span class="mlabel">inline</span></td></tr>
|
||||
<tr bgcolor="#f0f0f0"><td class="entry"><b>memory_pool_allocator</b>(const memory_pool_allocator< U, P > &src) (defined in <a class="el" href="a00077.html">tbb::interface6::memory_pool_allocator< T, P ></a>)</td><td class="entry"><a class="el" href="a00077.html">tbb::interface6::memory_pool_allocator< T, P ></a></td><td class="entry"><span class="mlabel">inline</span></td></tr>
|
||||
<tr bgcolor="#f0f0f0" class="even"><td class="entry"><b>my_pool</b> (defined in <a class="el" href="a00077.html">tbb::interface6::memory_pool_allocator< T, P ></a>)</td><td class="entry"><a class="el" href="a00077.html">tbb::interface6::memory_pool_allocator< T, P ></a></td><td class="entry"><span class="mlabel">protected</span></td></tr>
|
||||
|
||||
@@ -46,7 +46,7 @@
|
||||
<table class="directory">
|
||||
<tr bgcolor="#f0f0f0" class="even"><td class="entry"><b>const_pointer</b> typedef (defined in <a class="el" href="a00078.html">tbb::interface6::memory_pool_allocator< void, P ></a>)</td><td class="entry"><a class="el" href="a00078.html">tbb::interface6::memory_pool_allocator< void, P ></a></td><td class="entry"></td></tr>
|
||||
<tr bgcolor="#f0f0f0"><td class="entry"><b>memory_pool_allocator</b> (defined in <a class="el" href="a00078.html">tbb::interface6::memory_pool_allocator< void, P ></a>)</td><td class="entry"><a class="el" href="a00078.html">tbb::interface6::memory_pool_allocator< void, P ></a></td><td class="entry"><span class="mlabel">friend</span></td></tr>
|
||||
<tr bgcolor="#f0f0f0" class="even"><td class="entry"><b>memory_pool_allocator</b>(pool_type &pool) (defined in <a class="el" href="a00078.html">tbb::interface6::memory_pool_allocator< void, P ></a>)</td><td class="entry"><a class="el" href="a00078.html">tbb::interface6::memory_pool_allocator< void, P ></a></td><td class="entry"><span class="mlabel">inline</span></td></tr>
|
||||
<tr bgcolor="#f0f0f0" class="even"><td class="entry"><b>memory_pool_allocator</b>(pool_type &pool) (defined in <a class="el" href="a00078.html">tbb::interface6::memory_pool_allocator< void, P ></a>)</td><td class="entry"><a class="el" href="a00078.html">tbb::interface6::memory_pool_allocator< void, P ></a></td><td class="entry"><span class="mlabel">inline</span><span class="mlabel">explicit</span></td></tr>
|
||||
<tr bgcolor="#f0f0f0"><td class="entry"><b>memory_pool_allocator</b>(const memory_pool_allocator &src) (defined in <a class="el" href="a00078.html">tbb::interface6::memory_pool_allocator< void, P ></a>)</td><td class="entry"><a class="el" href="a00078.html">tbb::interface6::memory_pool_allocator< void, P ></a></td><td class="entry"><span class="mlabel">inline</span></td></tr>
|
||||
<tr bgcolor="#f0f0f0" class="even"><td class="entry"><b>memory_pool_allocator</b>(const memory_pool_allocator< U, P > &src) (defined in <a class="el" href="a00078.html">tbb::interface6::memory_pool_allocator< void, P ></a>)</td><td class="entry"><a class="el" href="a00078.html">tbb::interface6::memory_pool_allocator< void, P ></a></td><td class="entry"><span class="mlabel">inline</span></td></tr>
|
||||
<tr bgcolor="#f0f0f0"><td class="entry"><b>my_pool</b> (defined in <a class="el" href="a00078.html">tbb::interface6::memory_pool_allocator< void, P ></a>)</td><td class="entry"><a class="el" href="a00078.html">tbb::interface6::memory_pool_allocator< void, P ></a></td><td class="entry"><span class="mlabel">protected</span></td></tr>
|
||||
|
||||
@@ -44,7 +44,7 @@
|
||||
|
||||
<p>This is the complete list of members for <a class="el" href="a00076.html">tbb::interface6::memory_pool< Alloc ></a>, including all inherited members.</p>
|
||||
<table class="directory">
|
||||
<tr class="even"><td class="entry"><a class="el" href="a00076.html#af4c36829a159eac04d630ac5a99b9354">memory_pool</a>(const Alloc &src=Alloc())</td><td class="entry"><a class="el" href="a00076.html">tbb::interface6::memory_pool< Alloc ></a></td><td class="entry"></td></tr>
|
||||
<tr class="even"><td class="entry"><a class="el" href="a00076.html#af4c36829a159eac04d630ac5a99b9354">memory_pool</a>(const Alloc &src=Alloc())</td><td class="entry"><a class="el" href="a00076.html">tbb::interface6::memory_pool< Alloc ></a></td><td class="entry"><span class="mlabel">explicit</span></td></tr>
|
||||
<tr><td class="entry"><a class="el" href="a00076.html#ad2c7645b39b7280b1b3cf393d05fbaf7">~memory_pool</a>()</td><td class="entry"><a class="el" href="a00076.html">tbb::interface6::memory_pool< Alloc ></a></td><td class="entry"><span class="mlabel">inline</span></td></tr>
|
||||
</table></div><!-- contents -->
|
||||
<hr>
|
||||
|
||||
@@ -54,8 +54,8 @@
|
||||
<tr><td class="entry"><a class="el" href="a00151.html#ad5b33790cea52c61e1fb004a8ed26365">observe</a>(bool state=true)</td><td class="entry"><a class="el" href="a00151.html">tbb::interface6::task_scheduler_observer</a></td><td class="entry"><span class="mlabel">inline</span></td></tr>
|
||||
<tr class="even"><td class="entry"><a class="el" href="a00152.html#af4282a27725fbe86052bb785bdd9c5d3">on_scheduler_entry</a>(bool)</td><td class="entry"><a class="el" href="a00152.html">tbb::internal::task_scheduler_observer_v3</a></td><td class="entry"><span class="mlabel">inline</span><span class="mlabel">virtual</span></td></tr>
|
||||
<tr><td class="entry"><a class="el" href="a00152.html#a657e90f833568e217b807d0122fa7668">on_scheduler_exit</a>(bool)</td><td class="entry"><a class="el" href="a00152.html">tbb::internal::task_scheduler_observer_v3</a></td><td class="entry"><span class="mlabel">inline</span><span class="mlabel">virtual</span></td></tr>
|
||||
<tr class="even"><td class="entry"><a class="el" href="a00151.html#a89025b1e1d42e97d6fe114c0c331f730">task_scheduler_observer</a>(bool local=false)</td><td class="entry"><a class="el" href="a00151.html">tbb::interface6::task_scheduler_observer</a></td><td class="entry"><span class="mlabel">inline</span></td></tr>
|
||||
<tr><td class="entry"><a class="el" href="a00151.html#a36e7e0c466320029d5a3e50a573e04c1">task_scheduler_observer</a>(task_arena &a)</td><td class="entry"><a class="el" href="a00151.html">tbb::interface6::task_scheduler_observer</a></td><td class="entry"><span class="mlabel">inline</span></td></tr>
|
||||
<tr class="even"><td class="entry"><a class="el" href="a00151.html#a89025b1e1d42e97d6fe114c0c331f730">task_scheduler_observer</a>(bool local=false)</td><td class="entry"><a class="el" href="a00151.html">tbb::interface6::task_scheduler_observer</a></td><td class="entry"><span class="mlabel">inline</span><span class="mlabel">explicit</span></td></tr>
|
||||
<tr><td class="entry"><a class="el" href="a00151.html#a36e7e0c466320029d5a3e50a573e04c1">task_scheduler_observer</a>(task_arena &a)</td><td class="entry"><a class="el" href="a00151.html">tbb::interface6::task_scheduler_observer</a></td><td class="entry"><span class="mlabel">inline</span><span class="mlabel">explicit</span></td></tr>
|
||||
<tr class="even"><td class="entry"><a class="el" href="a00152.html#a25bffb05efaaab36bc58590969e29745">task_scheduler_observer_v3</a>()</td><td class="entry"><a class="el" href="a00152.html">tbb::internal::task_scheduler_observer_v3</a></td><td class="entry"><span class="mlabel">inline</span></td></tr>
|
||||
<tr><td class="entry"><a class="el" href="a00151.html#a9ef3f1853439b46e5a9db7fd1c0f9116">~task_scheduler_observer</a>()</td><td class="entry"><a class="el" href="a00151.html">tbb::interface6::task_scheduler_observer</a></td><td class="entry"><span class="mlabel">inline</span><span class="mlabel">virtual</span></td></tr>
|
||||
<tr class="even"><td class="entry"><a class="el" href="a00152.html#a151e475ebba39172fcc13f43bed426cc">~task_scheduler_observer_v3</a>()</td><td class="entry"><a class="el" href="a00152.html">tbb::internal::task_scheduler_observer_v3</a></td><td class="entry"><span class="mlabel">inline</span><span class="mlabel">virtual</span></td></tr>
|
||||
|
||||
@@ -57,7 +57,7 @@
|
||||
<tr class="even"><td class="entry"><a class="el" href="a00144.html#a2977b0fba9253e6cab31570f4992c998">max_concurrency</a>() const </td><td class="entry"><a class="el" href="a00144.html">tbb::interface7::task_arena</a></td><td class="entry"><span class="mlabel">inline</span></td></tr>
|
||||
<tr><td class="entry"><a class="el" href="a00144.html#abe92eac81ca849b110de69e6efd0e5aa">task_arena</a>(int max_concurrency_=automatic, unsigned reserved_for_masters=1)</td><td class="entry"><a class="el" href="a00144.html">tbb::interface7::task_arena</a></td><td class="entry"><span class="mlabel">inline</span></td></tr>
|
||||
<tr class="even"><td class="entry"><a class="el" href="a00144.html#a70d122b3e6e4760c6053c5c230c715ef">task_arena</a>(const task_arena &s)</td><td class="entry"><a class="el" href="a00144.html">tbb::interface7::task_arena</a></td><td class="entry"><span class="mlabel">inline</span></td></tr>
|
||||
<tr><td class="entry"><a class="el" href="a00144.html#a84dfcfd70fd08d383b8d4e8b96fa4a0d">task_arena</a>(attach)</td><td class="entry"><a class="el" href="a00144.html">tbb::interface7::task_arena</a></td><td class="entry"><span class="mlabel">inline</span></td></tr>
|
||||
<tr><td class="entry"><a class="el" href="a00144.html#a84dfcfd70fd08d383b8d4e8b96fa4a0d">task_arena</a>(attach)</td><td class="entry"><a class="el" href="a00144.html">tbb::interface7::task_arena</a></td><td class="entry"><span class="mlabel">inline</span><span class="mlabel">explicit</span></td></tr>
|
||||
<tr bgcolor="#f0f0f0" class="even"><td class="entry"><b>tbb::internal::task_scheduler_observer_v3</b> (defined in <a class="el" href="a00144.html">tbb::interface7::task_arena</a>)</td><td class="entry"><a class="el" href="a00144.html">tbb::interface7::task_arena</a></td><td class="entry"><span class="mlabel">friend</span></td></tr>
|
||||
<tr bgcolor="#f0f0f0"><td class="entry"><b>tbb::this_task_arena::max_concurrency</b> (defined in <a class="el" href="a00144.html">tbb::interface7::task_arena</a>)</td><td class="entry"><a class="el" href="a00144.html">tbb::interface7::task_arena</a></td><td class="entry"><span class="mlabel">friend</span></td></tr>
|
||||
<tr class="even"><td class="entry"><a class="el" href="a00144.html#aecb3eedeacfe8469a91c17525dae7fc9">terminate</a>()</td><td class="entry"><a class="el" href="a00144.html">tbb::interface7::task_arena</a></td><td class="entry"><span class="mlabel">inline</span></td></tr>
|
||||
|
||||
@@ -43,7 +43,7 @@ namespace tbb {
|
||||
combinable() { }
|
||||
|
||||
template <typename finit>
|
||||
combinable( finit _finit) : my_ets(_finit) { }
|
||||
explicit combinable( finit _finit) : my_ets(_finit) { }
|
||||
|
||||
//! destructor
|
||||
~combinable() { }
|
||||
|
||||
@@ -766,7 +766,7 @@ public:
|
||||
};
|
||||
|
||||
//! Construct empty table.
|
||||
concurrent_hash_map( const allocator_type &a = allocator_type() )
|
||||
explicit concurrent_hash_map( const allocator_type &a = allocator_type() )
|
||||
: internal::hash_map_base(), my_allocator(a)
|
||||
{}
|
||||
|
||||
|
||||
@@ -117,7 +117,7 @@ public:
|
||||
: base_type(n_of_buckets, key_compare(_Hasher, _Key_equality), a)
|
||||
{}
|
||||
|
||||
concurrent_unordered_map(const Allocator& a) : base_type(base_type::initial_bucket_number, key_compare(), a)
|
||||
explicit concurrent_unordered_map(const Allocator& a) : base_type(base_type::initial_bucket_number, key_compare(), a)
|
||||
{}
|
||||
|
||||
template <typename Iterator>
|
||||
@@ -253,7 +253,7 @@ public:
|
||||
: base_type(n_of_buckets, key_compare(_Hasher, _Key_equality), a)
|
||||
{}
|
||||
|
||||
concurrent_unordered_multimap(const Allocator& a) : base_type(base_type::initial_bucket_number, key_compare(), a)
|
||||
explicit concurrent_unordered_multimap(const Allocator& a) : base_type(base_type::initial_bucket_number, key_compare(), a)
|
||||
{}
|
||||
|
||||
template <typename Iterator>
|
||||
|
||||
@@ -96,7 +96,7 @@ public:
|
||||
: base_type(n_of_buckets, key_compare(a_hasher, a_keyeq), a)
|
||||
{}
|
||||
|
||||
concurrent_unordered_set(const Allocator& a) : base_type(base_type::initial_bucket_number, key_compare(), a)
|
||||
explicit concurrent_unordered_set(const Allocator& a) : base_type(base_type::initial_bucket_number, key_compare(), a)
|
||||
{}
|
||||
|
||||
template <typename Iterator>
|
||||
@@ -195,7 +195,7 @@ public:
|
||||
: base_type(n_of_buckets, key_compare(_Hasher, _Key_equality), a)
|
||||
{}
|
||||
|
||||
concurrent_unordered_multiset(const Allocator& a) : base_type(base_type::initial_bucket_number, key_compare(), a)
|
||||
explicit concurrent_unordered_multiset(const Allocator& a) : base_type(base_type::initial_bucket_number, key_compare(), a)
|
||||
{}
|
||||
|
||||
template <typename Iterator>
|
||||
|
||||
@@ -859,17 +859,17 @@ namespace interface6 {
|
||||
, typename = typename internal::enable_if<internal::is_callable_no_args<typename internal::strip<Finit>::type>::value>::type
|
||||
#endif
|
||||
>
|
||||
enumerable_thread_specific( Finit finit ) : my_construct_callback(
|
||||
explicit enumerable_thread_specific( Finit finit ) : my_construct_callback(
|
||||
internal::callback_leaf<T,internal::construct_by_finit<T,Finit> >::make( tbb::internal::move(finit) )
|
||||
){}
|
||||
|
||||
//! Constructor with exemplar. Each local instance of T is copy-constructed from the exemplar.
|
||||
enumerable_thread_specific( const T& exemplar ) : my_construct_callback(
|
||||
explicit enumerable_thread_specific( const T& exemplar ) : my_construct_callback(
|
||||
internal::callback_leaf<T,internal::construct_by_exemplar<T> >::make( exemplar )
|
||||
){}
|
||||
|
||||
#if __TBB_ETS_USE_CPP11
|
||||
enumerable_thread_specific( T&& exemplar ) : my_construct_callback(
|
||||
explicit enumerable_thread_specific( T&& exemplar ) : my_construct_callback(
|
||||
internal::callback_leaf<T,internal::construct_by_exemplar<T> >::make( std::move(exemplar) )
|
||||
){}
|
||||
|
||||
@@ -1088,7 +1088,7 @@ namespace interface6 {
|
||||
flattened2d( const Container &c, typename Container::const_iterator b, typename Container::const_iterator e ) :
|
||||
my_container(const_cast<Container*>(&c)), my_begin(b), my_end(e) { }
|
||||
|
||||
flattened2d( const Container &c ) :
|
||||
explicit flattened2d( const Container &c ) :
|
||||
my_container(const_cast<Container*>(&c)), my_begin(c.begin()), my_end(c.end()) { }
|
||||
|
||||
iterator begin() { return iterator(*my_container) = my_begin; }
|
||||
|
||||
+11
-11
@@ -496,7 +496,7 @@ public:
|
||||
typedef receiver<input_type>::predecessor_type predecessor_type;
|
||||
|
||||
//! Constructor
|
||||
continue_receiver( int number_of_predecessors = 0 ) {
|
||||
explicit continue_receiver( int number_of_predecessors = 0 ) {
|
||||
my_predecessor_count = my_initial_predecessor_count = number_of_predecessors;
|
||||
my_current_count = 0;
|
||||
}
|
||||
@@ -963,7 +963,7 @@ protected:
|
||||
graph& my_graph;
|
||||
graph_node *next, *prev;
|
||||
public:
|
||||
graph_node(graph& g) : my_graph(g) {
|
||||
explicit graph_node(graph& g) : my_graph(g) {
|
||||
my_graph.register_node(this);
|
||||
}
|
||||
virtual ~graph_node() {
|
||||
@@ -1450,7 +1450,7 @@ public:
|
||||
TupleType // the tuple providing the types
|
||||
>::type output_ports_type;
|
||||
|
||||
split_node(graph &g) : graph_node(g)
|
||||
explicit split_node(graph &g) : graph_node(g)
|
||||
{
|
||||
tbb::internal::fgt_multioutput_node<N>(tbb::internal::FLOW_SPLIT_NODE, &this->my_graph,
|
||||
static_cast<receiver<input_type> *>(this), this->output_ports());
|
||||
@@ -1589,7 +1589,7 @@ public:
|
||||
typedef typename sender<output_type>::successor_list_type successor_list_type;
|
||||
#endif
|
||||
|
||||
overwrite_node(graph &g) : graph_node(g), my_buffer_is_valid(false) {
|
||||
explicit overwrite_node(graph &g) : graph_node(g), my_buffer_is_valid(false) {
|
||||
my_successors.set_owner( this );
|
||||
tbb::internal::fgt_node( tbb::internal::FLOW_OVERWRITE_NODE, &this->my_graph,
|
||||
static_cast<receiver<input_type> *>(this), static_cast<sender<output_type> *>(this) );
|
||||
@@ -1750,7 +1750,7 @@ public:
|
||||
typedef typename sender<output_type>::successor_type successor_type;
|
||||
|
||||
//! Constructor
|
||||
write_once_node(graph& g) : overwrite_node<T>(g) {
|
||||
explicit write_once_node(graph& g) : overwrite_node<T>(g) {
|
||||
tbb::internal::fgt_node( tbb::internal::FLOW_WRITE_ONCE_NODE, &(this->my_graph),
|
||||
static_cast<receiver<input_type> *>(this),
|
||||
static_cast<sender<output_type> *>(this) );
|
||||
@@ -1799,7 +1799,7 @@ private:
|
||||
#endif
|
||||
public:
|
||||
|
||||
broadcast_node(graph& g) : graph_node(g) {
|
||||
explicit broadcast_node(graph& g) : graph_node(g) {
|
||||
my_successors.set_owner( this );
|
||||
tbb::internal::fgt_node( tbb::internal::FLOW_BROADCAST_NODE, &this->my_graph,
|
||||
static_cast<receiver<input_type> *>(this), static_cast<sender<output_type> *>(this) );
|
||||
@@ -2198,7 +2198,7 @@ protected:
|
||||
|
||||
public:
|
||||
//! Constructor
|
||||
buffer_node( graph &g ) : graph_node(g), internal::reservable_item_buffer<T>(),
|
||||
explicit buffer_node( graph &g ) : graph_node(g), internal::reservable_item_buffer<T>(),
|
||||
forwarder_busy(false) {
|
||||
my_successors.set_owner(this);
|
||||
my_aggregator.initialize_handler(handler_type(this));
|
||||
@@ -2450,7 +2450,7 @@ public:
|
||||
typedef typename sender<output_type>::successor_type successor_type;
|
||||
|
||||
//! Constructor
|
||||
queue_node( graph &g ) : base_type(g) {
|
||||
explicit queue_node( graph &g ) : base_type(g) {
|
||||
tbb::internal::fgt_node( tbb::internal::FLOW_QUEUE_NODE, &(this->my_graph),
|
||||
static_cast<receiver<input_type> *>(this),
|
||||
static_cast<sender<output_type> *>(this) );
|
||||
@@ -2553,7 +2553,7 @@ public:
|
||||
typedef typename sender<output_type>::successor_type successor_type;
|
||||
|
||||
//! Constructor
|
||||
priority_queue_node( graph &g ) : buffer_node<T, A>(g), mark(0) {
|
||||
explicit priority_queue_node( graph &g ) : buffer_node<T, A>(g), mark(0) {
|
||||
tbb::internal::fgt_node( tbb::internal::FLOW_PRIORITY_QUEUE_NODE, &(this->my_graph),
|
||||
static_cast<receiver<input_type> *>(this),
|
||||
static_cast<sender<output_type> *>(this) );
|
||||
@@ -3042,7 +3042,7 @@ private:
|
||||
public:
|
||||
typedef OutputTuple output_type;
|
||||
typedef typename unfolded_type::input_ports_type input_ports_type;
|
||||
join_node(graph &g) : unfolded_type(g) {
|
||||
explicit join_node(graph &g) : unfolded_type(g) {
|
||||
tbb::internal::fgt_multiinput_node<N>( tbb::internal::FLOW_JOIN_NODE_RESERVING, &this->my_graph,
|
||||
this->input_ports(), static_cast< sender< output_type > *>(this) );
|
||||
}
|
||||
@@ -3067,7 +3067,7 @@ private:
|
||||
public:
|
||||
typedef OutputTuple output_type;
|
||||
typedef typename unfolded_type::input_ports_type input_ports_type;
|
||||
join_node(graph &g) : unfolded_type(g) {
|
||||
explicit join_node(graph &g) : unfolded_type(g) {
|
||||
tbb::internal::fgt_multiinput_node<N>( tbb::internal::FLOW_JOIN_NODE_QUEUEING, &this->my_graph,
|
||||
this->input_ports(), static_cast< sender< output_type > *>(this) );
|
||||
}
|
||||
|
||||
@@ -764,7 +764,7 @@ class concurrent_queue_iterator: public concurrent_queue_iterator_base_v3<typena
|
||||
public:
|
||||
#endif
|
||||
//! Construct iterator pointing to head of queue.
|
||||
concurrent_queue_iterator( const concurrent_queue_base_v3<Value>& queue ) :
|
||||
explicit concurrent_queue_iterator( const concurrent_queue_base_v3<typename tbb_remove_cv<Value>::type>& queue ) :
|
||||
concurrent_queue_iterator_base_v3<typename tbb_remove_cv<Value>::type>(queue)
|
||||
{
|
||||
}
|
||||
@@ -772,6 +772,8 @@ public:
|
||||
public:
|
||||
concurrent_queue_iterator() {}
|
||||
|
||||
/** If Value==Container::value_type, then this routine is the copy constructor.
|
||||
If Value==const Container::value_type, then this routine is a conversion constructor. */
|
||||
concurrent_queue_iterator( const concurrent_queue_iterator<Container,typename Container::value_type>& other ) :
|
||||
concurrent_queue_iterator_base_v3<typename tbb_remove_cv<Value>::type>(other)
|
||||
{}
|
||||
@@ -1023,7 +1025,7 @@ public:
|
||||
#endif
|
||||
|
||||
//! Construct iterator pointing to head of queue.
|
||||
concurrent_queue_iterator( const concurrent_queue_base_v3& queue ) :
|
||||
explicit concurrent_queue_iterator( const concurrent_queue_base_v3& queue ) :
|
||||
concurrent_queue_iterator_base_v3(queue,__TBB_offsetof(concurrent_queue_base_v3::padded_page<Value>,last))
|
||||
{
|
||||
}
|
||||
|
||||
@@ -83,7 +83,7 @@ static inline int32_t __TBB_machine_cmpswp4(volatile void *ptr, int32_t value, i
|
||||
"it eq\n"
|
||||
"strexeq %0, %5, [%3]\n"
|
||||
: "=&r" (res), "=&r" (oldval), "+Qo" (*(volatile int32_t*)ptr)
|
||||
: "r" ((int32_t *)ptr), "Ir" (comparand), "r" (value)
|
||||
: "r" ((volatile int32_t *)ptr), "Ir" (comparand), "r" (value)
|
||||
: "cc");
|
||||
} while (res);
|
||||
|
||||
@@ -116,7 +116,7 @@ static inline int64_t __TBB_machine_cmpswp8(volatile void *ptr, int64_t value, i
|
||||
"it eq\n"
|
||||
"strexdeq %0, %5, %H5, [%3]"
|
||||
: "=&r" (res), "=&r" (oldval), "+Qo" (*(volatile int64_t*)ptr)
|
||||
: "r" ((int64_t *)ptr), "r" (comparand), "r" (value)
|
||||
: "r" ((volatile int64_t *)ptr), "r" (comparand), "r" (value)
|
||||
: "cc");
|
||||
} while (res);
|
||||
|
||||
@@ -139,7 +139,7 @@ static inline int32_t __TBB_machine_fetchadd4(volatile void* ptr, int32_t addend
|
||||
" cmp %1, #0\n"
|
||||
" bne 1b\n"
|
||||
: "=&r" (result), "=&r" (tmp), "+Qo" (*(volatile int32_t*)ptr), "=&r"(tmp2)
|
||||
: "r" ((int32_t *)ptr), "Ir" (addend)
|
||||
: "r" ((volatile int32_t *)ptr), "Ir" (addend)
|
||||
: "cc");
|
||||
|
||||
__TBB_full_memory_fence();
|
||||
@@ -162,7 +162,7 @@ static inline int64_t __TBB_machine_fetchadd8(volatile void *ptr, int64_t addend
|
||||
" cmp %1, #0\n"
|
||||
" bne 1b"
|
||||
: "=&r" (result), "=&r" (tmp), "+Qo" (*(volatile int64_t*)ptr), "=&r"(tmp2)
|
||||
: "r" ((int64_t *)ptr), "r" (addend)
|
||||
: "r" ((volatile int64_t *)ptr), "r" (addend)
|
||||
: "cc");
|
||||
|
||||
|
||||
|
||||
@@ -107,7 +107,7 @@ public:
|
||||
typedef memory_pool_allocator<U, P> other;
|
||||
};
|
||||
|
||||
memory_pool_allocator(pool_type &pool) throw() : my_pool(&pool) {}
|
||||
explicit memory_pool_allocator(pool_type &pool) throw() : my_pool(&pool) {}
|
||||
memory_pool_allocator(const memory_pool_allocator& src) throw() : my_pool(src.my_pool) {}
|
||||
template<typename U>
|
||||
memory_pool_allocator(const memory_pool_allocator<U,P>& src) throw() : my_pool(src.my_pool) {}
|
||||
@@ -165,7 +165,7 @@ public:
|
||||
typedef memory_pool_allocator<U, P> other;
|
||||
};
|
||||
|
||||
memory_pool_allocator( pool_type &pool) throw() : my_pool(&pool) {}
|
||||
explicit memory_pool_allocator( pool_type &pool) throw() : my_pool(&pool) {}
|
||||
memory_pool_allocator( const memory_pool_allocator& src) throw() : my_pool(src.my_pool) {}
|
||||
template<typename U>
|
||||
memory_pool_allocator(const memory_pool_allocator<U,P>& src) throw() : my_pool(src.my_pool) {}
|
||||
@@ -196,7 +196,7 @@ class memory_pool : public internal::pool_base {
|
||||
|
||||
public:
|
||||
//! construct pool with underlying allocator
|
||||
memory_pool(const Alloc &src = Alloc());
|
||||
explicit memory_pool(const Alloc &src = Alloc());
|
||||
|
||||
//! destroy pool
|
||||
~memory_pool() { destroy(); } // call the callbacks first and destroy my_alloc latter
|
||||
|
||||
@@ -103,7 +103,7 @@ public:
|
||||
serial = serial_in_order
|
||||
};
|
||||
protected:
|
||||
filter( bool is_serial_ ) :
|
||||
explicit filter( bool is_serial_ ) :
|
||||
next_filter_in_pipeline(not_in_pipeline()),
|
||||
my_input_buffer(NULL),
|
||||
my_filter_mode(static_cast<unsigned char>((is_serial_ ? serial : parallel) | exact_exception_propagation)),
|
||||
@@ -112,7 +112,7 @@ protected:
|
||||
next_segment(NULL)
|
||||
{}
|
||||
|
||||
filter( mode filter_mode ) :
|
||||
explicit filter( mode filter_mode ) :
|
||||
next_filter_in_pipeline(not_in_pipeline()),
|
||||
my_input_buffer(NULL),
|
||||
my_filter_mode(static_cast<unsigned char>(filter_mode | exact_exception_propagation)),
|
||||
@@ -205,7 +205,7 @@ public:
|
||||
end_of_stream
|
||||
};
|
||||
protected:
|
||||
thread_bound_filter(mode filter_mode):
|
||||
explicit thread_bound_filter(mode filter_mode):
|
||||
filter(static_cast<mode>(filter_mode | filter::filter_is_bound))
|
||||
{
|
||||
__TBB_ASSERT(filter_mode & filter::filter_is_serial, "thread-bound filters must be serial");
|
||||
|
||||
@@ -168,7 +168,7 @@ public:
|
||||
struct attach {};
|
||||
|
||||
//! Creates an instance of task_arena attached to the current arena of the thread
|
||||
task_arena( attach )
|
||||
explicit task_arena( attach )
|
||||
: task_arena_base(automatic, 1) // use default settings if attach fails
|
||||
, my_initialized(false)
|
||||
{
|
||||
|
||||
@@ -115,7 +115,7 @@ public:
|
||||
guarantees and is not composable. Thus the current default behavior of the
|
||||
constructor is obsolete too and will be changed in one of the future versions
|
||||
of the library. **/
|
||||
task_scheduler_observer( bool local = false ) {
|
||||
explicit task_scheduler_observer( bool local = false ) {
|
||||
#if __TBB_ARENA_OBSERVER
|
||||
my_context_tag = local? implicit_tag : global_tag;
|
||||
#else
|
||||
@@ -129,7 +129,7 @@ public:
|
||||
/** entry/exit notifications are invoked whenever a thread joins/leaves arena.
|
||||
If a thread is already in the arena when the observer is activated, the entry notification
|
||||
is called before it executes the first stolen task. **/
|
||||
task_scheduler_observer( task_arena & a) {
|
||||
explicit task_scheduler_observer( task_arena & a) {
|
||||
my_context_tag = (intptr_t)&a;
|
||||
}
|
||||
#endif /* __TBB_ARENA_OBSERVER */
|
||||
|
||||
@@ -923,7 +923,7 @@ inline __TBB_Flag __TBB_LockByte( __TBB_atomic_flag& flag ) {
|
||||
#define __TBB_UnlockByte(addr) __TBB_store_with_release((addr),0)
|
||||
#endif
|
||||
|
||||
// lock primitives with TSX
|
||||
// lock primitives with Intel(R) Transactional Synchronization Extensions (Intel(R) TSX)
|
||||
#if ( __TBB_x86_32 || __TBB_x86_64 ) /* only on ia32/intel64 */
|
||||
inline void __TBB_TryLockByteElidedCancel() { __TBB_machine_try_lock_elided_cancel(); }
|
||||
|
||||
|
||||
@@ -26,7 +26,7 @@
|
||||
#define TBB_VERSION_MINOR 0
|
||||
|
||||
// Engineering-focused interface version
|
||||
#define TBB_INTERFACE_VERSION 9104
|
||||
#define TBB_INTERFACE_VERSION 9105
|
||||
#define TBB_INTERFACE_VERSION_MAJOR TBB_INTERFACE_VERSION/1000
|
||||
|
||||
// The oldest major interface version still supported
|
||||
|
||||
+5
-1
@@ -19,14 +19,18 @@
|
||||
all: release test
|
||||
|
||||
clean:
|
||||
$(MAKE) -rf rml/Makefile tbb_root=.. clean
|
||||
python setup.py clean
|
||||
-rm -rf build/ tbb_wrap.* _TBB.* *.pyc TBB.py*
|
||||
|
||||
release: TBB.py
|
||||
release: rml_release TBB.py
|
||||
|
||||
TBB.py: tbb.i tbb.src.py setup.py
|
||||
python setup.py build_ext -f --inplace
|
||||
|
||||
ipc-rml:
|
||||
$(MAKE) -rf rml/Makefile tbb_root=.. rml_dll cfg=release
|
||||
|
||||
test: TBB.py
|
||||
python TBB.py test
|
||||
|
||||
|
||||
@@ -0,0 +1,24 @@
|
||||
#!/usr/bin/env python
|
||||
#
|
||||
# Copyright (c) 2005-2017 Intel Corporation
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
|
||||
from tbb import *
|
||||
from tbb import __all__, __doc__
|
||||
|
||||
if __name__ == "__main__":
|
||||
from tbb import _main
|
||||
import sys
|
||||
sys.exit(_main())
|
||||
+28
-11
@@ -4,10 +4,10 @@
|
||||
</H2>
|
||||
|
||||
<H2>Overview</H2>
|
||||
It is a preview Python* module which unlocks opportunities for additional performance in multi-threaded Python programs by enabling threading composability
|
||||
It is a preview Python* module which unlocks opportunities for additional performance in multi-threaded and multiprocess Python programs by enabling threading composability
|
||||
between two or more thread-enabled libraries like Numpy, Scipy, Sklearn, Dask, Joblib, and etc.
|
||||
<p></p>
|
||||
The biggest improvement can be achieved when a task pool like the ThreadPool from the Python standard library or libraries like Dask or Joblib (used in multi-threading mode)
|
||||
The biggest improvement can be achieved when a task pool like the ThreadPool or Pool from the Python standard library or libraries like Dask or Joblib (used either in multi-threading or multi-processing mode)
|
||||
execute tasks calling compute-intensive functions of Numpy/Scipy/Sklearn/PyDAAL which in turn are parallelized using Intel® Math Kernel Library or/and Intel® TBB.
|
||||
<p></p>
|
||||
The module implements Pool class with the standard interface using Intel® TBB which can be used to replace Python's ThreadPool.
|
||||
@@ -15,20 +15,32 @@ Thanks to the monkey-patching technique implemented in class Monkey, no source c
|
||||
<p></p>
|
||||
For more information and examples, please refer to <A HREF="http://software.intel.com/en-us/blogs/2016/04/04/unleash-parallel-performance-of-python-programs">online blog</A>.
|
||||
|
||||
<H2>Directories</H2>
|
||||
<DL>
|
||||
<DT><A HREF="rml">rml</A>
|
||||
<DD>The folder contains needed sources to build the plugin with cross-process dynamic thread scheduler implementation.
|
||||
<DT><A HREF="tbb">tbb</A>
|
||||
<DD>The folder contains Python module sources.
|
||||
</DL>
|
||||
|
||||
<H2>Files</H2>
|
||||
<DL>
|
||||
<DT><A HREF="setup.py">setup.py</A>
|
||||
<DD>Standard Python setup script.
|
||||
<DT><A HREF="Makefile">Makefile</A>
|
||||
<DD>Makefile for building, installing, and testing. See below.
|
||||
<DT><A HREF="tbb.i">tbb.i</A>
|
||||
<DD>SWIG interface description file.
|
||||
<DT><A HREF="tbb.src.py">tbb.src.py</A>
|
||||
<DD>Python part of module implementation.
|
||||
<DT><A HREF="TBB.py">TBB.py</A>
|
||||
<DD>Alternative entry point for Python module.
|
||||
</DL>
|
||||
|
||||
<A NAME=build><H2>Build and install</H2></A>
|
||||
Prior to building it, please set up the environment using corresponding tbbvars script, e.g. `source tbbvars.sh intel64`
|
||||
Prior to building it, please do the following first:
|
||||
<UL>
|
||||
<LI>Download this source package;</LI>
|
||||
<LI>Build Intel® TBB (for more informantion, please refer to <A HREF="../index.html">documentation</A>);</LI>
|
||||
<LI>Set up the environment using generated tbbvars.sh script that can be found in $TBBROOT/build/*_release/ or $TBBROOT/build/*_debug/ folders.</LI>
|
||||
|
||||
</UL>
|
||||
<DL>
|
||||
<DT><TT>make</TT>
|
||||
<DD>Default build and run. Equivalent to 'make release test'.
|
||||
@@ -48,10 +60,15 @@ Please note, CXX=icl works on Windows only with Intel® Distribution for Pyth
|
||||
|
||||
<H2>Command-line interface</H2>
|
||||
<DL>
|
||||
<DT><TT>pydoc TBB</TT>
|
||||
<DD>Read built-in documentation for Python interfaces.
|
||||
<DT><TT>python -m TBB your_script.py</TT>
|
||||
<DD>Run your_script.py in context of `with TBB.Monkey():` when Intel TBB is enabled.
|
||||
<DT><TT>python -m tbb -h</TT>
|
||||
<DD>Print documentation on command-line interface</DD>
|
||||
<DT><TT>pydoc tbb</TT>
|
||||
<DD>Read built-in documentation for Python interfaces.</DD>
|
||||
<DT><TT>python-tbb your_script.py</TT>
|
||||
<DT><TT>python -m tbb your_script.py</TT>
|
||||
<DD>Run your_script.py in context of `with tbb.Monkey():` when Intel® TBB is enabled. By default only multi-threading will be covered.</DD>
|
||||
<DT><TT>python -m tbb --ipc your_script.py</TT>
|
||||
<DD>Run your_script.py in context of `with tbb.Monkey():` when Intel® TBB enabled in both multi-threading and multi-processing modes.</DD>
|
||||
</DL>
|
||||
|
||||
<H2>System Requirements</H2>
|
||||
|
||||
@@ -0,0 +1,151 @@
|
||||
# Copyright (c) 2005-2017 Intel Corporation
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
#
|
||||
#
|
||||
#
|
||||
#
|
||||
|
||||
|
||||
.NOTPARALLEL:
|
||||
|
||||
tbb_root ?= ../..
|
||||
BUILDING_PHASE=0
|
||||
TEST_RESOURCE = $(RML.RES)
|
||||
include $(tbb_root)/build/common.inc
|
||||
DEBUG_SUFFIX=$(findstring _debug,_$(cfg))
|
||||
|
||||
ifeq (android,$(target))
|
||||
$(error "RML is not supported on Android")
|
||||
endif
|
||||
|
||||
.PHONY: default_rml rml rml_test clean
|
||||
|
||||
# default target
|
||||
default_rml: rml rml_test
|
||||
|
||||
RML_ROOT ?= $(tbb_root)/src/rml
|
||||
RML_SERVER_ROOT = $(RML_ROOT)/server
|
||||
# TODO: new API needs to be added for this server, exposing everything
|
||||
RML.DEF =
|
||||
|
||||
VPATH = $(tbb_root)/src/tbb $(tbb_root)/src/tbb/$(ASSEMBLY_SOURCE)
|
||||
VPATH += $(tbb_root)/python/rml $(RML_ROOT)/test $(tbb_root)/src/test
|
||||
|
||||
include $(tbb_root)/build/common_rules.inc
|
||||
|
||||
#--------------------------------------------------------------------------
|
||||
# Define rules for making the RML server shared library and client objects.
|
||||
#--------------------------------------------------------------------------
|
||||
|
||||
# Object files that make up RML server
|
||||
RML_SERVER.OBJ = ipc_server.$(OBJ)
|
||||
|
||||
# Object files that RML clients need
|
||||
RML_TBB_CLIENT.OBJ ?= ipc_utils.$(OBJ)
|
||||
RML.OBJ = $(RML_SERVER.OBJ) $(RML_TBB_CLIENT.OBJ)
|
||||
ifeq (windows,$(tbb_os))
|
||||
RML_ASM.OBJ = $(if $(findstring intel64,$(arch)),$(TBB_ASM.OBJ))
|
||||
endif
|
||||
ifeq (linux,$(tbb_os))
|
||||
RML_ASM.OBJ = $(if $(findstring ia64,$(arch)),$(TBB_ASM.OBJ))
|
||||
endif
|
||||
|
||||
RML_TBB_DEP= cache_aligned_allocator_rml.$(OBJ) dynamic_link_rml.$(OBJ) tbb_misc_rml.$(OBJ) tbb_misc_ex_rml.$(OBJ)
|
||||
TBB_DEP_NON_RML_TEST?= cache_aligned_allocator_rml.$(OBJ) dynamic_link_rml.$(OBJ) $(RML_ASM.OBJ) tbb_misc_rml.$(OBJ) tbb_misc_ex_rml.$(OBJ)
|
||||
ifeq ($(cfg),debug)
|
||||
RML_TBB_DEP+= spin_mutex_rml.$(OBJ)
|
||||
TBB_DEP_RML_TEST?= $(RML_ASM.OBJ) tbb_misc_rml.$(OBJ)
|
||||
else
|
||||
TBB_DEP_RML_TEST?= $(RML_ASM.OBJ)
|
||||
endif
|
||||
LIBS += $(LIBDL)
|
||||
|
||||
INCLUDES += $(INCLUDE_KEY)$(RML_ROOT)/include $(INCLUDE_KEY).
|
||||
T_INCLUDES = $(INCLUDES) $(INCLUDE_KEY)$(tbb_root)/src/test $(INCLUDE_KEY)$(RML_SERVER_ROOT)
|
||||
|
||||
# Suppress superfluous warnings for RML compilation
|
||||
R_CPLUS_FLAGS = $(subst DO_ITT_NOTIFY,DO_ITT_NOTIFY=0,$(CPLUS_FLAGS)) $(WARNING_SUPPRESS) \
|
||||
$(DEFINE_KEY)TBB_USE_THREADING_TOOLS=0 $(DEFINE_KEY)__TBB_RML_STATIC=1 $(DEFINE_KEY)__TBB_NO_IMPLICIT_LINKAGE=1
|
||||
|
||||
%.$(OBJ): %.cpp
|
||||
$(CPLUS) $(COMPILE_ONLY) $(R_CPLUS_FLAGS) $(PIC_KEY) $(DSE_KEY) $(INCLUDES) $<
|
||||
|
||||
tbb_misc_rml.$(OBJ) $(RML_SERVER.OBJ): version_string.ver
|
||||
|
||||
RML_TEST.OBJ = test_job_automaton.$(OBJ) test_thread_monitor.$(OBJ) test_rml_tbb.$(OBJ)
|
||||
|
||||
$(RML_TBB_DEP): %_rml.$(OBJ): %.cpp
|
||||
$(CPLUS) $(COMPILE_ONLY) $(OUTPUTOBJ_KEY)$@ $(R_CPLUS_FLAGS) $(PIC_KEY) $(DSE_KEY) $(INCLUDES) $<
|
||||
|
||||
$(RML_TEST.OBJ): %.$(OBJ): %.cpp
|
||||
$(CPLUS) $(COMPILE_ONLY) $(R_CPLUS_FLAGS) $(PIC_KEY) $(T_INCLUDES) $<
|
||||
|
||||
ifneq (,$(RML.DEF))
|
||||
rml.def: $(RML.DEF)
|
||||
$(CPLUS) $(PREPROC_ONLY) $< $(CPLUS_FLAGS) $(INCLUDES) > $@
|
||||
|
||||
LIB_LINK_FLAGS += $(EXPORT_KEY)rml.def
|
||||
$(RML.DLL): rml.def
|
||||
endif
|
||||
|
||||
$(RML.DLL): CPLUS_FLAGS += $(SDL_FLAGS)
|
||||
$(RML.DLL): BUILDING_LIBRARY = $(RML.DLL)
|
||||
$(RML.DLL): $(RML_TBB_DEP) $(RML.OBJ) $(RML.RES) $(RML_NO_VERSION.DLL) $(RML_ASM.OBJ)
|
||||
$(LIB_LINK_CMD) $(LIB_OUTPUT_KEY)$(RML.DLL) $(RML.OBJ) $(RML_TBB_DEP) $(RML_ASM.OBJ) $(RML.RES) $(LIB_LINK_LIBS) $(LIB_LINK_FLAGS)
|
||||
|
||||
ifneq (,$(RML_NO_VERSION.DLL))
|
||||
$(RML_NO_VERSION.DLL):
|
||||
echo "INPUT ($(RML.DLL))" > $(RML_NO_VERSION.DLL)
|
||||
endif
|
||||
|
||||
rml: rml_dll
|
||||
rml_dll: $(RML.DLL)
|
||||
|
||||
#------------------------------------------------------
|
||||
# End of rules for making the RML server shared library
|
||||
#------------------------------------------------------
|
||||
|
||||
#------------------------------------------------------
|
||||
# Define rules for making the RML unit tests
|
||||
#------------------------------------------------------
|
||||
|
||||
add_debug=$(basename $(1))_debug$(suffix $(1))
|
||||
cross_suffix=$(if $(crosstest),$(if $(DEBUG_SUFFIX),$(subst _debug,,$(1)),$(call add_debug,$(1))),$(1))
|
||||
|
||||
RML_TESTS = test_job_automaton.$(TEST_EXT) test_thread_monitor.$(TEST_EXT)
|
||||
RML_CUSTOM_TESTS = test_rml_tbb.$(TEST_EXT)
|
||||
|
||||
test_rml_tbb.$(TEST_EXT): test_rml_tbb.$(OBJ) $(RML_TBB_CLIENT.OBJ) $(TBB_DEP_RML_TEST)
|
||||
$(CPLUS) $(OUTPUT_KEY)$@ $(CPLUS_FLAGS) test_rml_tbb.$(OBJ) $(RML_TBB_CLIENT.OBJ) $(TBB_DEP_RML_TEST) $(LIBS) $(LINK_FLAGS)
|
||||
|
||||
$(RML_TESTS): %.$(TEST_EXT): %.$(OBJ) $(TBB_DEP_NON_RML_TEST)
|
||||
$(CPLUS) $(OUTPUT_KEY)$@ $(CPLUS_FLAGS) $< $(TBB_DEP_NON_RML_TEST) $(LIBS) $(LINK_FLAGS)
|
||||
|
||||
### run_cmd is usually empty
|
||||
rml_test: $(call cross_suffix,$(RML.DLL)) $(TEST_PREREQUISITE) $(RML_TESTS) $(RML_CUSTOM_TESTS)
|
||||
$(run_cmd) ./test_job_automaton.$(TEST_EXT) $(args)
|
||||
$(run_cmd) ./test_thread_monitor.$(TEST_EXT) $(args)
|
||||
$(run_cmd) ./test_rml_tbb.$(TEST_EXT) $(args)
|
||||
|
||||
#------------------------------------------------------
|
||||
# End of rules for making the TBBMalloc unit tests
|
||||
#------------------------------------------------------
|
||||
|
||||
# Include automatically generated dependencies
|
||||
-include *.d
|
||||
|
||||
clean:
|
||||
-rm -rf *.o *.so* *.d *.def version_string.ver
|
||||
-rm -rf $(work_dir)_release/libirml*
|
||||
-rm -rf $(work_dir)_debug/libirml*
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,144 @@
|
||||
/*
|
||||
Copyright (c) 2017 Intel Corporation
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
|
||||
|
||||
|
||||
|
||||
*/
|
||||
|
||||
#include "ipc_utils.h"
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <limits.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
|
||||
namespace tbb {
|
||||
namespace internal {
|
||||
namespace rml {
|
||||
|
||||
#define MAX_STR_LEN 255
|
||||
#define STARTTIME_ITEM_ID 21
|
||||
|
||||
static char* get_stat_item(char* line, int item_id) {
|
||||
int id = 0, i = 0;
|
||||
|
||||
while( id!=item_id ) {
|
||||
while( line[i]!='(' && line[i]!=' ' && line[i]!='\0' ) {
|
||||
++i;
|
||||
}
|
||||
if( line[i]==' ' ) {
|
||||
++id;
|
||||
++i;
|
||||
} else if( line[i]=='(' ) {
|
||||
while( line[i]!=')' && line[i]!='\0' ) {
|
||||
++i;
|
||||
}
|
||||
if( line[i]==')' ) {
|
||||
++i;
|
||||
} else {
|
||||
return NULL;
|
||||
}
|
||||
} else {
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
return line + i;
|
||||
}
|
||||
|
||||
unsigned long long get_start_time(int pid) {
|
||||
const char* stat_file_path_template = "/proc/%d/stat";
|
||||
char stat_file_path[MAX_STR_LEN + 1];
|
||||
sprintf( stat_file_path, stat_file_path_template, pid );
|
||||
|
||||
FILE* stat_file = fopen( stat_file_path, "rt" );
|
||||
if( stat_file==NULL ) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
char stat_line[MAX_STR_LEN + 1];
|
||||
char* line = fgets( stat_line, MAX_STR_LEN, stat_file );
|
||||
if( line==NULL ) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
char* starttime_str = get_stat_item( stat_line, STARTTIME_ITEM_ID );
|
||||
if( starttime_str==NULL ) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
unsigned long long starttime = strtoull( starttime_str, NULL, 10 );
|
||||
if( starttime==ULLONG_MAX ) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
return starttime;
|
||||
}
|
||||
|
||||
char* get_shared_name(const char* prefix, int pid, unsigned long long time) {
|
||||
const char* name_template = "%s_%d_%llu";
|
||||
const int digits_in_int = 10;
|
||||
const int digits_in_long = 20;
|
||||
|
||||
int len = strlen( name_template ) + strlen( prefix ) + digits_in_int + digits_in_long + 1;
|
||||
char* name = new char[len];
|
||||
sprintf( name, name_template, prefix, pid, time );
|
||||
|
||||
return name;
|
||||
}
|
||||
|
||||
char* get_shared_name(const char* prefix) {
|
||||
int pid = getpgrp();
|
||||
unsigned long long time = get_start_time( pid );
|
||||
return get_shared_name( prefix, pid, time );
|
||||
}
|
||||
|
||||
int get_num_threads(const char* env_var) {
|
||||
if( env_var==NULL ) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
char* value = getenv( env_var );
|
||||
if( value==NULL ) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
int num_threads = (int)strtol( value, NULL, 10 );
|
||||
return num_threads;
|
||||
}
|
||||
|
||||
bool get_enable_flag(const char* env_var) {
|
||||
if( env_var==NULL ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
char* value = getenv( env_var );
|
||||
if( value==NULL ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if( strcmp( value, "0" ) == 0 ||
|
||||
strcmp( value, "false" ) == 0 ||
|
||||
strcmp( value, "False" ) == 0 ||
|
||||
strcmp( value, "FALSE" ) == 0 ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
}}} //tbb::internal::rml
|
||||
@@ -0,0 +1,34 @@
|
||||
/*
|
||||
Copyright (c) 2017 Intel Corporation
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
|
||||
|
||||
|
||||
|
||||
*/
|
||||
|
||||
#ifndef __IPC_UTILS_H
|
||||
#define __IPC_UTILS_H
|
||||
|
||||
namespace tbb {
|
||||
namespace internal {
|
||||
namespace rml {
|
||||
|
||||
char* get_shared_name(const char* prefix);
|
||||
int get_num_threads(const char* env_var);
|
||||
bool get_enable_flag(const char* env_var);
|
||||
|
||||
}}} //tbb::internal::rml
|
||||
|
||||
#endif
|
||||
+7
-7
@@ -58,13 +58,14 @@ else:
|
||||
tbb_flag = ['-tbb'] if use_compiler_tbb else []
|
||||
compile_flags = ['-std=c++11', '-Wno-unused-variable']
|
||||
|
||||
_tbb = Extension("_TBB", ["tbb.i"],
|
||||
_tbb = Extension("tbb._api", ["tbb/api.i"],
|
||||
include_dirs=[os.path.join(tbb_root, 'include')] if not use_compiler_tbb else [],
|
||||
swig_opts =['-c++', '-O', '-threads'] + ( # add '-builtin' later
|
||||
['-I' + os.path.join(tbb_root, 'include')] if not use_compiler_tbb else []),
|
||||
extra_compile_args=compile_flags + tbb_flag,
|
||||
extra_link_args=tbb_flag,
|
||||
libraries =['tbb'] if not use_compiler_tbb else [],
|
||||
libraries =(['tbb'] if not use_compiler_tbb else []) +
|
||||
(['irml'] if platform.system() == "Linux" else []), # TODO: why do we need this?
|
||||
library_dirs=[os.path.join(tbb_root, 'lib', 'intel64', 'gcc4.4'), # for Linux
|
||||
os.path.join(tbb_root, 'lib'), # for MacOS
|
||||
os.path.join(tbb_root, 'lib', 'intel64', 'vc_mt'), # for Windows
|
||||
@@ -86,7 +87,7 @@ setup( name ="TBB",
|
||||
"extended with standard Pool implementation and monkey-patching",
|
||||
url ="https://software.intel.com/en-us/intel-tbb",
|
||||
author ="Intel Corporation",
|
||||
author_email="tbbdevelopers@intel.com",
|
||||
author_email="inteltbbdevelopers@intel.com",
|
||||
license ="Dual license: Apache or Proprietary",
|
||||
version ="0.1",
|
||||
classifiers =[
|
||||
@@ -98,11 +99,9 @@ setup( name ="TBB",
|
||||
'Intended Audience :: Other Audience',
|
||||
'Intended Audience :: Science/Research',
|
||||
'License :: OSI Approved :: Apache Software License',
|
||||
'License :: Other/Proprietary License',
|
||||
'Operating System :: MacOS :: MacOS X',
|
||||
'Operating System :: Microsoft :: Windows',
|
||||
'Operating System :: POSIX',
|
||||
'Operating System :: Unix',
|
||||
'Operating System :: POSIX :: Linux',
|
||||
'Programming Language :: Python',
|
||||
'Programming Language :: Python :: 2',
|
||||
'Programming Language :: Python :: 3',
|
||||
@@ -110,8 +109,9 @@ setup( name ="TBB",
|
||||
'Topic :: System :: Hardware :: Symmetric Multi-processing',
|
||||
'Topic :: Software Development :: Libraries',
|
||||
],
|
||||
keywords='tbb multiprocessing multithreading composable parallelism',
|
||||
keywords='TBB multiprocessing multithreading composable parallelism',
|
||||
ext_modules=[_tbb],
|
||||
packages=['tbb'],
|
||||
py_modules=['TBB'],
|
||||
cmdclass={'build': TBBBuild}
|
||||
)
|
||||
|
||||
@@ -0,0 +1,264 @@
|
||||
#
|
||||
# Copyright (c) 2005-2017 Intel Corporation
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
from __future__ import print_function
|
||||
|
||||
import multiprocessing.pool
|
||||
import ctypes
|
||||
import atexit
|
||||
import sys
|
||||
import os
|
||||
|
||||
from .api import *
|
||||
from .api import __all__ as api__all
|
||||
from .pool import *
|
||||
from .pool import __all__ as pool__all
|
||||
|
||||
__all__ = ["Monkey"] + api__all + pool__all
|
||||
|
||||
__doc__ = """
|
||||
Python API for Intel(R) Threading Building Blocks library (Intel(R) TBB)
|
||||
extended with standard Python's pools implementation and monkey-patching.
|
||||
|
||||
Command-line interface example:
|
||||
$ python -m tbb $your_script.py
|
||||
Runs your_script.py in context of tbb.Monkey
|
||||
"""
|
||||
|
||||
|
||||
ipc_enabled = False
|
||||
libirml = "libirml.so.1"
|
||||
|
||||
|
||||
def _test(arg=None):
|
||||
"""Some tests"""
|
||||
import platform
|
||||
if platform.system() == "Linux":
|
||||
ctypes.CDLL(libirml)
|
||||
from .test import test
|
||||
test(arg)
|
||||
print("done")
|
||||
|
||||
|
||||
def tbb_process_pool_worker27(inqueue, outqueue, initializer=None, initargs=(),
|
||||
maxtasks=None):
|
||||
from multiprocessing.pool import worker
|
||||
worker(inqueue, outqueue, initializer, initargs, maxtasks)
|
||||
if ipc_enabled:
|
||||
try:
|
||||
librml = ctypes.CDLL(libirml)
|
||||
librml.release_resources()
|
||||
except:
|
||||
print("Warning: Can not load ", libirml, file=sys.stderr)
|
||||
|
||||
|
||||
class TBBProcessPool27(multiprocessing.pool.Pool):
|
||||
def _repopulate_pool(self):
|
||||
"""Bring the number of pool processes up to the specified number,
|
||||
for use after reaping workers which have exited.
|
||||
"""
|
||||
from multiprocessing.util import debug
|
||||
|
||||
for i in range(self._processes - len(self._pool)):
|
||||
w = self.Process(target=tbb_process_pool_worker27,
|
||||
args=(self._inqueue, self._outqueue,
|
||||
self._initializer,
|
||||
self._initargs, self._maxtasksperchild)
|
||||
)
|
||||
self._pool.append(w)
|
||||
w.name = w.name.replace('Process', 'PoolWorker')
|
||||
w.daemon = True
|
||||
w.start()
|
||||
debug('added worker')
|
||||
|
||||
def __del__(self):
|
||||
self.close()
|
||||
for p in self._pool:
|
||||
p.join()
|
||||
|
||||
def __exit__(self):
|
||||
self.close()
|
||||
for p in self._pool:
|
||||
p.join()
|
||||
|
||||
|
||||
def tbb_process_pool_worker35(inqueue, outqueue, initializer=None, initargs=(),
|
||||
maxtasks=None, wrap_exception=False):
|
||||
from multiprocessing.pool import worker
|
||||
worker(inqueue, outqueue, initializer, initargs, maxtasks, wrap_exception)
|
||||
if ipc_enabled:
|
||||
try:
|
||||
librml = ctypes.CDLL(libirml)
|
||||
librml.release_resources()
|
||||
except:
|
||||
print("Warning: Can not load ", libirml, file=sys.stderr)
|
||||
|
||||
|
||||
class TBBProcessPool35(multiprocessing.pool.Pool):
|
||||
def _repopulate_pool(self):
|
||||
"""Bring the number of pool processes up to the specified number,
|
||||
for use after reaping workers which have exited.
|
||||
"""
|
||||
from multiprocessing.util import debug
|
||||
|
||||
for i in range(self._processes - len(self._pool)):
|
||||
w = self.Process(target=tbb_process_pool_worker35,
|
||||
args=(self._inqueue, self._outqueue,
|
||||
self._initializer,
|
||||
self._initargs, self._maxtasksperchild,
|
||||
self._wrap_exception)
|
||||
)
|
||||
self._pool.append(w)
|
||||
w.name = w.name.replace('Process', 'PoolWorker')
|
||||
w.daemon = True
|
||||
w.start()
|
||||
debug('added worker')
|
||||
|
||||
def __del__(self):
|
||||
self.close()
|
||||
for p in self._pool:
|
||||
p.join()
|
||||
|
||||
def __exit__(self):
|
||||
self.close()
|
||||
for p in self._pool:
|
||||
p.join()
|
||||
|
||||
|
||||
class Monkey:
|
||||
"""
|
||||
Context manager which replaces standard multiprocessing.pool
|
||||
implementations with tbb.pool using monkey-patching. It also enables TBB
|
||||
threading for Intel(R) Math Kernel Library (Intel(R) MKL). For example:
|
||||
|
||||
with tbb.Monkey():
|
||||
run_my_numpy_code()
|
||||
|
||||
It allows multiple parallel tasks to be executed on the same thread pool
|
||||
and coordinate number of threads across multiple processes thus avoiding
|
||||
overheads from oversubscription.
|
||||
"""
|
||||
_items = {'ThreadPool' : None,
|
||||
'Pool' : None}
|
||||
_modules = {'ThreadPool' : None,
|
||||
'Pool' : None}
|
||||
|
||||
def __init__(self, max_num_threads=None):
|
||||
"""
|
||||
Create context manager for running under TBB scheduler.
|
||||
:param max_num_threads: if specified, limits maximal number of threads
|
||||
"""
|
||||
if max_num_threads:
|
||||
self.ctl = global_control(global_control.max_allowed_parallelism, int(max_num_threads))
|
||||
|
||||
def _patch(self, class_name, module_name, object):
|
||||
self._modules[class_name] = __import__(module_name, globals(),
|
||||
locals(), [class_name])
|
||||
if self._modules[class_name] == None:
|
||||
return
|
||||
oldattr = getattr(self._modules[class_name], class_name, None)
|
||||
if oldattr == None:
|
||||
self._modules[class_name] = None
|
||||
return
|
||||
self._items[class_name] = oldattr
|
||||
setattr(self._modules[class_name], class_name, object)
|
||||
|
||||
def __enter__(self):
|
||||
self.env = os.getenv('MKL_THREADING_LAYER')
|
||||
os.environ['MKL_THREADING_LAYER'] = 'TBB'
|
||||
if sys.version_info.major == 2 and sys.version_info.minor >= 7:
|
||||
self._patch("Pool", "multiprocessing.pool", TBBProcessPool27)
|
||||
elif sys.version_info.major == 3 and sys.version_info.minor >= 5:
|
||||
self._patch("Pool", "multiprocessing.pool", TBBProcessPool35)
|
||||
self._patch("ThreadPool", "multiprocessing.pool", Pool)
|
||||
return self
|
||||
|
||||
def __exit__(self, exc_type, exc_value, traceback):
|
||||
if self.env is None:
|
||||
del os.environ['MKL_THREADING_LAYER']
|
||||
else:
|
||||
os.environ['MKL_THREADING_LAYER'] = self.env
|
||||
for name in self._items.keys():
|
||||
setattr(self._modules[name], name, self._items[name])
|
||||
|
||||
|
||||
def init_sem_name():
|
||||
try:
|
||||
librml = ctypes.CDLL(libirml)
|
||||
librml.set_active_sem_name()
|
||||
librml.set_stop_sem_name()
|
||||
except Exception as e:
|
||||
print("Warning: Can not initialize name of shared semaphores:", e,
|
||||
file=sys.stderr)
|
||||
|
||||
|
||||
def tbb_atexit():
|
||||
if ipc_enabled:
|
||||
try:
|
||||
librml = ctypes.CDLL(libirml)
|
||||
librml.release_semaphores()
|
||||
except:
|
||||
print("Warning: Can not release shared semaphores",
|
||||
file=sys.stderr)
|
||||
|
||||
|
||||
def _main():
|
||||
# Run the module specified as the next command line argument
|
||||
# python -m TBB user_app.py
|
||||
global ipc_enabled
|
||||
|
||||
import platform
|
||||
import argparse
|
||||
parser = argparse.ArgumentParser(prog="python -m tbb", description="""
|
||||
Run your Python script in context of tbb.Monkey, which
|
||||
replaces standard Python pools and threading layer of
|
||||
Intel(R) Math Kernel Library by implementation based on
|
||||
Intel(R) Threading Building Blocks. It enables multiple parallel
|
||||
tasks to be executed on the same thread pool and coordinate
|
||||
number of threads across multiple processes thus avoiding
|
||||
overheads from oversubscription.
|
||||
""", formatter_class=argparse.ArgumentDefaultsHelpFormatter)
|
||||
if platform.system() == "Linux":
|
||||
parser.add_argument('--ipc', action='store_true',
|
||||
help="Enable inter-precess (IPC) synchronization")
|
||||
parser.add_argument('-p', '--max-num-threads', default=default_num_threads(), type=int,
|
||||
help="Initialize TBB with P max number of threads per process", metavar='P')
|
||||
#parser.add_argument('-a', '--replace-allocator', action='store_true',
|
||||
# help="Enable TBB malloc")
|
||||
#parser.add_argument('--huge-pages', action='store_true',
|
||||
# help="Enable huge pages for TBB malloc")
|
||||
parser.add_argument('-m', action='store_true', dest='module',
|
||||
help="Executes following as a module")
|
||||
parser.add_argument('name', help="Script or module name")
|
||||
parser.add_argument('args', nargs=argparse.REMAINDER,
|
||||
help="Command line arguments")
|
||||
args = parser.parse_args()
|
||||
sys.argv = [args.name] + args.args
|
||||
|
||||
ipc_enabled = platform.system() == "Linux" and args.ipc
|
||||
os.environ["IPC_ENABLE"] = "1" if ipc_enabled else "0"
|
||||
if ipc_enabled:
|
||||
atexit.register(tbb_atexit)
|
||||
init_sem_name()
|
||||
|
||||
if not os.environ.get("KMP_BLOCKTIME"): # TODO move
|
||||
os.environ["KMP_BLOCKTIME"] = "0"
|
||||
if '_' + args.name in globals():
|
||||
return globals()['_' + args.name](*args.args)
|
||||
else:
|
||||
import runpy
|
||||
runf = runpy.run_module if args.module else runpy.run_path
|
||||
with Monkey(max_num_threads=args.max_num_threads):
|
||||
runf(args.name, run_name='__main__')
|
||||
@@ -0,0 +1,19 @@
|
||||
#
|
||||
# Copyright (c) 2005-2017 Intel Corporation
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
|
||||
from . import _main
|
||||
from sys import exit
|
||||
exit(_main())
|
||||
@@ -18,50 +18,19 @@
|
||||
#
|
||||
#
|
||||
|
||||
|
||||
# Based on the software developed by:
|
||||
# Copyright (c) 2008,2016 david decotigny (Pool of threads)
|
||||
# Copyright (c) 2006-2008, R Oudkerk (multiprocessing.Pool)
|
||||
# All rights reserved.
|
||||
#
|
||||
# Redistribution and use in source and binary forms, with or without
|
||||
# modification, are permitted provided that the following conditions
|
||||
# are met:
|
||||
#
|
||||
# 1. Redistributions of source code must retain the above copyright
|
||||
# notice, this list of conditions and the following disclaimer.
|
||||
# 2. Redistributions in binary form must reproduce the above copyright
|
||||
# notice, this list of conditions and the following disclaimer in the
|
||||
# documentation and/or other materials provided with the distribution.
|
||||
# 3. Neither the name of author nor the names of any contributors may be
|
||||
# used to endorse or promote products derived from this software
|
||||
# without specific prior written permission.
|
||||
#
|
||||
# THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS "AS IS" AND
|
||||
# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
# ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
|
||||
# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
# SUCH DAMAGE.
|
||||
#
|
||||
|
||||
from __future__ import print_function
|
||||
__all__ = ["task_arena", "task_group", "task_scheduler_init", "global_control", "default_num_threads"]
|
||||
%}
|
||||
%begin %{
|
||||
/* Defines Python wrappers for Intel(R) Threading Building Blocks (Intel TBB).*/
|
||||
%}
|
||||
%module TBB
|
||||
%module api
|
||||
|
||||
#if SWIG_VERSION < 0x030001
|
||||
#error SWIG version 3.0.6 or newer is required for correct functioning
|
||||
#endif
|
||||
|
||||
%{
|
||||
#define TBB_PREVIEW_GLOBAL_CONTROL 1
|
||||
#include <tbb/tbb.h>
|
||||
using namespace tbb;
|
||||
|
||||
@@ -140,7 +109,21 @@ namespace tbb {
|
||||
};
|
||||
};
|
||||
|
||||
}
|
||||
class global_control {
|
||||
public:
|
||||
enum parameter {
|
||||
max_allowed_parallelism,
|
||||
thread_stack_size,
|
||||
parameter_max // insert new parameters above this point
|
||||
};
|
||||
global_control(parameter param, size_t value);
|
||||
~global_control();
|
||||
static size_t active_value(parameter param);
|
||||
};
|
||||
|
||||
// Python part of the module
|
||||
%pythoncode "tbb.src.py"
|
||||
} // tbb
|
||||
|
||||
// Additional definitions for Python part of the module
|
||||
%pythoncode %{
|
||||
default_num_threads = task_scheduler_init_default_num_threads
|
||||
%}
|
||||
@@ -1,4 +1,3 @@
|
||||
|
||||
#
|
||||
# Copyright (c) 2005-2017 Intel Corporation
|
||||
#
|
||||
@@ -73,20 +72,14 @@
|
||||
import sys
|
||||
import threading
|
||||
import traceback
|
||||
from .api import *
|
||||
|
||||
__all__ = ["Pool", "Monkey", "task_arena", "task_group", "task_scheduler_init"]
|
||||
__all__ = ["Pool", "TimeoutError"]
|
||||
__doc__ = """
|
||||
Python API to Intel(R) Threading Building Blocks library (Intel TBB)
|
||||
extended with standard Pool implementation and monkey-patching.
|
||||
|
||||
Command-line interface:
|
||||
$ python -m TBB $your_script.py
|
||||
|
||||
Runs your_script.py in context of `with Monkey():`
|
||||
Standard Python Pool implementation based on Python API
|
||||
for Intel(R) Threading Building Blocks library (Intel(R) TBB)
|
||||
"""
|
||||
|
||||
default_num_threads = task_scheduler_init_default_num_threads
|
||||
|
||||
|
||||
class TimeoutError(Exception):
|
||||
"""Raised when a result is not available within the given timeout"""
|
||||
@@ -96,7 +89,7 @@ class TimeoutError(Exception):
|
||||
class Pool(object):
|
||||
"""
|
||||
The Pool class provides standard multiprocessing.Pool interface
|
||||
which is mapped onto Intel TBB tasks executing in its thread pool
|
||||
which is mapped onto Intel(R) TBB tasks executing in its thread pool
|
||||
"""
|
||||
|
||||
def __init__(self, nworkers=0, name="Pool"):
|
||||
@@ -639,202 +632,3 @@ class OrderedResultCollector(AbstractResultCollector):
|
||||
self._to_notify._set_exception()
|
||||
else:
|
||||
self._to_notify._set_value(lst)
|
||||
|
||||
|
||||
def _test(arg=None):
|
||||
"""Some tests"""
|
||||
if arg == "-v":
|
||||
def say(*x):
|
||||
print(*x)
|
||||
else:
|
||||
def say(*x):
|
||||
pass
|
||||
say("Start Pool testing")
|
||||
import time
|
||||
|
||||
get_tid = lambda: threading.current_thread().ident
|
||||
|
||||
def return42():
|
||||
return 42
|
||||
|
||||
def f(x):
|
||||
return x * x
|
||||
|
||||
def work(mseconds):
|
||||
res = str(mseconds)
|
||||
if mseconds < 0:
|
||||
mseconds = -mseconds
|
||||
say("[%d] Start to work for %fms..." % (get_tid(), mseconds*10))
|
||||
time.sleep(mseconds/100.)
|
||||
say("[%d] Work done (%fms)." % (get_tid(), mseconds*10))
|
||||
return res
|
||||
|
||||
### Test copy/pasted from multiprocessing
|
||||
pool = Pool(4) # start worker threads
|
||||
|
||||
# edge cases
|
||||
assert pool.map(return42, []) == []
|
||||
assert pool.apply_async(return42, []).get() == 42
|
||||
assert pool.apply(return42, []) == 42
|
||||
assert list(pool.imap(return42, iter([]))) == []
|
||||
assert list(pool.imap_unordered(return42, iter([]))) == []
|
||||
assert pool.map_async(return42, []).get() == []
|
||||
assert list(pool.imap_async(return42, iter([])).get()) == []
|
||||
assert list(pool.imap_unordered_async(return42, iter([])).get()) == []
|
||||
|
||||
# basic tests
|
||||
result = pool.apply_async(f, (10,)) # evaluate "f(10)" asynchronously
|
||||
assert result.get(timeout=1) == 100 # ... unless slow computer
|
||||
assert list(pool.map(f, range(10))) == list(map(f, range(10)))
|
||||
it = pool.imap(f, range(10))
|
||||
assert next(it) == 0
|
||||
assert next(it) == 1
|
||||
assert next(it) == 4
|
||||
|
||||
# Test apply_sync exceptions
|
||||
result = pool.apply_async(time.sleep, (3,))
|
||||
try:
|
||||
say(result.get(timeout=1)) # raises `TimeoutError`
|
||||
except TimeoutError:
|
||||
say("Good. Got expected timeout exception.")
|
||||
else:
|
||||
assert False, "Expected exception !"
|
||||
assert result.get() is None # sleep() returns None
|
||||
|
||||
def cb(s):
|
||||
say("Result ready: %s" % s)
|
||||
|
||||
# Test imap()
|
||||
assert list(pool.imap(work, range(10, 3, -1), chunksize=4)) == list(map(
|
||||
str, range(10, 3, -1)))
|
||||
|
||||
# Test imap_unordered()
|
||||
assert sorted(pool.imap_unordered(work, range(10, 3, -1))) == sorted(map(
|
||||
str, range(10, 3, -1)))
|
||||
|
||||
# Test map_async()
|
||||
result = pool.map_async(work, range(10), callback=cb)
|
||||
try:
|
||||
result.get(timeout=0.01) # raises `TimeoutError`
|
||||
except TimeoutError:
|
||||
say("Good. Got expected timeout exception.")
|
||||
else:
|
||||
assert False, "Expected exception !"
|
||||
say(result.get())
|
||||
|
||||
# Test imap_async()
|
||||
result = pool.imap_async(work, range(3, 10), callback=cb)
|
||||
try:
|
||||
result.get(timeout=0.01) # raises `TimeoutError`
|
||||
except TimeoutError:
|
||||
say("Good. Got expected timeout exception.")
|
||||
else:
|
||||
assert False, "Expected exception !"
|
||||
for i in result.get():
|
||||
say("Item:", i)
|
||||
say("### Loop again:")
|
||||
for i in result.get():
|
||||
say("Item2:", i)
|
||||
|
||||
# Test imap_unordered_async()
|
||||
result = pool.imap_unordered_async(work, range(10, 3, -1), callback=cb)
|
||||
try:
|
||||
say(result.get(timeout=0.01)) # raises `TimeoutError`
|
||||
except TimeoutError:
|
||||
say("Good. Got expected timeout exception.")
|
||||
else:
|
||||
assert False, "Expected exception !"
|
||||
for i in result.get():
|
||||
say("Item1:", i)
|
||||
for i in result.get():
|
||||
say("Item2:", i)
|
||||
r = result.get()
|
||||
for i in r:
|
||||
say("Item3:", i)
|
||||
for i in r:
|
||||
say("Item4:", i)
|
||||
for i in r:
|
||||
say("Item5:", i)
|
||||
|
||||
#
|
||||
# The case for the exceptions
|
||||
#
|
||||
|
||||
# Exceptions in imap_unordered_async()
|
||||
result = pool.imap_unordered_async(work, range(2, -10, -1), callback=cb)
|
||||
time.sleep(3)
|
||||
try:
|
||||
for i in result.get():
|
||||
say("Got item:", i)
|
||||
except (IOError, ValueError):
|
||||
say("Good. Got expected exception")
|
||||
|
||||
# Exceptions in imap_async()
|
||||
result = pool.imap_async(work, range(2, -10, -1), callback=cb)
|
||||
time.sleep(3)
|
||||
try:
|
||||
for i in result.get():
|
||||
say("Got item:", i)
|
||||
except (IOError, ValueError):
|
||||
say("Good. Got expected exception")
|
||||
|
||||
# Stop the test: need to stop the pool !!!
|
||||
pool.terminate()
|
||||
pool.join()
|
||||
print("done")
|
||||
|
||||
|
||||
# End of david's derived file content
|
||||
|
||||
class Monkey:
|
||||
"""
|
||||
Context manager which replaces standard multiprocessing.pool.ThreadPool
|
||||
implementation with TBB.Pool using monkey-patching. It also enables TBB
|
||||
threading for Intel MKL. For example:
|
||||
|
||||
with TBB.Monkey():
|
||||
run_my_numpy_code()
|
||||
|
||||
"""
|
||||
_items = {'ThreadPool': None}
|
||||
|
||||
def __init__(self):
|
||||
pass
|
||||
|
||||
def __enter__(self):
|
||||
import os
|
||||
self.env = os.getenv('MKL_THREADING_LAYER')
|
||||
os.environ['MKL_THREADING_LAYER'] = 'TBB'
|
||||
self.module = __import__('multiprocessing.pool', globals(), locals(), self._items.keys())
|
||||
for name in self._items.keys():
|
||||
oldattr = getattr(self.module, name)
|
||||
self._items[name] = oldattr
|
||||
setattr(self.module, name, Pool)
|
||||
return self
|
||||
|
||||
def __exit__(self, exc_type, exc_value, traceback):
|
||||
import os
|
||||
if self.env is None:
|
||||
del os.environ['MKL_THREADING_LAYER']
|
||||
else:
|
||||
os.environ['MKL_THREADING_LAYER'] = self.env
|
||||
for name in self._items.keys():
|
||||
setattr(self.module, name, self._items[name])
|
||||
|
||||
|
||||
def _main():
|
||||
# Run the module specified as the next command line argument
|
||||
# python -m TBB user_app.py
|
||||
del sys.argv[0] # shift arguments
|
||||
if len(sys.argv) < 1:
|
||||
print("No file name specified for execution", file=sys.stderr)
|
||||
elif '_' + sys.argv[0] in globals():
|
||||
globals()['_' + sys.argv[0]](*sys.argv[1:])
|
||||
else:
|
||||
import runpy
|
||||
with Monkey():
|
||||
runpy.run_path(sys.argv[0], run_name='__main__')
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
sys.exit(_main())
|
||||
@@ -0,0 +1,198 @@
|
||||
#
|
||||
# Copyright (c) 2005-2017 Intel Corporation
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
#
|
||||
#
|
||||
#
|
||||
#
|
||||
|
||||
# Based on the software developed by:
|
||||
# Copyright (c) 2008,2016 david decotigny (Pool of threads)
|
||||
# Copyright (c) 2006-2008, R Oudkerk (multiprocessing.Pool)
|
||||
# All rights reserved.
|
||||
#
|
||||
# Redistribution and use in source and binary forms, with or without
|
||||
# modification, are permitted provided that the following conditions
|
||||
# are met:
|
||||
#
|
||||
# 1. Redistributions of source code must retain the above copyright
|
||||
# notice, this list of conditions and the following disclaimer.
|
||||
# 2. Redistributions in binary form must reproduce the above copyright
|
||||
# notice, this list of conditions and the following disclaimer in the
|
||||
# documentation and/or other materials provided with the distribution.
|
||||
# 3. Neither the name of author nor the names of any contributors may be
|
||||
# used to endorse or promote products derived from this software
|
||||
# without specific prior written permission.
|
||||
#
|
||||
# THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS "AS IS" AND
|
||||
# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
# ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
|
||||
# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
# SUCH DAMAGE.
|
||||
#
|
||||
|
||||
from __future__ import print_function
|
||||
import time
|
||||
import threading
|
||||
|
||||
from .api import *
|
||||
from .pool import *
|
||||
|
||||
|
||||
def test(arg=None):
|
||||
if arg == "-v":
|
||||
def say(*x):
|
||||
print(*x)
|
||||
else:
|
||||
def say(*x):
|
||||
pass
|
||||
say("Start Pool testing")
|
||||
|
||||
get_tid = lambda: threading.current_thread().ident
|
||||
|
||||
def return42():
|
||||
return 42
|
||||
|
||||
def f(x):
|
||||
return x * x
|
||||
|
||||
def work(mseconds):
|
||||
res = str(mseconds)
|
||||
if mseconds < 0:
|
||||
mseconds = -mseconds
|
||||
say("[%d] Start to work for %fms..." % (get_tid(), mseconds*10))
|
||||
time.sleep(mseconds/100.)
|
||||
say("[%d] Work done (%fms)." % (get_tid(), mseconds*10))
|
||||
return res
|
||||
|
||||
### Test copy/pasted from multiprocessing
|
||||
pool = Pool(4) # start worker threads
|
||||
|
||||
# edge cases
|
||||
assert pool.map(return42, []) == []
|
||||
assert pool.apply_async(return42, []).get() == 42
|
||||
assert pool.apply(return42, []) == 42
|
||||
assert list(pool.imap(return42, iter([]))) == []
|
||||
assert list(pool.imap_unordered(return42, iter([]))) == []
|
||||
assert pool.map_async(return42, []).get() == []
|
||||
assert list(pool.imap_async(return42, iter([])).get()) == []
|
||||
assert list(pool.imap_unordered_async(return42, iter([])).get()) == []
|
||||
|
||||
# basic tests
|
||||
result = pool.apply_async(f, (10,)) # evaluate "f(10)" asynchronously
|
||||
assert result.get(timeout=1) == 100 # ... unless slow computer
|
||||
assert list(pool.map(f, range(10))) == list(map(f, range(10)))
|
||||
it = pool.imap(f, range(10))
|
||||
assert next(it) == 0
|
||||
assert next(it) == 1
|
||||
assert next(it) == 4
|
||||
|
||||
# Test apply_sync exceptions
|
||||
result = pool.apply_async(time.sleep, (3,))
|
||||
try:
|
||||
say(result.get(timeout=1)) # raises `TimeoutError`
|
||||
except TimeoutError:
|
||||
say("Good. Got expected timeout exception.")
|
||||
else:
|
||||
assert False, "Expected exception !"
|
||||
assert result.get() is None # sleep() returns None
|
||||
|
||||
def cb(s):
|
||||
say("Result ready: %s" % s)
|
||||
|
||||
# Test imap()
|
||||
assert list(pool.imap(work, range(10, 3, -1), chunksize=4)) == list(map(
|
||||
str, range(10, 3, -1)))
|
||||
|
||||
# Test imap_unordered()
|
||||
assert sorted(pool.imap_unordered(work, range(10, 3, -1))) == sorted(map(
|
||||
str, range(10, 3, -1)))
|
||||
|
||||
# Test map_async()
|
||||
result = pool.map_async(work, range(10), callback=cb)
|
||||
try:
|
||||
result.get(timeout=0.01) # raises `TimeoutError`
|
||||
except TimeoutError:
|
||||
say("Good. Got expected timeout exception.")
|
||||
else:
|
||||
assert False, "Expected exception !"
|
||||
say(result.get())
|
||||
|
||||
# Test imap_async()
|
||||
result = pool.imap_async(work, range(3, 10), callback=cb)
|
||||
try:
|
||||
result.get(timeout=0.01) # raises `TimeoutError`
|
||||
except TimeoutError:
|
||||
say("Good. Got expected timeout exception.")
|
||||
else:
|
||||
assert False, "Expected exception !"
|
||||
for i in result.get():
|
||||
say("Item:", i)
|
||||
say("### Loop again:")
|
||||
for i in result.get():
|
||||
say("Item2:", i)
|
||||
|
||||
# Test imap_unordered_async()
|
||||
result = pool.imap_unordered_async(work, range(10, 3, -1), callback=cb)
|
||||
try:
|
||||
say(result.get(timeout=0.01)) # raises `TimeoutError`
|
||||
except TimeoutError:
|
||||
say("Good. Got expected timeout exception.")
|
||||
else:
|
||||
assert False, "Expected exception !"
|
||||
for i in result.get():
|
||||
say("Item1:", i)
|
||||
for i in result.get():
|
||||
say("Item2:", i)
|
||||
r = result.get()
|
||||
for i in r:
|
||||
say("Item3:", i)
|
||||
for i in r:
|
||||
say("Item4:", i)
|
||||
for i in r:
|
||||
say("Item5:", i)
|
||||
|
||||
#
|
||||
# The case for the exceptions
|
||||
#
|
||||
|
||||
# Exceptions in imap_unordered_async()
|
||||
result = pool.imap_unordered_async(work, range(2, -10, -1), callback=cb)
|
||||
time.sleep(3)
|
||||
try:
|
||||
for i in result.get():
|
||||
say("Got item:", i)
|
||||
except (IOError, ValueError):
|
||||
say("Good. Got expected exception")
|
||||
|
||||
# Exceptions in imap_async()
|
||||
result = pool.imap_async(work, range(2, -10, -1), callback=cb)
|
||||
time.sleep(3)
|
||||
try:
|
||||
for i in result.get():
|
||||
say("Got item:", i)
|
||||
except (IOError, ValueError):
|
||||
say("Good. Got expected exception")
|
||||
|
||||
# Stop the test: need to stop the pool !!!
|
||||
pool.terminate()
|
||||
pool.join()
|
||||
|
||||
|
||||
+1
-1
@@ -170,7 +170,7 @@ void market::destroy () {
|
||||
if ( my_task_node_count )
|
||||
runtime_warning( "Leaked %ld task objects\n", (long)my_task_node_count );
|
||||
#endif /* __TBB_COUNT_TASK_NODES */
|
||||
this->~market();
|
||||
this->market::~market(); // qualified to suppress warning
|
||||
NFS_Free( this );
|
||||
__TBB_InitOnce::remove_ref();
|
||||
}
|
||||
|
||||
@@ -23,6 +23,9 @@
|
||||
#endif
|
||||
#include "tbb/mutex.h"
|
||||
#include "itt_notify.h"
|
||||
#if __TBB_TSX_AVAILABLE
|
||||
#include "governor.h" // for speculation_enabled()
|
||||
#endif
|
||||
|
||||
namespace tbb {
|
||||
void mutex::scoped_lock::internal_acquire( mutex& m ) {
|
||||
@@ -138,6 +141,10 @@ void mutex::internal_destroy() {
|
||||
state = DESTROYED;
|
||||
#else
|
||||
int error_code = pthread_mutex_destroy(&impl);
|
||||
#if __TBB_TSX_AVAILABLE
|
||||
// For processors with speculative execution, skip the error code check due to glibc bug #16657
|
||||
if( tbb::internal::governor::speculation_enabled() ) return;
|
||||
#endif
|
||||
__TBB_ASSERT_EX(!error_code,"mutex: pthread_mutex_destroy failed");
|
||||
#endif /* _WIN32||_WIN64 */
|
||||
}
|
||||
|
||||
+100
-106
@@ -122,19 +122,18 @@ public:
|
||||
#if USE_INTERNAL_TID
|
||||
class ThreadId {
|
||||
static tls_key_t Tid_key;
|
||||
static intptr_t ThreadIdCount;
|
||||
static intptr_t ThreadCount;
|
||||
|
||||
unsigned int id;
|
||||
|
||||
static ThreadId get() {
|
||||
ThreadId result;
|
||||
result.id = reinterpret_cast<intptr_t>(TlsGetValue_func(Tid_key));
|
||||
if( !result.id ) {
|
||||
static unsigned int tlsNumber() {
|
||||
unsigned int result = reinterpret_cast<intptr_t>(TlsGetValue_func(Tid_key));
|
||||
if( !result ) {
|
||||
RecursiveMallocCallProtector scoped;
|
||||
// Thread-local value is zero -> first call from this thread,
|
||||
// need to initialize with next ID value (IDs start from 1)
|
||||
result.id = AtomicIncrement(ThreadIdCount); // returned new value!
|
||||
TlsSetValue_func( Tid_key, reinterpret_cast<void*>(result.id) );
|
||||
result = AtomicIncrement(ThreadCount); // returned new value!
|
||||
TlsSetValue_func( Tid_key, reinterpret_cast<void*>(result) );
|
||||
}
|
||||
return result;
|
||||
}
|
||||
@@ -165,22 +164,27 @@ public:
|
||||
}
|
||||
}
|
||||
|
||||
bool isCurrentThreadId() const { return id == ThreadId::get().id; }
|
||||
void saveCurrentThreadId() { id = ThreadId::get().id; }
|
||||
ThreadId() : id(ThreadId::tlsNumber()) {}
|
||||
bool isCurrentThreadId() const { return id == ThreadId::tlsNumber(); }
|
||||
|
||||
#if COLLECT_STATISTICS || MALLOC_TRACE
|
||||
friend unsigned int getThreadId() { return ThreadId::tlsNumber(); }
|
||||
#endif
|
||||
#if COLLECT_STATISTICS
|
||||
static unsigned getMaxThreadId() { return ThreadIdCount; }
|
||||
static unsigned getMaxThreadId() { return ThreadCount; }
|
||||
|
||||
friend unsigned int getThreadId();
|
||||
friend int STAT_increment(ThreadId tid, int bin, int ctr);
|
||||
#endif
|
||||
};
|
||||
|
||||
tls_key_t ThreadId::Tid_key;
|
||||
intptr_t ThreadId::ThreadIdCount;
|
||||
intptr_t ThreadId::ThreadCount;
|
||||
|
||||
#if COLLECT_STATISTICS
|
||||
unsigned int getThreadId() { return ThreadId::get().id; }
|
||||
int STAT_increment(ThreadId tid, int bin, int ctr)
|
||||
{
|
||||
return ::STAT_increment(tid.id, bin, ctr);
|
||||
}
|
||||
#endif
|
||||
|
||||
#else // USE_INTERNAL_TID
|
||||
@@ -193,7 +197,6 @@ class ThreadId {
|
||||
#endif
|
||||
public:
|
||||
ThreadId() : tid(GetMyTID()) {}
|
||||
void saveCurrentThreadId() { tid = GetMyTID(); }
|
||||
#if USE_PTHREAD
|
||||
bool isCurrentThreadId() const { return pthread_equal(pthread_self(), tid); }
|
||||
#else
|
||||
@@ -205,13 +208,6 @@ public:
|
||||
|
||||
#endif // USE_INTERNAL_TID
|
||||
|
||||
#if COLLECT_STATISTICS
|
||||
int STAT_increment(ThreadId tid, int bin, int ctr)
|
||||
{
|
||||
return ::STAT_increment(tid.id, bin, ctr);
|
||||
}
|
||||
#endif
|
||||
|
||||
/*********** Code to provide thread ID and a thread-local void pointer **********/
|
||||
|
||||
bool TLSKey::init()
|
||||
@@ -263,7 +259,6 @@ inline void TLSKey::setThreadMallocTLS( TLSData * newvalue ) {
|
||||
*/
|
||||
class Bin;
|
||||
class StartupBlock;
|
||||
class TLSData;
|
||||
|
||||
class LifoList {
|
||||
public:
|
||||
@@ -338,26 +333,27 @@ MallocMutex MemoryPool::memPoolListLock;
|
||||
HugePagesStatus hugePages;
|
||||
static bool usedBySrcIncluded = false;
|
||||
|
||||
// Slab block is 16KB-aligned. To prevent false sharing, separate locally-accessed
|
||||
// fields and fields commonly accessed by not owner threads.
|
||||
class GlobalBlockFields : public BlockI {
|
||||
protected:
|
||||
FreeObject *publicFreeList;
|
||||
Block *nextPrivatizable;
|
||||
};
|
||||
|
||||
// Padding helpers
|
||||
template<size_t padd>
|
||||
struct PaddingImpl {
|
||||
size_t __padding[padd];
|
||||
};
|
||||
|
||||
template<>
|
||||
struct PaddingImpl<0> {
|
||||
};
|
||||
struct PaddingImpl<0> {};
|
||||
|
||||
template<int N>
|
||||
struct Padding : PaddingImpl<N/sizeof(size_t)> {};
|
||||
|
||||
// Slab block is 16KB-aligned. To prevent false sharing, separate locally-accessed
|
||||
// fields and fields commonly accessed by not owner threads.
|
||||
class GlobalBlockFields : public BlockI {
|
||||
protected:
|
||||
FreeObject *publicFreeList;
|
||||
Block *nextPrivatizable;
|
||||
MemoryPool *poolPtr;
|
||||
};
|
||||
|
||||
class LocalBlockFields : public GlobalBlockFields, Padding<blockHeaderAlignment - sizeof(GlobalBlockFields)> {
|
||||
protected:
|
||||
Block *next;
|
||||
@@ -368,17 +364,17 @@ protected:
|
||||
when releasing object from a block that current thread owned.
|
||||
NULL for orphaned blocks. */
|
||||
TLSData *tlsPtr;
|
||||
ThreadId ownerTid;
|
||||
ThreadId ownerTid; /* the ID of the thread that owns or last owned the block */
|
||||
BackRefIdx backRefIdx;
|
||||
uint16_t allocatedCount; /* Number of objects allocated (obviously by the owning thread) */
|
||||
uint16_t objectSize;
|
||||
bool isFull;
|
||||
|
||||
friend void *BootStrapBlocks::allocate(MemoryPool *memPool, size_t size);
|
||||
friend void *BootStrapBlocks::allocate(MemoryPool *, size_t);
|
||||
friend class FreeBlockPool;
|
||||
friend class StartupBlock;
|
||||
friend class LifoList;
|
||||
friend Block *MemoryPool::getEmptyBlock(size_t size);
|
||||
friend Block *MemoryPool::getEmptyBlock(size_t);
|
||||
};
|
||||
|
||||
// Use inheritance to guarantee that a user data start on next cache line.
|
||||
@@ -393,7 +389,7 @@ public:
|
||||
inline bool emptyEnoughToUse();
|
||||
bool freeListNonNull() { return freeList; }
|
||||
void freePublicObject(FreeObject *objectToFree);
|
||||
inline void freeOwnObject(MemoryPool *memPool, TLSData *tls, void *object);
|
||||
inline void freeOwnObject(void *object);
|
||||
void makeEmpty();
|
||||
void privatizePublicFreeList();
|
||||
void restoreBumpPtr();
|
||||
@@ -405,7 +401,7 @@ public:
|
||||
return isStartupAllocObject()? 0 : objectSize;
|
||||
}
|
||||
const BackRefIdx *getBackRefIdx() const { return &backRefIdx; }
|
||||
inline TLSData *ownBlock() const;
|
||||
inline bool isOwnedByCurrentThread() const;
|
||||
bool isStartupAllocObject() const { return objectSize == startupAllocObjSizeMark; }
|
||||
inline FreeObject *findObjectToFree(const void *object) const;
|
||||
void checkFreePrecond(const void *object) const {
|
||||
@@ -438,10 +434,9 @@ public:
|
||||
suppress_unused_warning(object);
|
||||
#endif
|
||||
}
|
||||
const BackRefIdx *getBackRef() const { return &backRefIdx; }
|
||||
void initEmptyBlock(TLSData *tls, size_t size);
|
||||
size_t findObjectSize(void *object) const;
|
||||
inline MemoryPool *getMemPool() const;
|
||||
MemoryPool *getMemPool() const { return poolPtr; } // do not use on the hot path!
|
||||
|
||||
protected:
|
||||
void cleanBlockHeader();
|
||||
@@ -452,9 +447,9 @@ private:
|
||||
inline FreeObject *allocateFromBumpPtr();
|
||||
inline FreeObject *findAllocatedObject(const void *address) const;
|
||||
inline bool isProperlyPlaced(const void *object) const;
|
||||
inline bool isOrphaned() const { return !tlsPtr; }
|
||||
inline void markOwned(TLSData *tls) {
|
||||
ownerTid.saveCurrentThreadId();
|
||||
MALLOC_ASSERT(!tlsPtr, ASSERT_TEXT);
|
||||
ownerTid = ThreadId(); /* save the ID of the current thread */
|
||||
tlsPtr = tls;
|
||||
}
|
||||
inline void markOrphaned() {
|
||||
@@ -485,11 +480,11 @@ public:
|
||||
inline void setActiveBlock(Block *block);
|
||||
inline Block* setPreviousBlockActive();
|
||||
Block* getPublicFreeListBlock();
|
||||
void moveBlockToBinFront(Block *block);
|
||||
void moveBlockToFront(Block *block);
|
||||
void processLessUsedBlock(MemoryPool *memPool, Block *block);
|
||||
|
||||
void outofTLSBin (Block* block);
|
||||
void verifyTLSBin (size_t size) const;
|
||||
void outofTLSBin(Block* block);
|
||||
void verifyTLSBin(size_t size) const;
|
||||
void pushTLSBin(Block* block);
|
||||
|
||||
void verifyInitState() const {
|
||||
@@ -1002,7 +997,6 @@ TLSData* MemoryPool::getTLS(bool create)
|
||||
TLSData* tls = extMemPool.tlsPointerKey.getThreadMallocTLS();
|
||||
if (create && !tls)
|
||||
tls = extMemPool.tlsPointerKey.createTLS(this, &extMemPool.backend);
|
||||
if (tls) tls->markUsed();
|
||||
return tls;
|
||||
}
|
||||
|
||||
@@ -1054,6 +1048,7 @@ Block *MemoryPool::getEmptyBlock(size_t size)
|
||||
b->backRefIdx = backRefIdx[i];
|
||||
}
|
||||
b->tlsPtr = tls;
|
||||
b->poolPtr = this;
|
||||
// all but first one go to per-thread pool
|
||||
if (i > 0) {
|
||||
MALLOC_ASSERT(tls, ASSERT_TEXT);
|
||||
@@ -1063,7 +1058,7 @@ Block *MemoryPool::getEmptyBlock(size_t size)
|
||||
}
|
||||
MALLOC_ASSERT(result, ASSERT_TEXT);
|
||||
result->initEmptyBlock(tls, size);
|
||||
STAT_increment(result->owner, getIndex(result->objectSize), allocBlockNew);
|
||||
STAT_increment(getThreadId(), getIndex(result->objectSize), allocBlockNew);
|
||||
return result;
|
||||
}
|
||||
|
||||
@@ -1184,12 +1179,12 @@ void Bin::verifyTLSBin (size_t size) const
|
||||
uint32_t objSize = getObjectSize(size);
|
||||
|
||||
if (activeBlk) {
|
||||
MALLOC_ASSERT( activeBlk->ownerTid.isCurrentThreadId(), ASSERT_TEXT );
|
||||
MALLOC_ASSERT( activeBlk->isOwnedByCurrentThread(), ASSERT_TEXT );
|
||||
MALLOC_ASSERT( activeBlk->objectSize == objSize, ASSERT_TEXT );
|
||||
#if MALLOC_DEBUG>1
|
||||
for (Block* temp = activeBlk->next; temp; temp=temp->next) {
|
||||
MALLOC_ASSERT( temp!=activeBlk, ASSERT_TEXT );
|
||||
MALLOC_ASSERT( temp->owner.own(), ASSERT_TEXT );
|
||||
MALLOC_ASSERT( temp->isOwnedByCurrentThread(), ASSERT_TEXT );
|
||||
MALLOC_ASSERT( temp->objectSize == objSize, ASSERT_TEXT );
|
||||
MALLOC_ASSERT( temp->previous->next == temp, ASSERT_TEXT );
|
||||
if (temp->next) {
|
||||
@@ -1198,7 +1193,7 @@ void Bin::verifyTLSBin (size_t size) const
|
||||
}
|
||||
for (Block* temp = activeBlk->previous; temp; temp=temp->previous) {
|
||||
MALLOC_ASSERT( temp!=activeBlk, ASSERT_TEXT );
|
||||
MALLOC_ASSERT( temp->owner.own(), ASSERT_TEXT );
|
||||
MALLOC_ASSERT( temp->isOwnedByCurrentThread(), ASSERT_TEXT );
|
||||
MALLOC_ASSERT( temp->objectSize == objSize, ASSERT_TEXT );
|
||||
MALLOC_ASSERT( temp->next->previous == temp, ASSERT_TEXT );
|
||||
if (temp->previous) {
|
||||
@@ -1221,7 +1216,7 @@ void Bin::pushTLSBin(Block* block)
|
||||
because the function is applied to partially filled blocks as well */
|
||||
unsigned int size = block->objectSize;
|
||||
|
||||
MALLOC_ASSERT( block->ownerTid.isCurrentThreadId(), ASSERT_TEXT );
|
||||
MALLOC_ASSERT( block->isOwnedByCurrentThread(), ASSERT_TEXT );
|
||||
MALLOC_ASSERT( block->objectSize != 0, ASSERT_TEXT );
|
||||
MALLOC_ASSERT( block->next == NULL, ASSERT_TEXT );
|
||||
MALLOC_ASSERT( block->previous == NULL, ASSERT_TEXT );
|
||||
@@ -1249,7 +1244,7 @@ void Bin::outofTLSBin(Block* block)
|
||||
{
|
||||
unsigned int size = block->objectSize;
|
||||
|
||||
MALLOC_ASSERT( block->ownerTid.isCurrentThreadId(), ASSERT_TEXT );
|
||||
MALLOC_ASSERT( block->isOwnedByCurrentThread(), ASSERT_TEXT );
|
||||
MALLOC_ASSERT( block->objectSize != 0, ASSERT_TEXT );
|
||||
|
||||
MALLOC_ASSERT( this, ASSERT_TEXT );
|
||||
@@ -1287,7 +1282,7 @@ Block* Bin::getPublicFreeListBlock()
|
||||
MallocMutex::scoped_lock scoped_cs(mailLock);
|
||||
block = mailbox;
|
||||
if( block ) {
|
||||
MALLOC_ASSERT( block->ownBlock(), ASSERT_TEXT );
|
||||
MALLOC_ASSERT( block->isOwnedByCurrentThread(), ASSERT_TEXT );
|
||||
MALLOC_ASSERT( !isNotForUse(block->nextPrivatizable), ASSERT_TEXT );
|
||||
mailbox = block->nextPrivatizable;
|
||||
block->nextPrivatizable = (Block*) this;
|
||||
@@ -1306,7 +1301,7 @@ bool Block::emptyEnoughToUse()
|
||||
|
||||
if (bumpPtr) {
|
||||
/* If we are still using a bump ptr for this block it is empty enough to use. */
|
||||
STAT_increment(owner, getIndex(objectSize), examineEmptyEnough);
|
||||
STAT_increment(getThreadId(), getIndex(objectSize), examineEmptyEnough);
|
||||
isFull = false;
|
||||
return 1;
|
||||
}
|
||||
@@ -1316,9 +1311,9 @@ bool Block::emptyEnoughToUse()
|
||||
isFull = (allocatedCount*objectSize > threshold)? true: false;
|
||||
#if COLLECT_STATISTICS
|
||||
if (isFull)
|
||||
STAT_increment(owner, getIndex(objectSize), examineNotEmpty);
|
||||
STAT_increment(getThreadId(), getIndex(objectSize), examineNotEmpty);
|
||||
else
|
||||
STAT_increment(owner, getIndex(objectSize), examineEmptyEnough);
|
||||
STAT_increment(getThreadId(), getIndex(objectSize), examineEmptyEnough);
|
||||
#endif
|
||||
return !isFull;
|
||||
}
|
||||
@@ -1328,21 +1323,23 @@ void Block::restoreBumpPtr()
|
||||
{
|
||||
MALLOC_ASSERT( allocatedCount == 0, ASSERT_TEXT );
|
||||
MALLOC_ASSERT( publicFreeList == NULL, ASSERT_TEXT );
|
||||
STAT_increment(owner, getIndex(objectSize), freeRestoreBumpPtr);
|
||||
STAT_increment(getThreadId(), getIndex(objectSize), freeRestoreBumpPtr);
|
||||
bumpPtr = (FreeObject *)((uintptr_t)this + slabSize - objectSize);
|
||||
freeList = NULL;
|
||||
isFull = 0;
|
||||
}
|
||||
|
||||
void Block::freeOwnObject(MemoryPool *memPool, TLSData *tls, void *object)
|
||||
void Block::freeOwnObject(void *object)
|
||||
{
|
||||
tlsPtr->markUsed();
|
||||
allocatedCount--;
|
||||
MALLOC_ASSERT( allocatedCount < (slabSize-sizeof(Block))/objectSize, ASSERT_TEXT );
|
||||
#if COLLECT_STATISTICS
|
||||
if (tls->getAllocationBin(objectSize)->getActiveBlock() != this)
|
||||
STAT_increment(owner, getIndex(objectSize), freeToInactiveBlock);
|
||||
// Note that getAllocationBin is not called on the hottest path with statistics off.
|
||||
if (tlsPtr->getAllocationBin(objectSize)->getActiveBlock() != this)
|
||||
STAT_increment(getThreadId(), getIndex(objectSize), freeToInactiveBlock);
|
||||
else
|
||||
STAT_increment(owner, getIndex(objectSize), freeToActiveBlock);
|
||||
STAT_increment(getThreadId(), getIndex(objectSize), freeToActiveBlock);
|
||||
#endif
|
||||
if (allocatedCount==0 && publicFreeList==NULL) {
|
||||
// The bump pointer is about to be restored for the block,
|
||||
@@ -1350,16 +1347,14 @@ void Block::freeOwnObject(MemoryPool *memPool, TLSData *tls, void *object)
|
||||
|
||||
// if the last object of a slab is freed, the slab cannot be marked full
|
||||
MALLOC_ASSERT(!isFull, ASSERT_TEXT);
|
||||
tls->getAllocationBin(objectSize)->processLessUsedBlock(memPool, this);
|
||||
tlsPtr->getAllocationBin(objectSize)->processLessUsedBlock(poolPtr, this);
|
||||
} else {
|
||||
FreeObject *objectToFree = findObjectToFree(object);
|
||||
objectToFree->next = freeList;
|
||||
freeList = objectToFree;
|
||||
|
||||
if (isFull) {
|
||||
if (emptyEnoughToUse())
|
||||
tls->getAllocationBin(objectSize)->moveBlockToBinFront(this);
|
||||
}
|
||||
if (isFull && emptyEnoughToUse())
|
||||
tlsPtr->getAllocationBin(objectSize)->moveBlockToFront(this);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1390,7 +1385,7 @@ void Block::freePublicObject (FreeObject *objectToFree)
|
||||
// if the block is abandoned, its nextPrivatizable pointer should be UNUSABLE
|
||||
// otherwise, it should point to the bin the block belongs to.
|
||||
// reading nextPrivatizable is thread-safe below, because:
|
||||
// 1) the executing thread atomically got localPublicFreeList==NULL and changed it to non-NULL;
|
||||
// 1) the executing thread atomically got publicFreeList==NULL and changed it to non-NULL;
|
||||
// 2) only owning thread can change it back to NULL,
|
||||
// 3) but it can not be done until the block is put to the mailbox
|
||||
// So the executing thread is now the only one that can change nextPrivatizable
|
||||
@@ -1402,15 +1397,15 @@ void Block::freePublicObject (FreeObject *objectToFree)
|
||||
theBin->mailbox = this;
|
||||
}
|
||||
}
|
||||
STAT_increment(ThreadId::get(), ThreadCommonCounters, freeToOtherThread);
|
||||
STAT_increment(owner, getIndex(objectSize), freeByOtherThread);
|
||||
STAT_increment(getThreadId(), ThreadCommonCounters, freeToOtherThread);
|
||||
STAT_increment(ownerTid, getIndex(objectSize), freeByOtherThread);
|
||||
}
|
||||
|
||||
void Block::privatizePublicFreeList()
|
||||
{
|
||||
FreeObject *temp, *localPublicFreeList;
|
||||
|
||||
MALLOC_ASSERT( ownerTid.isCurrentThreadId(), ASSERT_TEXT );
|
||||
MALLOC_ASSERT( isOwnedByCurrentThread(), ASSERT_TEXT );
|
||||
#if FREELIST_NONBLOCKING
|
||||
temp = publicFreeList;
|
||||
do {
|
||||
@@ -1421,7 +1416,7 @@ void Block::privatizePublicFreeList()
|
||||
// no backoff necessary because trying to make change, not waiting for a change
|
||||
} while( temp != localPublicFreeList );
|
||||
#else
|
||||
STAT_increment(owner, ThreadCommonCounters, lockPublicFreeList);
|
||||
STAT_increment(getThreadId(), ThreadCommonCounters, lockPublicFreeList);
|
||||
{
|
||||
MallocMutex::scoped_lock scoped_cs(publicFreeListLock);
|
||||
localPublicFreeList = publicFreeList;
|
||||
@@ -1444,19 +1439,18 @@ void Block::privatizePublicFreeList()
|
||||
/* merge with local freeList */
|
||||
temp->next = freeList;
|
||||
freeList = localPublicFreeList;
|
||||
STAT_increment(owner, getIndex(objectSize), allocPrivatized);
|
||||
STAT_increment(getThreadId(), getIndex(objectSize), allocPrivatized);
|
||||
}
|
||||
}
|
||||
|
||||
void Block::privatizeOrphaned(TLSData *tls, unsigned index)
|
||||
{
|
||||
Bin* bin = tls->bin + index;
|
||||
STAT_increment(owner, index, allocBlockPublic);
|
||||
STAT_increment(getThreadId(), index, allocBlockPublic);
|
||||
next = NULL;
|
||||
previous = NULL;
|
||||
MALLOC_ASSERT( publicFreeList!=NULL, ASSERT_TEXT );
|
||||
/* There is not a race here since no other thread owns this block */
|
||||
MALLOC_ASSERT(isOrphaned(), ASSERT_TEXT);
|
||||
markOwned(tls);
|
||||
// It is safe to change nextPrivatizable, as publicFreeList is not null
|
||||
MALLOC_ASSERT( isNotForUse(nextPrivatizable), ASSERT_TEXT );
|
||||
@@ -1474,7 +1468,7 @@ void Block::privatizeOrphaned(TLSData *tls, unsigned index)
|
||||
void Block::shareOrphaned(const Bin *bin, unsigned index)
|
||||
{
|
||||
MALLOC_ASSERT( bin, ASSERT_TEXT );
|
||||
STAT_increment(owner, index, freeBlockPublic);
|
||||
STAT_increment(getThreadId(), index, freeBlockPublic);
|
||||
markOrphaned();
|
||||
// need to set publicFreeList to non-zero, so other threads
|
||||
// will not change nextPrivatizable and it can be zeroed.
|
||||
@@ -1483,7 +1477,7 @@ void Block::shareOrphaned(const Bin *bin, unsigned index)
|
||||
#if FREELIST_NONBLOCKING
|
||||
oldval = (void*)AtomicCompareExchange((intptr_t&)publicFreeList, (intptr_t)UNUSABLE, 0);
|
||||
#else
|
||||
STAT_increment(owner, ThreadCommonCounters, lockPublicFreeList);
|
||||
STAT_increment(getThreadId(), ThreadCommonCounters, lockPublicFreeList);
|
||||
{
|
||||
MallocMutex::scoped_lock scoped_cs(publicFreeListLock);
|
||||
if ( (oldval=publicFreeList)==NULL )
|
||||
@@ -1542,13 +1536,8 @@ void Block::initEmptyBlock(TLSData *tls, size_t size)
|
||||
// each block should have the address where the head of the list of "privatizable" blocks is kept
|
||||
// the only exception is a block for boot strap which is initialized when TLS is yet NULL
|
||||
nextPrivatizable = tls? (Block*)(tls->bin + index) : NULL;
|
||||
TRACEF(( "[ScalableMalloc trace] Empty block %p is initialized, owner is %d, objectSize is %d, bumpPtr is %p\n",
|
||||
this, owner, objectSize, bumpPtr ));
|
||||
}
|
||||
|
||||
MemoryPool *Block::getMemPool() const
|
||||
{
|
||||
return tlsPtr->getMemPool();
|
||||
TRACEF(( "[ScalableMalloc trace] Empty block %p is initialized, owner is %ld, objectSize is %d, bumpPtr is %p\n",
|
||||
this, tlsPtr ? getThreadId() : -1, objectSize, bumpPtr ));
|
||||
}
|
||||
|
||||
Block *OrphanedBlocks::get(TLSData *tls, unsigned int size)
|
||||
@@ -1645,7 +1634,7 @@ void Block::makeEmpty()
|
||||
MALLOC_ASSERT( allocatedCount==0, ASSERT_TEXT );
|
||||
MALLOC_ASSERT( publicFreeList==NULL, ASSERT_TEXT );
|
||||
if (!isStartupAllocObject())
|
||||
STAT_increment(owner, getIndex(objectSize), freeBlockBack);
|
||||
STAT_increment(getThreadId(), getIndex(objectSize), freeBlockBack);
|
||||
|
||||
cleanBlockHeader();
|
||||
|
||||
@@ -1659,7 +1648,7 @@ void Block::makeEmpty()
|
||||
inline void Bin::setActiveBlock (Block *block)
|
||||
{
|
||||
// MALLOC_ASSERT( bin, ASSERT_TEXT );
|
||||
MALLOC_ASSERT( block->ownBlock(), ASSERT_TEXT );
|
||||
MALLOC_ASSERT( block->isOwnedByCurrentThread(), ASSERT_TEXT );
|
||||
// it is the caller responsibility to keep bin consistence (i.e. ensure this block is in the bin list)
|
||||
activeBlk = block;
|
||||
}
|
||||
@@ -1675,10 +1664,8 @@ inline Block* Bin::setPreviousBlockActive()
|
||||
return temp;
|
||||
}
|
||||
|
||||
inline TLSData *Block::ownBlock() const {
|
||||
if (!tlsPtr || !ownerTid.isCurrentThreadId()) return NULL;
|
||||
tlsPtr->markUsed();
|
||||
return tlsPtr;
|
||||
inline bool Block::isOwnedByCurrentThread() const {
|
||||
return tlsPtr && ownerTid.isCurrentThreadId();
|
||||
}
|
||||
|
||||
FreeObject *Block::findObjectToFree(const void *object) const
|
||||
@@ -2087,7 +2074,7 @@ FreeObject *Block::allocateFromFreeList()
|
||||
freeList = result->next;
|
||||
MALLOC_ASSERT( allocatedCount < (slabSize-sizeof(Block))/objectSize, ASSERT_TEXT );
|
||||
allocatedCount++;
|
||||
STAT_increment(owner, getIndex(objectSize), allocFreeListUsed);
|
||||
STAT_increment(getThreadId(), getIndex(objectSize), allocFreeListUsed);
|
||||
|
||||
return result;
|
||||
}
|
||||
@@ -2102,14 +2089,14 @@ FreeObject *Block::allocateFromBumpPtr()
|
||||
}
|
||||
MALLOC_ASSERT( allocatedCount < (slabSize-sizeof(Block))/objectSize, ASSERT_TEXT );
|
||||
allocatedCount++;
|
||||
STAT_increment(owner, getIndex(objectSize), allocBumpPtrUsed);
|
||||
STAT_increment(getThreadId(), getIndex(objectSize), allocBumpPtrUsed);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
inline FreeObject* Block::allocate()
|
||||
{
|
||||
MALLOC_ASSERT( ownBlock(), ASSERT_TEXT );
|
||||
MALLOC_ASSERT( isOwnedByCurrentThread(), ASSERT_TEXT );
|
||||
|
||||
/* for better cache locality, first looking in the free list. */
|
||||
if ( FreeObject *result = allocateFromFreeList() ) {
|
||||
@@ -2145,7 +2132,7 @@ size_t Block::findObjectSize(void *object) const
|
||||
return size;
|
||||
}
|
||||
|
||||
void Bin::moveBlockToBinFront(Block *block)
|
||||
void Bin::moveBlockToFront(Block *block)
|
||||
{
|
||||
/* move the block to the front of the bin */
|
||||
if (block == activeBlk) return;
|
||||
@@ -2259,8 +2246,10 @@ void *MemoryPool::getFromLLOCache(TLSData* tls, size_t size, size_t alignment)
|
||||
return NULL;
|
||||
MALLOC_ASSERT(allocationSize >= alignment, "Overflow must be checked before.");
|
||||
|
||||
if (tls)
|
||||
if (tls) {
|
||||
tls->markUsed();
|
||||
lmb = tls->lloc.get(allocationSize);
|
||||
}
|
||||
if (!lmb)
|
||||
lmb = extMemPool.mallocLargeObject(this, allocationSize);
|
||||
|
||||
@@ -2313,8 +2302,12 @@ void MemoryPool::putToLLOCache(TLSData *tls, void *object)
|
||||
// overwrite backRefIdx to simplify double free detection
|
||||
header->backRefIdx = BackRefIdx();
|
||||
|
||||
if (!tls || !tls->lloc.put(header->memoryBlock, &extMemPool))
|
||||
extMemPool.freeLargeObject(header->memoryBlock);
|
||||
if (tls) {
|
||||
tls->markUsed();
|
||||
if (tls->lloc.put(header->memoryBlock, &extMemPool))
|
||||
return;
|
||||
}
|
||||
extMemPool.freeLargeObject(header->memoryBlock);
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -2461,7 +2454,7 @@ bool isLargeObject(void *object)
|
||||
static inline bool isSmallObject (void *ptr)
|
||||
{
|
||||
Block* expectedBlock = (Block*)alignDown(ptr, slabSize);
|
||||
const BackRefIdx* idx = expectedBlock->getBackRef();
|
||||
const BackRefIdx* idx = expectedBlock->getBackRefIdx();
|
||||
|
||||
bool isSmall = expectedBlock == getBackRef(safer_dereference(idx));
|
||||
if (isSmall)
|
||||
@@ -2476,7 +2469,7 @@ static inline bool isRecognized (void* ptr)
|
||||
(isLargeObject<unknownMem>(ptr) || isSmallObject(ptr));
|
||||
}
|
||||
|
||||
static inline void freeSmallObject(MemoryPool *memPool, void *object)
|
||||
static inline void freeSmallObject(void *object)
|
||||
{
|
||||
/* mask low bits to get the block */
|
||||
Block *block = (Block *)alignDown(object, slabSize);
|
||||
@@ -2488,9 +2481,9 @@ static inline void freeSmallObject(MemoryPool *memPool, void *object)
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
if (TLSData *tls = block->ownBlock())
|
||||
block->freeOwnObject(memPool, tls, object);
|
||||
else { /* Slower path to add to the shared list, the allocatedCount is updated by the owner thread in malloc. */
|
||||
if (block->isOwnedByCurrentThread()) {
|
||||
block->freeOwnObject(object);
|
||||
} else { /* Slower path to add to the shared list, the allocatedCount is updated by the owner thread in malloc. */
|
||||
FreeObject *objectToFree = block->findObjectToFree(object);
|
||||
block->freePublicObject(objectToFree);
|
||||
}
|
||||
@@ -2506,13 +2499,14 @@ static void *internalPoolMalloc(MemoryPool* memPool, size_t size)
|
||||
if (!size) size = sizeof(size_t);
|
||||
|
||||
TLSData *tls = memPool->getTLS(/*create=*/true);
|
||||
/*
|
||||
* Use Large Object Allocation
|
||||
*/
|
||||
|
||||
/* Allocate a large object */
|
||||
if (size >= minLargeObjectSize)
|
||||
return memPool->getFromLLOCache(tls, size, largeObjectAlignment);
|
||||
|
||||
if (!tls) return NULL;
|
||||
|
||||
tls->markUsed();
|
||||
/*
|
||||
* Get an element in thread-local array corresponding to the given size;
|
||||
* It keeps ptr to the active block for allocations of this size
|
||||
@@ -2534,7 +2528,7 @@ static void *internalPoolMalloc(MemoryPool* memPool, size_t size)
|
||||
mallocBlock = bin->getPublicFreeListBlock();
|
||||
if (mallocBlock) {
|
||||
if (mallocBlock->emptyEnoughToUse()) {
|
||||
bin->moveBlockToBinFront(mallocBlock);
|
||||
bin->moveBlockToFront(mallocBlock);
|
||||
}
|
||||
MALLOC_ASSERT( mallocBlock->freeListNonNull(), ASSERT_TEXT );
|
||||
if ( FreeObject *result = mallocBlock->allocateFromFreeList() )
|
||||
@@ -2593,7 +2587,7 @@ static bool internalPoolFree(MemoryPool *memPool, void *object, size_t size)
|
||||
if (size >= minLargeObjectSize || isLargeObject<ourMem>(object))
|
||||
memPool->putToLLOCache(memPool->getTLS(/*create=*/false), object);
|
||||
else
|
||||
freeSmallObject(memPool, object);
|
||||
freeSmallObject(object);
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -2893,7 +2887,7 @@ extern "C" void __TBB_malloc_safer_free(void *object, void (*original_free)(void
|
||||
defaultMemPool->putToLLOCache(tls, object);
|
||||
return;
|
||||
} else if (isSmallObject(object)) {
|
||||
freeSmallObject(defaultMemPool, object);
|
||||
freeSmallObject(object);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -73,7 +73,7 @@
|
||||
|
||||
#define COLLECT_STATISTICS ( MALLOC_DEBUG && MALLOCENV_COLLECT_STATISTICS )
|
||||
#ifndef USE_INTERNAL_TID
|
||||
#define USE_INTERNAL_TID COLLECT_STATISTICS
|
||||
#define USE_INTERNAL_TID COLLECT_STATISTICS || MALLOC_TRACE
|
||||
#endif
|
||||
|
||||
#include "Statistics.h"
|
||||
|
||||
+2
-2
@@ -745,7 +745,7 @@ public:
|
||||
x = x*a + 1;
|
||||
return r;
|
||||
}
|
||||
FastRandom( unsigned seed ) {
|
||||
explicit FastRandom( unsigned seed ) {
|
||||
x = seed;
|
||||
a = Primes[seed % (sizeof(Primes) / sizeof(Primes[0]))];
|
||||
}
|
||||
@@ -787,7 +787,7 @@ public:
|
||||
class DummyBody {
|
||||
int m_numIters;
|
||||
public:
|
||||
DummyBody( int iters ) : m_numIters( iters ) {}
|
||||
explicit DummyBody( int iters ) : m_numIters( iters ) {}
|
||||
void operator()( int ) const {
|
||||
for ( volatile int i = 0; i < m_numIters; ++i ) {}
|
||||
}
|
||||
|
||||
@@ -18,7 +18,7 @@
|
||||
|
||||
*/
|
||||
|
||||
// Header that includes TSX-specific test functions
|
||||
// Header that includes Intel(R) Transactional Synchronization Extensions (Intel(R) TSX) specific test functions
|
||||
|
||||
#if __TBB_TSX_AVAILABLE
|
||||
#define __TBB_TSX_TESTING_ENABLED_FOR_THIS_COMPILER (__INTEL_COMPILER || __GNUC__ || _MSC_VER || __SUNPRO_CC)
|
||||
|
||||
@@ -625,13 +625,12 @@ void TestEntries()
|
||||
|
||||
rml::MemoryPool *CreateUsablePool(size_t size)
|
||||
{
|
||||
using namespace rml;
|
||||
MemoryPool *pool;
|
||||
MemPoolPolicy okPolicy(getMemMalloc, putMemFree);
|
||||
rml::MemoryPool *pool;
|
||||
rml::MemPoolPolicy okPolicy(getMemMalloc, putMemFree);
|
||||
|
||||
putMemAll = getMemAll = getMemSuccessful = 0;
|
||||
MemPoolError res = pool_create_v1(0, &okPolicy, &pool);
|
||||
if (res != POOL_OK) {
|
||||
rml::MemPoolError res = pool_create_v1(0, &okPolicy, &pool);
|
||||
if (res != rml::POOL_OK) {
|
||||
ASSERT(!getMemAll && !putMemAll, "No callbacks after fail.");
|
||||
return NULL;
|
||||
}
|
||||
@@ -652,10 +651,9 @@ rml::MemoryPool *CreateUsablePool(size_t size)
|
||||
|
||||
void CheckPoolLeaks(size_t poolsAlwaysAvailable)
|
||||
{
|
||||
using namespace rml;
|
||||
const size_t MAX_POOLS = 16*1000;
|
||||
const int ITERS = 20, CREATED_STABLE = 3;
|
||||
MemoryPool *pools[MAX_POOLS];
|
||||
rml::MemoryPool *pools[MAX_POOLS];
|
||||
size_t created, maxCreated = MAX_POOLS;
|
||||
int maxNotChangedCnt = 0;
|
||||
|
||||
@@ -663,7 +661,7 @@ void CheckPoolLeaks(size_t poolsAlwaysAvailable)
|
||||
// can be stabilized and still stable CREATED_STABLE times
|
||||
for (int j=0; j<ITERS && maxNotChangedCnt<CREATED_STABLE; j++) {
|
||||
for (created=0; created<maxCreated; created++) {
|
||||
MemoryPool *p = CreateUsablePool(1024);
|
||||
rml::MemoryPool *p = CreateUsablePool(1024);
|
||||
if (!p)
|
||||
break;
|
||||
pools[created] = p;
|
||||
@@ -685,22 +683,20 @@ void CheckPoolLeaks(size_t poolsAlwaysAvailable)
|
||||
|
||||
void TestPoolCreation()
|
||||
{
|
||||
using namespace rml;
|
||||
|
||||
putMemAll = getMemAll = getMemSuccessful = 0;
|
||||
|
||||
MemPoolPolicy nullPolicy(NULL, putMemFree),
|
||||
rml::MemPoolPolicy nullPolicy(NULL, putMemFree),
|
||||
emptyFreePolicy(getMemMalloc, NULL),
|
||||
okPolicy(getMemMalloc, putMemFree);
|
||||
MemoryPool *pool;
|
||||
rml::MemoryPool *pool;
|
||||
|
||||
MemPoolError res = pool_create_v1(0, &nullPolicy, &pool);
|
||||
ASSERT(res==INVALID_POLICY, "pool with empty pAlloc can't be created");
|
||||
rml::MemPoolError res = pool_create_v1(0, &nullPolicy, &pool);
|
||||
ASSERT(res==rml::INVALID_POLICY, "pool with empty pAlloc can't be created");
|
||||
res = pool_create_v1(0, &emptyFreePolicy, &pool);
|
||||
ASSERT(res==INVALID_POLICY, "pool with empty pFree can't be created");
|
||||
ASSERT(res==rml::INVALID_POLICY, "pool with empty pFree can't be created");
|
||||
ASSERT(!putMemAll && !getMemAll, "no callback calls are expected");
|
||||
res = pool_create_v1(0, &okPolicy, &pool);
|
||||
ASSERT(res==POOL_OK, NULL);
|
||||
ASSERT(res==rml::POOL_OK, NULL);
|
||||
bool ok = pool_destroy(pool);
|
||||
ASSERT(ok, NULL);
|
||||
ASSERT(putMemAll == getMemSuccessful, "no leaks after pool_destroy");
|
||||
@@ -717,16 +713,42 @@ struct AllocatedObject {
|
||||
rml::MemoryPool *pool;
|
||||
};
|
||||
|
||||
// TODO: extend testing of pool_identify() in concurrent environment
|
||||
const size_t BUF_SIZE = 1024*1024;
|
||||
|
||||
class PoolIdentityCheck : NoAssign {
|
||||
rml::MemoryPool** const pools;
|
||||
AllocatedObject** const objs;
|
||||
public:
|
||||
PoolIdentityCheck(rml::MemoryPool** p, AllocatedObject** o) : pools(p), objs(o) {}
|
||||
void operator()(int id) const {
|
||||
objs[id] = (AllocatedObject*)pool_malloc(pools[id], BUF_SIZE/2);
|
||||
ASSERT(objs[id], NULL);
|
||||
rml::MemoryPool *act_pool = rml::pool_identify(objs[id]);
|
||||
ASSERT(act_pool == pools[id], NULL);
|
||||
|
||||
for (size_t total=0; total<2*BUF_SIZE; total+=256) {
|
||||
AllocatedObject *o = (AllocatedObject*)pool_malloc(pools[id], 256);
|
||||
ASSERT(o, NULL);
|
||||
act_pool = rml::pool_identify(o);
|
||||
ASSERT(act_pool == pools[id], NULL);
|
||||
pool_free(act_pool, o);
|
||||
}
|
||||
if( id&1 ) { // make every second returned object "small"
|
||||
pool_free(act_pool, objs[id]);
|
||||
objs[id] = (AllocatedObject*)pool_malloc(pools[id], 16);
|
||||
ASSERT(objs[id], NULL);
|
||||
}
|
||||
objs[id]->pool = act_pool;
|
||||
}
|
||||
};
|
||||
|
||||
void TestPoolDetection()
|
||||
{
|
||||
using namespace rml;
|
||||
const int POOLS = 4;
|
||||
rml::MemPoolPolicy pol(fixedBufGetMem, NULL, 0, /*fixedSizePool=*/true,
|
||||
/*keepMemTillDestroy=*/false);
|
||||
rml::MemoryPool *pools[POOLS];
|
||||
const size_t BUF_SIZE = 1024*1024;
|
||||
FixedPoolHead<BUF_SIZE> head[POOLS];
|
||||
FixedPoolHead<BUF_SIZE*POOLS> head[POOLS];
|
||||
AllocatedObject *objs[POOLS];
|
||||
|
||||
for (int i=0; i<POOLS; i++)
|
||||
@@ -734,23 +756,14 @@ void TestPoolDetection()
|
||||
// if object somehow released to different pools, subsequent allocation
|
||||
// from affected pools became impossible
|
||||
for (int k=0; k<10; k++) {
|
||||
PoolIdentityCheck check(pools, objs);
|
||||
if( k&1 )
|
||||
NativeParallelFor( POOLS, check);
|
||||
else
|
||||
for (int i=0; i<POOLS; i++) check(i);
|
||||
|
||||
for (int i=0; i<POOLS; i++) {
|
||||
objs[i] = (AllocatedObject*)pool_malloc(pools[i], BUF_SIZE/2);
|
||||
ASSERT(objs[i], NULL);
|
||||
MemoryPool *act_pool = pool_identify(objs[i]);
|
||||
ASSERT(act_pool == pools[i], NULL);
|
||||
objs[i]->pool = act_pool;
|
||||
for (size_t total=0; total<2*BUF_SIZE; total+=256) {
|
||||
AllocatedObject *o = (AllocatedObject*)pool_malloc(pools[i], 256);
|
||||
ASSERT(o, NULL);
|
||||
act_pool = pool_identify(o);
|
||||
ASSERT(act_pool == pools[i], NULL);
|
||||
o->pool = act_pool;
|
||||
pool_free(act_pool, o);
|
||||
}
|
||||
}
|
||||
for (int i=0; i<POOLS; i++) {
|
||||
rml::MemoryPool *p = pool_identify(objs[i]);
|
||||
rml::MemoryPool *p = rml::pool_identify(objs[i]);
|
||||
ASSERT(p == objs[i]->pool, NULL);
|
||||
pool_free(p, objs[i]);
|
||||
}
|
||||
|
||||
@@ -22,6 +22,8 @@
|
||||
#include "tbb/queuing_mutex.h"
|
||||
#include "tbb/queuing_rw_mutex.h"
|
||||
#include "tbb/spin_rw_mutex.h"
|
||||
#include "tbb/mutex.h"
|
||||
|
||||
#include "tbb/tick_count.h"
|
||||
#include "tbb/atomic.h"
|
||||
|
||||
@@ -211,6 +213,7 @@ int TestMain () {
|
||||
Test<tbb::queuing_mutex>( "queuing_mutex", p );
|
||||
Test<tbb::queuing_rw_mutex>( "queuing_rw_mutex", p );
|
||||
Test<tbb::spin_rw_mutex>( "spin_rw_mutex", p );
|
||||
Test<tbb::mutex>( "mutex", p );
|
||||
TestReaderWriter<tbb::queuing_rw_mutex>( "queuing_rw_mutex", p );
|
||||
TestReaderWriter<tbb::spin_rw_mutex>( "spin_rw_mutex", p );
|
||||
}
|
||||
|
||||
@@ -240,7 +240,7 @@ int main(int argc, char *argv[] ) {
|
||||
void initialize_strings_vector(std::vector <string_pair>* vector)
|
||||
{
|
||||
vector->push_back(string_pair("TBB: VERSION\t\t2017.0", required)); // check TBB_VERSION
|
||||
vector->push_back(string_pair("TBB: INTERFACE VERSION\t9104", required)); // check TBB_INTERFACE_VERSION
|
||||
vector->push_back(string_pair("TBB: INTERFACE VERSION\t9105", required)); // check TBB_INTERFACE_VERSION
|
||||
vector->push_back(string_pair("TBB: BUILD_DATE", required));
|
||||
vector->push_back(string_pair("TBB: BUILD_HOST", required));
|
||||
vector->push_back(string_pair("TBB: BUILD_OS", required));
|
||||
|
||||
Reference in New Issue
Block a user