Compare commits

..
61 changed files with 2458 additions and 651 deletions
+28 -2
View File
@@ -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.
+8 -9
View File
@@ -1,18 +1,17 @@
# Intel(R) Threading Building Blocks 2017 Update 4
[![Stable release](https://img.shields.io/badge/version-2017_U4-green.svg)] (https://github.com/01org/tbb/releases/tag/2017_U4)
# Intel(R) Threading Building Blocks 2017 Update 5
[![Stable release](https://img.shields.io/badge/version-2017_U5-green.svg)](https://github.com/01org/tbb/releases/tag/2017_U5)
[![Apache License Version 2.0](https://img.shields.io/badge/license-Apache_2.0-green.svg)](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
View File
@@ -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
View File
@@ -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
View File
@@ -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");
}
+4 -3
View File
@@ -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
+1
View File
@@ -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
+1
View File
@@ -81,6 +81,7 @@ DYLIB_KEY = /DLL
EXPORT_KEY = /DEF:
NODEFAULTLIB_KEY = /Zl
NOINTRINSIC_KEY = /Oi-
BIGOBJ_KEY = /bigobj
ifneq (,$(codecov))
+4 -3
View File
@@ -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.
+2 -2
View File
@@ -133,7 +133,7 @@ class&#160;</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&#160;</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">
+1 -1
View File
@@ -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&lt; T &gt;</a>)</td><td class="entry"><a class="el" href="a00033.html">tbb::combinable&lt; T &gt;</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&lt; T &gt;</a>)</td><td class="entry"><a class="el" href="a00033.html">tbb::combinable&lt; T &gt;</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&lt; T &gt;</a>)</td><td class="entry"><a class="el" href="a00033.html">tbb::combinable&lt; T &gt;</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&lt; T &gt;</a>)</td><td class="entry"><a class="el" href="a00033.html">tbb::combinable&lt; T &gt;</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 &amp;other) (defined in <a class="el" href="a00033.html">tbb::combinable&lt; T &gt;</a>)</td><td class="entry"><a class="el" href="a00033.html">tbb::combinable&lt; T &gt;</a></td><td class="entry"><span class="mlabel">inline</span></td></tr>
<tr bgcolor="#f0f0f0" class="even"><td class="entry"><b>combinable</b>(combinable &amp;&amp;other) (defined in <a class="el" href="a00033.html">tbb::combinable&lt; T &gt;</a>)</td><td class="entry"><a class="el" href="a00033.html">tbb::combinable&lt; T &gt;</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&lt; T &gt;</a>)</td><td class="entry"><a class="el" href="a00033.html">tbb::combinable&lt; T &gt;</a></td><td class="entry"><span class="mlabel">inline</span></td></tr>
+1 -1
View File
@@ -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>
+1 -1
View File
@@ -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 &amp;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 &amp;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>
+1 -1
View File
@@ -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&lt; Key, T, HashCompare, A &gt;</a>)</td><td class="entry"><a class="el" href="a00036.html">tbb::interface5::concurrent_hash_map&lt; Key, T, HashCompare, A &gt;</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&lt; Key, T, HashCompare, A &gt;</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&lt; Key, T, HashCompare, A &gt;</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 &amp;a=allocator_type())</td><td class="entry"><a class="el" href="a00036.html">tbb::interface5::concurrent_hash_map&lt; Key, T, HashCompare, A &gt;</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 &amp;a=allocator_type())</td><td class="entry"><a class="el" href="a00036.html">tbb::interface5::concurrent_hash_map&lt; Key, T, HashCompare, A &gt;</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 &amp;a=allocator_type())</td><td class="entry"><a class="el" href="a00036.html">tbb::interface5::concurrent_hash_map&lt; Key, T, HashCompare, A &gt;</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 &amp;table, const allocator_type &amp;a=allocator_type())</td><td class="entry"><a class="el" href="a00036.html">tbb::interface5::concurrent_hash_map&lt; Key, T, HashCompare, A &gt;</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 &amp;&amp;table)</td><td class="entry"><a class="el" href="a00036.html">tbb::interface5::concurrent_hash_map&lt; Key, T, HashCompare, A &gt;</a></td><td class="entry"><span class="mlabel">inline</span></td></tr>
+1 -1
View File
@@ -48,7 +48,7 @@
<tr bgcolor="#f0f0f0"><td class="entry"><b>at</b>(const key_type &amp;key) (defined in <a class="el" href="a00040.html">tbb::interface5::concurrent_unordered_map&lt; Key, T, Hasher, Key_equality, Allocator &gt;</a>)</td><td class="entry"><a class="el" href="a00040.html">tbb::interface5::concurrent_unordered_map&lt; Key, T, Hasher, Key_equality, Allocator &gt;</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 &amp;key) const (defined in <a class="el" href="a00040.html">tbb::interface5::concurrent_unordered_map&lt; Key, T, Hasher, Key_equality, Allocator &gt;</a>)</td><td class="entry"><a class="el" href="a00040.html">tbb::interface5::concurrent_unordered_map&lt; Key, T, Hasher, Key_equality, Allocator &gt;</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 &amp;_Hasher=hasher(), const key_equal &amp;_Key_equality=key_equal(), const allocator_type &amp;a=allocator_type()) (defined in <a class="el" href="a00040.html">tbb::interface5::concurrent_unordered_map&lt; Key, T, Hasher, Key_equality, Allocator &gt;</a>)</td><td class="entry"><a class="el" href="a00040.html">tbb::interface5::concurrent_unordered_map&lt; Key, T, Hasher, Key_equality, Allocator &gt;</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 &amp;a) (defined in <a class="el" href="a00040.html">tbb::interface5::concurrent_unordered_map&lt; Key, T, Hasher, Key_equality, Allocator &gt;</a>)</td><td class="entry"><a class="el" href="a00040.html">tbb::interface5::concurrent_unordered_map&lt; Key, T, Hasher, Key_equality, Allocator &gt;</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 &amp;a) (defined in <a class="el" href="a00040.html">tbb::interface5::concurrent_unordered_map&lt; Key, T, Hasher, Key_equality, Allocator &gt;</a>)</td><td class="entry"><a class="el" href="a00040.html">tbb::interface5::concurrent_unordered_map&lt; Key, T, Hasher, Key_equality, Allocator &gt;</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 &amp;_Hasher=hasher(), const key_equal &amp;_Key_equality=key_equal(), const allocator_type &amp;a=allocator_type()) (defined in <a class="el" href="a00040.html">tbb::interface5::concurrent_unordered_map&lt; Key, T, Hasher, Key_equality, Allocator &gt;</a>)</td><td class="entry"><a class="el" href="a00040.html">tbb::interface5::concurrent_unordered_map&lt; Key, T, Hasher, Key_equality, Allocator &gt;</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&lt; value_type &gt; il, size_type n_of_buckets=base_type::initial_bucket_number, const hasher &amp;_Hasher=hasher(), const key_equal &amp;_Key_equality=key_equal(), const allocator_type &amp;a=allocator_type())</td><td class="entry"><a class="el" href="a00040.html">tbb::interface5::concurrent_unordered_map&lt; Key, T, Hasher, Key_equality, Allocator &gt;</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 &amp;table) (defined in <a class="el" href="a00040.html">tbb::interface5::concurrent_unordered_map&lt; Key, T, Hasher, Key_equality, Allocator &gt;</a>)</td><td class="entry"><a class="el" href="a00040.html">tbb::interface5::concurrent_unordered_map&lt; Key, T, Hasher, Key_equality, Allocator &gt;</a></td><td class="entry"><span class="mlabel">inline</span></td></tr>
+1 -1
View File
@@ -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&lt; Key, T, Hasher, Key_equality, Allocator &gt;</a>)</td><td class="entry"><a class="el" href="a00042.html">tbb::interface5::concurrent_unordered_multimap&lt; Key, T, Hasher, Key_equality, Allocator &gt;</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 &amp;_Hasher=hasher(), const key_equal &amp;_Key_equality=key_equal(), const allocator_type &amp;a=allocator_type()) (defined in <a class="el" href="a00042.html">tbb::interface5::concurrent_unordered_multimap&lt; Key, T, Hasher, Key_equality, Allocator &gt;</a>)</td><td class="entry"><a class="el" href="a00042.html">tbb::interface5::concurrent_unordered_multimap&lt; Key, T, Hasher, Key_equality, Allocator &gt;</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 &amp;a) (defined in <a class="el" href="a00042.html">tbb::interface5::concurrent_unordered_multimap&lt; Key, T, Hasher, Key_equality, Allocator &gt;</a>)</td><td class="entry"><a class="el" href="a00042.html">tbb::interface5::concurrent_unordered_multimap&lt; Key, T, Hasher, Key_equality, Allocator &gt;</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 &amp;a) (defined in <a class="el" href="a00042.html">tbb::interface5::concurrent_unordered_multimap&lt; Key, T, Hasher, Key_equality, Allocator &gt;</a>)</td><td class="entry"><a class="el" href="a00042.html">tbb::interface5::concurrent_unordered_multimap&lt; Key, T, Hasher, Key_equality, Allocator &gt;</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 &amp;_Hasher=hasher(), const key_equal &amp;_Key_equality=key_equal(), const allocator_type &amp;a=allocator_type()) (defined in <a class="el" href="a00042.html">tbb::interface5::concurrent_unordered_multimap&lt; Key, T, Hasher, Key_equality, Allocator &gt;</a>)</td><td class="entry"><a class="el" href="a00042.html">tbb::interface5::concurrent_unordered_multimap&lt; Key, T, Hasher, Key_equality, Allocator &gt;</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&lt; value_type &gt; il, size_type n_of_buckets=base_type::initial_bucket_number, const hasher &amp;_Hasher=hasher(), const key_equal &amp;_Key_equality=key_equal(), const allocator_type &amp;a=allocator_type())</td><td class="entry"><a class="el" href="a00042.html">tbb::interface5::concurrent_unordered_multimap&lt; Key, T, Hasher, Key_equality, Allocator &gt;</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 &amp;table) (defined in <a class="el" href="a00042.html">tbb::interface5::concurrent_unordered_multimap&lt; Key, T, Hasher, Key_equality, Allocator &gt;</a>)</td><td class="entry"><a class="el" href="a00042.html">tbb::interface5::concurrent_unordered_multimap&lt; Key, T, Hasher, Key_equality, Allocator &gt;</a></td><td class="entry"><span class="mlabel">inline</span></td></tr>
+1 -1
View File
@@ -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&lt; Key, Hasher, Key_equality, Allocator &gt;</a>)</td><td class="entry"><a class="el" href="a00044.html">tbb::interface5::concurrent_unordered_set&lt; Key, Hasher, Key_equality, Allocator &gt;</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 &amp;a_hasher=hasher(), const key_equal &amp;a_keyeq=key_equal(), const allocator_type &amp;a=allocator_type()) (defined in <a class="el" href="a00044.html">tbb::interface5::concurrent_unordered_set&lt; Key, Hasher, Key_equality, Allocator &gt;</a>)</td><td class="entry"><a class="el" href="a00044.html">tbb::interface5::concurrent_unordered_set&lt; Key, Hasher, Key_equality, Allocator &gt;</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 &amp;a) (defined in <a class="el" href="a00044.html">tbb::interface5::concurrent_unordered_set&lt; Key, Hasher, Key_equality, Allocator &gt;</a>)</td><td class="entry"><a class="el" href="a00044.html">tbb::interface5::concurrent_unordered_set&lt; Key, Hasher, Key_equality, Allocator &gt;</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 &amp;a) (defined in <a class="el" href="a00044.html">tbb::interface5::concurrent_unordered_set&lt; Key, Hasher, Key_equality, Allocator &gt;</a>)</td><td class="entry"><a class="el" href="a00044.html">tbb::interface5::concurrent_unordered_set&lt; Key, Hasher, Key_equality, Allocator &gt;</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 &amp;a_hasher=hasher(), const key_equal &amp;a_keyeq=key_equal(), const allocator_type &amp;a=allocator_type()) (defined in <a class="el" href="a00044.html">tbb::interface5::concurrent_unordered_set&lt; Key, Hasher, Key_equality, Allocator &gt;</a>)</td><td class="entry"><a class="el" href="a00044.html">tbb::interface5::concurrent_unordered_set&lt; Key, Hasher, Key_equality, Allocator &gt;</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&lt; value_type &gt; il, size_type n_of_buckets=base_type::initial_bucket_number, const hasher &amp;a_hasher=hasher(), const key_equal &amp;a_keyeq=key_equal(), const allocator_type &amp;a=allocator_type())</td><td class="entry"><a class="el" href="a00044.html">tbb::interface5::concurrent_unordered_set&lt; Key, Hasher, Key_equality, Allocator &gt;</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 &amp;table) (defined in <a class="el" href="a00044.html">tbb::interface5::concurrent_unordered_set&lt; Key, Hasher, Key_equality, Allocator &gt;</a>)</td><td class="entry"><a class="el" href="a00044.html">tbb::interface5::concurrent_unordered_set&lt; Key, Hasher, Key_equality, Allocator &gt;</a></td><td class="entry"><span class="mlabel">inline</span></td></tr>
+1 -1
View File
@@ -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&lt; Key, Hasher, Key_equality, Allocator &gt;</a>)</td><td class="entry"><a class="el" href="a00043.html">tbb::interface5::concurrent_unordered_multiset&lt; Key, Hasher, Key_equality, Allocator &gt;</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 &amp;_Hasher=hasher(), const key_equal &amp;_Key_equality=key_equal(), const allocator_type &amp;a=allocator_type()) (defined in <a class="el" href="a00043.html">tbb::interface5::concurrent_unordered_multiset&lt; Key, Hasher, Key_equality, Allocator &gt;</a>)</td><td class="entry"><a class="el" href="a00043.html">tbb::interface5::concurrent_unordered_multiset&lt; Key, Hasher, Key_equality, Allocator &gt;</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 &amp;a) (defined in <a class="el" href="a00043.html">tbb::interface5::concurrent_unordered_multiset&lt; Key, Hasher, Key_equality, Allocator &gt;</a>)</td><td class="entry"><a class="el" href="a00043.html">tbb::interface5::concurrent_unordered_multiset&lt; Key, Hasher, Key_equality, Allocator &gt;</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 &amp;a) (defined in <a class="el" href="a00043.html">tbb::interface5::concurrent_unordered_multiset&lt; Key, Hasher, Key_equality, Allocator &gt;</a>)</td><td class="entry"><a class="el" href="a00043.html">tbb::interface5::concurrent_unordered_multiset&lt; Key, Hasher, Key_equality, Allocator &gt;</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 &amp;_Hasher=hasher(), const key_equal &amp;_Key_equality=key_equal(), const allocator_type &amp;a=allocator_type()) (defined in <a class="el" href="a00043.html">tbb::interface5::concurrent_unordered_multiset&lt; Key, Hasher, Key_equality, Allocator &gt;</a>)</td><td class="entry"><a class="el" href="a00043.html">tbb::interface5::concurrent_unordered_multiset&lt; Key, Hasher, Key_equality, Allocator &gt;</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&lt; value_type &gt; il, size_type n_of_buckets=base_type::initial_bucket_number, const hasher &amp;a_hasher=hasher(), const key_equal &amp;a_keyeq=key_equal(), const allocator_type &amp;a=allocator_type())</td><td class="entry"><a class="el" href="a00043.html">tbb::interface5::concurrent_unordered_multiset&lt; Key, Hasher, Key_equality, Allocator &gt;</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 &amp;table) (defined in <a class="el" href="a00043.html">tbb::interface5::concurrent_unordered_multiset&lt; Key, Hasher, Key_equality, Allocator &gt;</a>)</td><td class="entry"><a class="el" href="a00043.html">tbb::interface5::concurrent_unordered_multiset&lt; Key, Hasher, Key_equality, Allocator &gt;</a></td><td class="entry"><span class="mlabel">inline</span></td></tr>
+3 -3
View File
@@ -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&lt; T, Allocator, ETS_key_type &gt;</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&lt; T, Allocator, ETS_key_type &gt;</a>)</td><td class="entry"><a class="el" href="a00058.html">tbb::interface6::enumerable_thread_specific&lt; T, Allocator, ETS_key_type &gt;</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&lt; T, Allocator, ETS_key_type &gt;</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&lt; T, Allocator, ETS_key_type &gt;</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 &amp;exemplar)</td><td class="entry"><a class="el" href="a00058.html">tbb::interface6::enumerable_thread_specific&lt; T, Allocator, ETS_key_type &gt;</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 &amp;&amp;exemplar) (defined in <a class="el" href="a00058.html">tbb::interface6::enumerable_thread_specific&lt; T, Allocator, ETS_key_type &gt;</a>)</td><td class="entry"><a class="el" href="a00058.html">tbb::interface6::enumerable_thread_specific&lt; T, Allocator, ETS_key_type &gt;</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&lt; T, Allocator, ETS_key_type &gt;</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 &amp;exemplar)</td><td class="entry"><a class="el" href="a00058.html">tbb::interface6::enumerable_thread_specific&lt; T, Allocator, ETS_key_type &gt;</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 &amp;&amp;exemplar) (defined in <a class="el" href="a00058.html">tbb::interface6::enumerable_thread_specific&lt; T, Allocator, ETS_key_type &gt;</a>)</td><td class="entry"><a class="el" href="a00058.html">tbb::interface6::enumerable_thread_specific&lt; T, Allocator, ETS_key_type &gt;</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 &amp;&amp;arg1, P &amp;&amp;...args)</td><td class="entry"><a class="el" href="a00058.html">tbb::interface6::enumerable_thread_specific&lt; T, Allocator, ETS_key_type &gt;</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 &amp;other) (defined in <a class="el" href="a00058.html">tbb::interface6::enumerable_thread_specific&lt; T, Allocator, ETS_key_type &gt;</a>)</td><td class="entry"><a class="el" href="a00058.html">tbb::interface6::enumerable_thread_specific&lt; T, Allocator, ETS_key_type &gt;</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&lt; T, Alloc, Cachetype &gt; &amp;other) (defined in <a class="el" href="a00058.html">tbb::interface6::enumerable_thread_specific&lt; T, Allocator, ETS_key_type &gt;</a>)</td><td class="entry"><a class="el" href="a00058.html">tbb::interface6::enumerable_thread_specific&lt; T, Allocator, ETS_key_type &gt;</a></td><td class="entry"><span class="mlabel">inline</span></td></tr>
+1 -1
View File
@@ -54,7 +54,7 @@
<tr bgcolor="#f0f0f0"><td class="entry"><b>end</b>() (defined in <a class="el" href="a00063.html">tbb::interface6::flattened2d&lt; Container &gt;</a>)</td><td class="entry"><a class="el" href="a00063.html">tbb::interface6::flattened2d&lt; Container &gt;</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&lt; Container &gt;</a>)</td><td class="entry"><a class="el" href="a00063.html">tbb::interface6::flattened2d&lt; Container &gt;</a></td><td class="entry"><span class="mlabel">inline</span></td></tr>
<tr bgcolor="#f0f0f0"><td class="entry"><b>flattened2d</b>(const Container &amp;c, typename Container::const_iterator b, typename Container::const_iterator e) (defined in <a class="el" href="a00063.html">tbb::interface6::flattened2d&lt; Container &gt;</a>)</td><td class="entry"><a class="el" href="a00063.html">tbb::interface6::flattened2d&lt; Container &gt;</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 &amp;c) (defined in <a class="el" href="a00063.html">tbb::interface6::flattened2d&lt; Container &gt;</a>)</td><td class="entry"><a class="el" href="a00063.html">tbb::interface6::flattened2d&lt; Container &gt;</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 &amp;c) (defined in <a class="el" href="a00063.html">tbb::interface6::flattened2d&lt; Container &gt;</a>)</td><td class="entry"><a class="el" href="a00063.html">tbb::interface6::flattened2d&lt; Container &gt;</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&lt; Container &gt;</a>)</td><td class="entry"><a class="el" href="a00063.html">tbb::interface6::flattened2d&lt; Container &gt;</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&lt; Container &gt;</a>)</td><td class="entry"><a class="el" href="a00063.html">tbb::interface6::flattened2d&lt; Container &gt;</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&lt; Container &gt;</a>)</td><td class="entry"><a class="el" href="a00063.html">tbb::interface6::flattened2d&lt; Container &gt;</a></td><td class="entry"></td></tr>
+1 -1
View File
@@ -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&lt; T, P &gt;</a>)</td><td class="entry"><a class="el" href="a00077.html">tbb::interface6::memory_pool_allocator&lt; T, P &gt;</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&lt; T, P &gt;</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&lt; T, P &gt;</a>)</td><td class="entry"><a class="el" href="a00077.html">tbb::interface6::memory_pool_allocator&lt; T, P &gt;</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 &amp;pool) (defined in <a class="el" href="a00077.html">tbb::interface6::memory_pool_allocator&lt; T, P &gt;</a>)</td><td class="entry"><a class="el" href="a00077.html">tbb::interface6::memory_pool_allocator&lt; T, P &gt;</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 &amp;pool) (defined in <a class="el" href="a00077.html">tbb::interface6::memory_pool_allocator&lt; T, P &gt;</a>)</td><td class="entry"><a class="el" href="a00077.html">tbb::interface6::memory_pool_allocator&lt; T, P &gt;</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 &amp;src) (defined in <a class="el" href="a00077.html">tbb::interface6::memory_pool_allocator&lt; T, P &gt;</a>)</td><td class="entry"><a class="el" href="a00077.html">tbb::interface6::memory_pool_allocator&lt; T, P &gt;</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&lt; U, P &gt; &amp;src) (defined in <a class="el" href="a00077.html">tbb::interface6::memory_pool_allocator&lt; T, P &gt;</a>)</td><td class="entry"><a class="el" href="a00077.html">tbb::interface6::memory_pool_allocator&lt; T, P &gt;</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&lt; T, P &gt;</a>)</td><td class="entry"><a class="el" href="a00077.html">tbb::interface6::memory_pool_allocator&lt; T, P &gt;</a></td><td class="entry"><span class="mlabel">protected</span></td></tr>
+1 -1
View File
@@ -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&lt; void, P &gt;</a>)</td><td class="entry"><a class="el" href="a00078.html">tbb::interface6::memory_pool_allocator&lt; void, P &gt;</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&lt; void, P &gt;</a>)</td><td class="entry"><a class="el" href="a00078.html">tbb::interface6::memory_pool_allocator&lt; void, P &gt;</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 &amp;pool) (defined in <a class="el" href="a00078.html">tbb::interface6::memory_pool_allocator&lt; void, P &gt;</a>)</td><td class="entry"><a class="el" href="a00078.html">tbb::interface6::memory_pool_allocator&lt; void, P &gt;</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 &amp;pool) (defined in <a class="el" href="a00078.html">tbb::interface6::memory_pool_allocator&lt; void, P &gt;</a>)</td><td class="entry"><a class="el" href="a00078.html">tbb::interface6::memory_pool_allocator&lt; void, P &gt;</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 &amp;src) (defined in <a class="el" href="a00078.html">tbb::interface6::memory_pool_allocator&lt; void, P &gt;</a>)</td><td class="entry"><a class="el" href="a00078.html">tbb::interface6::memory_pool_allocator&lt; void, P &gt;</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&lt; U, P &gt; &amp;src) (defined in <a class="el" href="a00078.html">tbb::interface6::memory_pool_allocator&lt; void, P &gt;</a>)</td><td class="entry"><a class="el" href="a00078.html">tbb::interface6::memory_pool_allocator&lt; void, P &gt;</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&lt; void, P &gt;</a>)</td><td class="entry"><a class="el" href="a00078.html">tbb::interface6::memory_pool_allocator&lt; void, P &gt;</a></td><td class="entry"><span class="mlabel">protected</span></td></tr>
+1 -1
View File
@@ -44,7 +44,7 @@
<p>This is the complete list of members for <a class="el" href="a00076.html">tbb::interface6::memory_pool&lt; Alloc &gt;</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 &amp;src=Alloc())</td><td class="entry"><a class="el" href="a00076.html">tbb::interface6::memory_pool&lt; Alloc &gt;</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 &amp;src=Alloc())</td><td class="entry"><a class="el" href="a00076.html">tbb::interface6::memory_pool&lt; Alloc &gt;</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&lt; Alloc &gt;</a></td><td class="entry"><span class="mlabel">inline</span></td></tr>
</table></div><!-- contents -->
<hr>
+2 -2
View File
@@ -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 &amp;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 &amp;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>
+1 -1
View File
@@ -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 &amp;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>
+1 -1
View File
@@ -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() { }
+1 -1
View File
@@ -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)
{}
+2 -2
View File
@@ -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>
+2 -2
View File
@@ -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>
+4 -4
View File
@@ -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
View File
@@ -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))
{
}
+4 -4
View File
@@ -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");
+3 -3
View File
@@ -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
+3 -3
View File
@@ -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");
+1 -1
View File
@@ -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)
{
+2 -2
View File
@@ -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 */
+1 -1
View File
@@ -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(); }
+1 -1
View File
@@ -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
View File
@@ -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
+24
View File
@@ -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
View File
@@ -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&reg; Math Kernel Library or/and Intel&reg; TBB.
<p></p>
The module implements Pool class with the standard interface using Intel&reg; 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&reg; 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&reg; 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&reg; 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&reg; TBB enabled in both multi-threading and multi-processing modes.</DD>
</DL>
<H2>System Requirements</H2>
+151
View File
@@ -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
+144
View File
@@ -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
+34
View File
@@ -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
View File
@@ -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}
)
+264
View File
@@ -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__')
+19
View File
@@ -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())
+20 -37
View File
@@ -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
%}
+5 -211
View File
@@ -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())
+198
View File
@@ -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
View File
@@ -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();
}
+7
View File
@@ -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
View File
@@ -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;
}
}
+1 -1
View File
@@ -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
View File
@@ -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 ) {}
}
+1 -1
View File
@@ -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)
+49 -36
View File
@@ -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]);
}
+3
View File
@@ -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 );
}
+1 -1
View File
@@ -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));