From: Helge Norberg Date: Thu, 17 Sep 2015 12:42:09 +0000 (+0200) Subject: * Recompiled some libraries in Windows to support Visual Studio 2015. X-Git-Tag: 2.1.0_Beta1~279 X-Git-Url: https://git.sesse.net/?a=commitdiff_plain;h=156ace7db1f45b12f86a7d9d3f9a623dbdfbbcc5;p=casparcg * Recompiled some libraries in Windows to support Visual Studio 2015. * Code changes in separate commit. --- diff --git a/dependencies64/cef/lib/win32/debug/libcef_dll_wrapper.lib b/dependencies64/cef/lib/win32/debug/libcef_dll_wrapper.lib index e0881aa78..368a24c79 100644 Binary files a/dependencies64/cef/lib/win32/debug/libcef_dll_wrapper.lib and b/dependencies64/cef/lib/win32/debug/libcef_dll_wrapper.lib differ diff --git a/dependencies64/cef/lib/win32/release/libcef_dll_wrapper.lib b/dependencies64/cef/lib/win32/release/libcef_dll_wrapper.lib index 2ec1f100a..5e2958335 100644 Binary files a/dependencies64/cef/lib/win32/release/libcef_dll_wrapper.lib and b/dependencies64/cef/lib/win32/release/libcef_dll_wrapper.lib differ diff --git a/dependencies64/large_files_win32.7z b/dependencies64/large_files_win32.7z index aec67cf1f..4a34720ba 100644 Binary files a/dependencies64/large_files_win32.7z and b/dependencies64/large_files_win32.7z differ diff --git a/dependencies64/sfml/extlibs/lib/freetype.lib b/dependencies64/sfml/extlibs/lib/freetype.lib index 34eb0fb79..6cb91d31a 100644 Binary files a/dependencies64/sfml/extlibs/lib/freetype.lib and b/dependencies64/sfml/extlibs/lib/freetype.lib differ diff --git a/dependencies64/sfml/extlibs/lib/jpeg.lib b/dependencies64/sfml/extlibs/lib/jpeg.lib index d9aa1b4aa..2f2830b69 100644 Binary files a/dependencies64/sfml/extlibs/lib/jpeg.lib and b/dependencies64/sfml/extlibs/lib/jpeg.lib differ diff --git a/dependencies64/sfml/lib/win32/sfml-audio-2.lib b/dependencies64/sfml/lib/win32/sfml-audio-2.lib index cd462bf06..4d06363d0 100644 Binary files a/dependencies64/sfml/lib/win32/sfml-audio-2.lib and b/dependencies64/sfml/lib/win32/sfml-audio-2.lib differ diff --git a/dependencies64/sfml/lib/win32/sfml-audio-d-2.lib b/dependencies64/sfml/lib/win32/sfml-audio-d-2.lib index 05661fd27..9b3a8540b 100644 Binary files a/dependencies64/sfml/lib/win32/sfml-audio-d-2.lib and b/dependencies64/sfml/lib/win32/sfml-audio-d-2.lib differ diff --git a/dependencies64/sfml/lib/win32/sfml-graphics-2.lib b/dependencies64/sfml/lib/win32/sfml-graphics-2.lib index b6f5b21a9..f313d8c71 100644 Binary files a/dependencies64/sfml/lib/win32/sfml-graphics-2.lib and b/dependencies64/sfml/lib/win32/sfml-graphics-2.lib differ diff --git a/dependencies64/sfml/lib/win32/sfml-graphics-d-2.lib b/dependencies64/sfml/lib/win32/sfml-graphics-d-2.lib index 1397e5580..9676f2fb1 100644 Binary files a/dependencies64/sfml/lib/win32/sfml-graphics-d-2.lib and b/dependencies64/sfml/lib/win32/sfml-graphics-d-2.lib differ diff --git a/dependencies64/sfml/lib/win32/sfml-system-2.lib b/dependencies64/sfml/lib/win32/sfml-system-2.lib index 3b4ca919b..672713880 100644 Binary files a/dependencies64/sfml/lib/win32/sfml-system-2.lib and b/dependencies64/sfml/lib/win32/sfml-system-2.lib differ diff --git a/dependencies64/sfml/lib/win32/sfml-system-d-2.lib b/dependencies64/sfml/lib/win32/sfml-system-d-2.lib index 1bbea29fa..eb9e4a534 100644 Binary files a/dependencies64/sfml/lib/win32/sfml-system-d-2.lib and b/dependencies64/sfml/lib/win32/sfml-system-d-2.lib differ diff --git a/dependencies64/sfml/lib/win32/sfml-window-2.lib b/dependencies64/sfml/lib/win32/sfml-window-2.lib index b75c3b8a7..c4841d1f5 100644 Binary files a/dependencies64/sfml/lib/win32/sfml-window-2.lib and b/dependencies64/sfml/lib/win32/sfml-window-2.lib differ diff --git a/dependencies64/sfml/lib/win32/sfml-window-d-2.lib b/dependencies64/sfml/lib/win32/sfml-window-d-2.lib index d9bc34bfe..874430df4 100644 Binary files a/dependencies64/sfml/lib/win32/sfml-window-d-2.lib and b/dependencies64/sfml/lib/win32/sfml-window-d-2.lib differ diff --git a/dependencies64/tbb/bin/win32/tbb.dll b/dependencies64/tbb/bin/win32/tbb.dll index a1abe1ee8..042fc9603 100644 Binary files a/dependencies64/tbb/bin/win32/tbb.dll and b/dependencies64/tbb/bin/win32/tbb.dll differ diff --git a/dependencies64/tbb/bin/win32/tbb.pdb b/dependencies64/tbb/bin/win32/tbb.pdb deleted file mode 100644 index 6446fefd9..000000000 Binary files a/dependencies64/tbb/bin/win32/tbb.pdb and /dev/null differ diff --git a/dependencies64/tbb/bin/win32/tbb_debug.dll b/dependencies64/tbb/bin/win32/tbb_debug.dll index 920e3de1e..71ba22971 100644 Binary files a/dependencies64/tbb/bin/win32/tbb_debug.dll and b/dependencies64/tbb/bin/win32/tbb_debug.dll differ diff --git a/dependencies64/tbb/bin/win32/tbb_debug.pdb b/dependencies64/tbb/bin/win32/tbb_debug.pdb deleted file mode 100644 index 9e2d8db88..000000000 Binary files a/dependencies64/tbb/bin/win32/tbb_debug.pdb and /dev/null differ diff --git a/dependencies64/tbb/bin/win32/tbb_preview.dll b/dependencies64/tbb/bin/win32/tbb_preview.dll deleted file mode 100644 index c82b3cbbb..000000000 Binary files a/dependencies64/tbb/bin/win32/tbb_preview.dll and /dev/null differ diff --git a/dependencies64/tbb/bin/win32/tbb_preview.pdb b/dependencies64/tbb/bin/win32/tbb_preview.pdb deleted file mode 100644 index 2e258a96b..000000000 Binary files a/dependencies64/tbb/bin/win32/tbb_preview.pdb and /dev/null differ diff --git a/dependencies64/tbb/bin/win32/tbb_preview_debug.dll b/dependencies64/tbb/bin/win32/tbb_preview_debug.dll deleted file mode 100644 index 77a2af7f9..000000000 Binary files a/dependencies64/tbb/bin/win32/tbb_preview_debug.dll and /dev/null differ diff --git a/dependencies64/tbb/bin/win32/tbb_preview_debug.pdb b/dependencies64/tbb/bin/win32/tbb_preview_debug.pdb deleted file mode 100644 index f2277b0d6..000000000 Binary files a/dependencies64/tbb/bin/win32/tbb_preview_debug.pdb and /dev/null differ diff --git a/dependencies64/tbb/bin/win32/tbbmalloc.dll b/dependencies64/tbb/bin/win32/tbbmalloc.dll index aa3e29156..0901272ee 100644 Binary files a/dependencies64/tbb/bin/win32/tbbmalloc.dll and b/dependencies64/tbb/bin/win32/tbbmalloc.dll differ diff --git a/dependencies64/tbb/bin/win32/tbbmalloc.pdb b/dependencies64/tbb/bin/win32/tbbmalloc.pdb deleted file mode 100644 index 8cb385c54..000000000 Binary files a/dependencies64/tbb/bin/win32/tbbmalloc.pdb and /dev/null differ diff --git a/dependencies64/tbb/bin/win32/tbbmalloc_debug.dll b/dependencies64/tbb/bin/win32/tbbmalloc_debug.dll index 0cfece1ee..69aeb0570 100644 Binary files a/dependencies64/tbb/bin/win32/tbbmalloc_debug.dll and b/dependencies64/tbb/bin/win32/tbbmalloc_debug.dll differ diff --git a/dependencies64/tbb/bin/win32/tbbmalloc_debug.pdb b/dependencies64/tbb/bin/win32/tbbmalloc_debug.pdb deleted file mode 100644 index 1cee81918..000000000 Binary files a/dependencies64/tbb/bin/win32/tbbmalloc_debug.pdb and /dev/null differ diff --git a/dependencies64/tbb/bin/win32/tbbmalloc_proxy.dll b/dependencies64/tbb/bin/win32/tbbmalloc_proxy.dll index 68842a657..b3ad02e6a 100644 Binary files a/dependencies64/tbb/bin/win32/tbbmalloc_proxy.dll and b/dependencies64/tbb/bin/win32/tbbmalloc_proxy.dll differ diff --git a/dependencies64/tbb/bin/win32/tbbmalloc_proxy.pdb b/dependencies64/tbb/bin/win32/tbbmalloc_proxy.pdb deleted file mode 100644 index e827e16d1..000000000 Binary files a/dependencies64/tbb/bin/win32/tbbmalloc_proxy.pdb and /dev/null differ diff --git a/dependencies64/tbb/bin/win32/tbbmalloc_proxy_debug.dll b/dependencies64/tbb/bin/win32/tbbmalloc_proxy_debug.dll index fe79a8283..891a2521e 100644 Binary files a/dependencies64/tbb/bin/win32/tbbmalloc_proxy_debug.dll and b/dependencies64/tbb/bin/win32/tbbmalloc_proxy_debug.dll differ diff --git a/dependencies64/tbb/bin/win32/tbbmalloc_proxy_debug.pdb b/dependencies64/tbb/bin/win32/tbbmalloc_proxy_debug.pdb deleted file mode 100644 index 987658252..000000000 Binary files a/dependencies64/tbb/bin/win32/tbbmalloc_proxy_debug.pdb and /dev/null differ diff --git a/dependencies64/tbb/include/index.html b/dependencies64/tbb/include/index.html index 0c85b47f8..1ae016782 100644 --- a/dependencies64/tbb/include/index.html +++ b/dependencies64/tbb/include/index.html @@ -13,7 +13,7 @@ Include files for Intel® Threading Building Blocks (Intel® TBB).
Up to parent directory

-Copyright © 2005-2014 Intel Corporation. All Rights Reserved. +Copyright © 2005-2015 Intel Corporation. All Rights Reserved.

Intel is a registered trademark or trademark of Intel Corporation or its subsidiaries in the United States and other countries. diff --git a/dependencies64/tbb/include/serial/tbb/parallel_for.h b/dependencies64/tbb/include/serial/tbb/parallel_for.h index e0bddb713..89e5483ba 100644 --- a/dependencies64/tbb/include/serial/tbb/parallel_for.h +++ b/dependencies64/tbb/include/serial/tbb/parallel_for.h @@ -1,5 +1,5 @@ /* - Copyright 2005-2014 Intel Corporation. All Rights Reserved. + Copyright 2005-2015 Intel Corporation. All Rights Reserved. This file is part of Threading Building Blocks. Threading Building Blocks is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License diff --git a/dependencies64/tbb/include/serial/tbb/tbb_annotate.h b/dependencies64/tbb/include/serial/tbb/tbb_annotate.h index 2024cf644..e4e321f98 100644 --- a/dependencies64/tbb/include/serial/tbb/tbb_annotate.h +++ b/dependencies64/tbb/include/serial/tbb/tbb_annotate.h @@ -1,5 +1,5 @@ /* - Copyright 2005-2014 Intel Corporation. All Rights Reserved. + Copyright 2005-2015 Intel Corporation. All Rights Reserved. This file is part of Threading Building Blocks. Threading Building Blocks is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License diff --git a/dependencies64/tbb/include/tbb/aggregator.h b/dependencies64/tbb/include/tbb/aggregator.h index 8a28ed0d7..ed908c029 100644 --- a/dependencies64/tbb/include/tbb/aggregator.h +++ b/dependencies64/tbb/include/tbb/aggregator.h @@ -1,5 +1,5 @@ /* - Copyright 2005-2014 Intel Corporation. All Rights Reserved. + Copyright 2005-2015 Intel Corporation. All Rights Reserved. This file is part of Threading Building Blocks. Threading Building Blocks is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License diff --git a/dependencies64/tbb/include/tbb/aligned_space.h b/dependencies64/tbb/include/tbb/aligned_space.h index d2015972d..8ee62a013 100644 --- a/dependencies64/tbb/include/tbb/aligned_space.h +++ b/dependencies64/tbb/include/tbb/aligned_space.h @@ -1,5 +1,5 @@ /* - Copyright 2005-2014 Intel Corporation. All Rights Reserved. + Copyright 2005-2015 Intel Corporation. All Rights Reserved. This file is part of Threading Building Blocks. Threading Building Blocks is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License diff --git a/dependencies64/tbb/include/tbb/atomic.h b/dependencies64/tbb/include/tbb/atomic.h index 45bf31740..e3ffa6ec6 100644 --- a/dependencies64/tbb/include/tbb/atomic.h +++ b/dependencies64/tbb/include/tbb/atomic.h @@ -1,5 +1,5 @@ /* - Copyright 2005-2014 Intel Corporation. All Rights Reserved. + Copyright 2005-2015 Intel Corporation. All Rights Reserved. This file is part of Threading Building Blocks. Threading Building Blocks is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License diff --git a/dependencies64/tbb/include/tbb/blocked_range.h b/dependencies64/tbb/include/tbb/blocked_range.h index 41233476e..220e6954f 100644 --- a/dependencies64/tbb/include/tbb/blocked_range.h +++ b/dependencies64/tbb/include/tbb/blocked_range.h @@ -1,5 +1,5 @@ /* - Copyright 2005-2014 Intel Corporation. All Rights Reserved. + Copyright 2005-2015 Intel Corporation. All Rights Reserved. This file is part of Threading Building Blocks. Threading Building Blocks is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License diff --git a/dependencies64/tbb/include/tbb/blocked_range2d.h b/dependencies64/tbb/include/tbb/blocked_range2d.h index 8bec6a7b8..3a2f38371 100644 --- a/dependencies64/tbb/include/tbb/blocked_range2d.h +++ b/dependencies64/tbb/include/tbb/blocked_range2d.h @@ -1,5 +1,5 @@ /* - Copyright 2005-2014 Intel Corporation. All Rights Reserved. + Copyright 2005-2015 Intel Corporation. All Rights Reserved. This file is part of Threading Building Blocks. Threading Building Blocks is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License diff --git a/dependencies64/tbb/include/tbb/blocked_range3d.h b/dependencies64/tbb/include/tbb/blocked_range3d.h index a359e241f..0e27bbadd 100644 --- a/dependencies64/tbb/include/tbb/blocked_range3d.h +++ b/dependencies64/tbb/include/tbb/blocked_range3d.h @@ -1,5 +1,5 @@ /* - Copyright 2005-2014 Intel Corporation. All Rights Reserved. + Copyright 2005-2015 Intel Corporation. All Rights Reserved. This file is part of Threading Building Blocks. Threading Building Blocks is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License diff --git a/dependencies64/tbb/include/tbb/cache_aligned_allocator.h b/dependencies64/tbb/include/tbb/cache_aligned_allocator.h index 253ef7b2e..2a58dab8a 100644 --- a/dependencies64/tbb/include/tbb/cache_aligned_allocator.h +++ b/dependencies64/tbb/include/tbb/cache_aligned_allocator.h @@ -1,5 +1,5 @@ /* - Copyright 2005-2014 Intel Corporation. All Rights Reserved. + Copyright 2005-2015 Intel Corporation. All Rights Reserved. This file is part of Threading Building Blocks. Threading Building Blocks is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License diff --git a/dependencies64/tbb/include/tbb/combinable.h b/dependencies64/tbb/include/tbb/combinable.h index 566606d6f..57fd98c91 100644 --- a/dependencies64/tbb/include/tbb/combinable.h +++ b/dependencies64/tbb/include/tbb/combinable.h @@ -1,5 +1,5 @@ /* - Copyright 2005-2014 Intel Corporation. All Rights Reserved. + Copyright 2005-2015 Intel Corporation. All Rights Reserved. This file is part of Threading Building Blocks. Threading Building Blocks is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License diff --git a/dependencies64/tbb/include/tbb/compat/condition_variable b/dependencies64/tbb/include/tbb/compat/condition_variable index 89c2ccf55..ce9c2377d 100644 --- a/dependencies64/tbb/include/tbb/compat/condition_variable +++ b/dependencies64/tbb/include/tbb/compat/condition_variable @@ -1,5 +1,5 @@ /* - Copyright 2005-2014 Intel Corporation. All Rights Reserved. + Copyright 2005-2015 Intel Corporation. All Rights Reserved. This file is part of Threading Building Blocks. Threading Building Blocks is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License @@ -140,6 +140,25 @@ public: it uses tbb::tick_count::interval_t to specify the time duration. */ unique_lock(mutex_type& m, const tick_count::interval_t &i) : pm(&m) {owns = try_lock_for( i );} +#if __TBB_CPP11_RVALUE_REF_PRESENT + //! Move constructor + /** postconditions: pm == src_p.pm and owns == src_p.owns (where src_p is the state of src just prior to this + construction), src.pm == 0 and src.owns == false. */ + unique_lock(unique_lock && src): pm(NULL), owns(false) {this->swap(src);} + + //! Move assignment + /** effects: If owns calls pm->unlock(). + Postconditions: pm == src_p.pm and owns == src_p.owns (where src_p is the state of src just prior to this + assignment), src.pm == 0 and src.owns == false. */ + unique_lock& operator=(unique_lock && src) { + if (owns) + this->unlock(); + pm = NULL; + this->swap(src); + return *this; + } +#endif // __TBB_CPP11_RVALUE_REF_PRESENT + //! Destructor ~unique_lock() { if( owns ) pm->unlock(); } diff --git a/dependencies64/tbb/include/tbb/compat/ppl.h b/dependencies64/tbb/include/tbb/compat/ppl.h index 9012e0acd..156fd392f 100644 --- a/dependencies64/tbb/include/tbb/compat/ppl.h +++ b/dependencies64/tbb/include/tbb/compat/ppl.h @@ -1,5 +1,5 @@ /* - Copyright 2005-2014 Intel Corporation. All Rights Reserved. + Copyright 2005-2015 Intel Corporation. All Rights Reserved. This file is part of Threading Building Blocks. Threading Building Blocks is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License diff --git a/dependencies64/tbb/include/tbb/compat/thread b/dependencies64/tbb/include/tbb/compat/thread index 64197bfc0..fc7c40b00 100644 --- a/dependencies64/tbb/include/tbb/compat/thread +++ b/dependencies64/tbb/include/tbb/compat/thread @@ -1,5 +1,5 @@ /* - Copyright 2005-2014 Intel Corporation. All Rights Reserved. + Copyright 2005-2015 Intel Corporation. All Rights Reserved. This file is part of Threading Building Blocks. Threading Building Blocks is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License @@ -21,10 +21,12 @@ #ifndef __TBB_thread_H #define __TBB_thread_H -#include "../tbb_thread.h" +#include "../tbb_config.h" #if TBB_IMPLEMENT_CPP0X +#include "../tbb_thread.h" + namespace std { typedef tbb::tbb_thread thread; @@ -36,11 +38,23 @@ namespace this_thread { inline void sleep_for(const tbb::tick_count::interval_t& rel_time) { tbb::internal::thread_sleep_v3( rel_time ); } - } -} +} // namespace std + +#else /* TBB_IMPLEMENT_CPP0X */ + +#define __TBB_COMPAT_THREAD_RECURSION_PROTECTOR 1 +#include +#undef __TBB_COMPAT_THREAD_RECURSION_PROTECTOR #endif /* TBB_IMPLEMENT_CPP0X */ +#else /* __TBB_thread_H */ + +#if __TBB_COMPAT_THREAD_RECURSION_PROTECTOR +#error The tbb/compat/thread header attempts to include itself. \ + Please make sure that {TBBROOT}/include/tbb/compat is NOT in include paths. +#endif + #endif /* __TBB_thread_H */ diff --git a/dependencies64/tbb/include/tbb/compat/tuple b/dependencies64/tbb/include/tbb/compat/tuple index 00b7809ca..795b2fbd6 100644 --- a/dependencies64/tbb/include/tbb/compat/tuple +++ b/dependencies64/tbb/include/tbb/compat/tuple @@ -1,5 +1,5 @@ /* - Copyright 2005-2014 Intel Corporation. All Rights Reserved. + Copyright 2005-2015 Intel Corporation. All Rights Reserved. This file is part of Threading Building Blocks. Threading Building Blocks is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License diff --git a/dependencies64/tbb/include/tbb/concurrent_hash_map.h b/dependencies64/tbb/include/tbb/concurrent_hash_map.h index a635899da..c1f69d670 100644 --- a/dependencies64/tbb/include/tbb/concurrent_hash_map.h +++ b/dependencies64/tbb/include/tbb/concurrent_hash_map.h @@ -1,5 +1,5 @@ /* - Copyright 2005-2014 Intel Corporation. All Rights Reserved. + Copyright 2005-2015 Intel Corporation. All Rights Reserved. This file is part of Threading Building Blocks. Threading Building Blocks is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License @@ -44,7 +44,7 @@ #include "atomic.h" #include "tbb_exception.h" #include "tbb_profiling.h" -#include "internal/_concurrent_unordered_impl.h" // Need tbb_hasher +#include "internal/_tbb_hash_compare_impl.h" #if __TBB_INITIALIZER_LISTS_PRESENT #include #endif @@ -57,13 +57,6 @@ namespace tbb { -//! hash_compare that is default argument for concurrent_hash_map -template -struct tbb_hash_compare { - static size_t hash( const Key& a ) { return tbb_hasher(a); } - static bool equal( const Key& a, const Key& b ) { return a == b; } -}; - namespace interface5 { template, typename A = tbb_allocator > > @@ -580,7 +573,15 @@ protected: node( const Key &key ) : item(key, T()) {} node( const Key &key, const T &t ) : item(key, t) {} #if __TBB_CPP11_RVALUE_REF_PRESENT + node( const Key &key, T &&t ) : item(key, std::move(t)) {} node( value_type&& i ) : item(std::move(i)){} +#if __TBB_CPP11_VARIADIC_TEMPLATES_PRESENT + template + node( Args&&... args ) : item(std::forward(args)...) {} +#if __TBB_COPY_FROM_NON_CONST_REF_BROKEN + node( value_type& i ) : item(const_cast(i)) {} +#endif //__TBB_COPY_FROM_NON_CONST_REF_BROKEN +#endif //__TBB_CPP11_VARIADIC_TEMPLATES_PRESENT #endif //__TBB_CPP11_RVALUE_REF_PRESENT node( const value_type& i ) : item(i) {} @@ -604,6 +605,18 @@ protected: return new( allocator ) node(key, *t); } +#if __TBB_CPP11_RVALUE_REF_PRESENT + static node* allocate_node_move_construct(node_allocator_type& allocator, const Key &key, const T * t){ + return new( allocator ) node(key, std::move(*const_cast(t))); + } +#if __TBB_CPP11_VARIADIC_TEMPLATES_PRESENT + template + static node* allocate_node_emplace_construct(node_allocator_type& allocator, Args&&... args){ + return new( allocator ) node(std::forward(args)...); + } +#endif //#if __TBB_CPP11_VARIADIC_TEMPLATES_PRESENT +#endif + static node* allocate_node_default_construct(node_allocator_type& allocator, const Key &key, const T * ){ return new( allocator ) node(key); } @@ -957,6 +970,49 @@ public: return lookup(/*insert*/true, value.first, &value.second, NULL, /*write=*/false, &allocate_node_copy_construct ); } +#if __TBB_CPP11_RVALUE_REF_PRESENT + //! Insert item by copying if there is no such key present already and acquire a read lock on the item. + /** Returns true if item is new. */ + bool insert( const_accessor &result, value_type && value ) { + return generic_move_insert(result, std::move(value)); + } + + //! Insert item by copying if there is no such key present already and acquire a write lock on the item. + /** Returns true if item is new. */ + bool insert( accessor &result, value_type && value ) { + return generic_move_insert(result, std::move(value)); + } + + //! Insert item by copying if there is no such key present already + /** Returns true if item is inserted. */ + bool insert( value_type && value ) { + return generic_move_insert(accessor_not_used(), std::move(value)); + } + +#if __TBB_CPP11_VARIADIC_TEMPLATES_PRESENT + //! Insert item by copying if there is no such key present already and acquire a read lock on the item. + /** Returns true if item is new. */ + template + bool emplace( const_accessor &result, Args&&... args ) { + return generic_emplace(result, std::forward(args)...); + } + + //! Insert item by copying if there is no such key present already and acquire a write lock on the item. + /** Returns true if item is new. */ + template + bool emplace( accessor &result, Args&&... args ) { + return generic_emplace(result, std::forward(args)...); + } + + //! Insert item by copying if there is no such key present already + /** Returns true if item is inserted. */ + template + bool emplace( Args&&... args ) { + return generic_emplace(accessor_not_used(), std::forward(args)...); + } +#endif //__TBB_CPP11_VARIADIC_TEMPLATES_PRESENT +#endif //__TBB_CPP11_RVALUE_REF_PRESENT + //! Insert range [first, last) template void insert( I first, I last ) { @@ -989,7 +1045,32 @@ public: protected: //! Insert or find item and optionally acquire a lock on the item. - bool lookup(bool op_insert, const Key &key, const T *t, const_accessor *result, bool write, node* (*allocate_node)(node_allocator_type& , const Key &, const T * ) ) ; + bool lookup(bool op_insert, const Key &key, const T *t, const_accessor *result, bool write, node* (*allocate_node)(node_allocator_type& , const Key &, const T * ), node *tmp_n = 0 ) ; + + struct accessor_not_used { void release(){}}; + friend const_accessor* accessor_location( accessor_not_used const& ){ return NULL;} + friend const_accessor* accessor_location( const_accessor & a ) { return &a;} + + friend bool is_write_access_needed( accessor const& ) { return true;} + friend bool is_write_access_needed( const_accessor const& ) { return false;} + friend bool is_write_access_needed( accessor_not_used const& ) { return false;} + +#if __TBB_CPP11_RVALUE_REF_PRESENT + template + bool generic_move_insert( Accessor && result, value_type && value ) { + result.release(); + return lookup(/*insert*/true, value.first, &value.second, accessor_location(result), is_write_access_needed(result), &allocate_node_move_construct ); + } + +#if __TBB_CPP11_VARIADIC_TEMPLATES_PRESENT + template + bool generic_emplace( Accessor && result, Args &&... args ) { + result.release(); + node * node_ptr = allocate_node_emplace_construct(my_allocator, std::forward(args)...); + return lookup(/*insert*/true, node_ptr->item.first, NULL, accessor_location(result), is_write_access_needed(result), &do_not_allocate_node, node_ptr ); + } +#endif //__TBB_CPP11_VARIADIC_TEMPLATES_PRESENT +#endif //__TBB_CPP11_RVALUE_REF_PRESENT //! delete item by accessor bool exclude( const_accessor &item_accessor ); @@ -1035,13 +1116,13 @@ protected: }; template -bool concurrent_hash_map::lookup( bool op_insert, const Key &key, const T *t, const_accessor *result, bool write, node* (*allocate_node)(node_allocator_type& , const Key&, const T*) ) { +bool concurrent_hash_map::lookup( bool op_insert, const Key &key, const T *t, const_accessor *result, bool write, node* (*allocate_node)(node_allocator_type& , const Key&, const T*), node *tmp_n ) { __TBB_ASSERT( !result || !result->my_node, NULL ); bool return_value; hashcode_t const h = my_hash_compare.hash( key ); hashcode_t m = (hashcode_t) itt_load_word_with_acquire( my_mask ); segment_index_t grow_segment = 0; - node *n, *tmp_n = 0; + node *n; restart: {//lock scope __TBB_ASSERT((m&(m+1))==0, "data structure is invalid"); diff --git a/dependencies64/tbb/include/tbb/concurrent_lru_cache.h b/dependencies64/tbb/include/tbb/concurrent_lru_cache.h index dbf0f1f82..db50e25d2 100644 --- a/dependencies64/tbb/include/tbb/concurrent_lru_cache.h +++ b/dependencies64/tbb/include/tbb/concurrent_lru_cache.h @@ -1,5 +1,5 @@ /* - Copyright 2005-2014 Intel Corporation. All Rights Reserved. + Copyright 2005-2015 Intel Corporation. All Rights Reserved. This file is part of Threading Building Blocks. Threading Building Blocks is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License diff --git a/dependencies64/tbb/include/tbb/concurrent_priority_queue.h b/dependencies64/tbb/include/tbb/concurrent_priority_queue.h index 247c91819..3a0ad6f82 100644 --- a/dependencies64/tbb/include/tbb/concurrent_priority_queue.h +++ b/dependencies64/tbb/include/tbb/concurrent_priority_queue.h @@ -1,5 +1,5 @@ /* - Copyright 2005-2014 Intel Corporation. All Rights Reserved. + Copyright 2005-2015 Intel Corporation. All Rights Reserved. This file is part of Threading Building Blocks. Threading Building Blocks is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License diff --git a/dependencies64/tbb/include/tbb/concurrent_queue.h b/dependencies64/tbb/include/tbb/concurrent_queue.h index 2cead237c..4cb05861a 100644 --- a/dependencies64/tbb/include/tbb/concurrent_queue.h +++ b/dependencies64/tbb/include/tbb/concurrent_queue.h @@ -1,5 +1,5 @@ /* - Copyright 2005-2014 Intel Corporation. All Rights Reserved. + Copyright 2005-2015 Intel Corporation. All Rights Reserved. This file is part of Threading Building Blocks. Threading Building Blocks is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License diff --git a/dependencies64/tbb/include/tbb/concurrent_unordered_map.h b/dependencies64/tbb/include/tbb/concurrent_unordered_map.h index b2f54174a..ab97b3e52 100644 --- a/dependencies64/tbb/include/tbb/concurrent_unordered_map.h +++ b/dependencies64/tbb/include/tbb/concurrent_unordered_map.h @@ -1,5 +1,5 @@ /* - Copyright 2005-2014 Intel Corporation. All Rights Reserved. + Copyright 2005-2015 Intel Corporation. All Rights Reserved. This file is part of Threading Building Blocks. Threading Building Blocks is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License diff --git a/dependencies64/tbb/include/tbb/concurrent_unordered_set.h b/dependencies64/tbb/include/tbb/concurrent_unordered_set.h index 846351869..0d0df9064 100644 --- a/dependencies64/tbb/include/tbb/concurrent_unordered_set.h +++ b/dependencies64/tbb/include/tbb/concurrent_unordered_set.h @@ -1,5 +1,5 @@ /* - Copyright 2005-2014 Intel Corporation. All Rights Reserved. + Copyright 2005-2015 Intel Corporation. All Rights Reserved. This file is part of Threading Building Blocks. Threading Building Blocks is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License diff --git a/dependencies64/tbb/include/tbb/concurrent_vector.h b/dependencies64/tbb/include/tbb/concurrent_vector.h index bdecd7ef7..484de99e7 100644 --- a/dependencies64/tbb/include/tbb/concurrent_vector.h +++ b/dependencies64/tbb/include/tbb/concurrent_vector.h @@ -1,5 +1,5 @@ /* - Copyright 2005-2014 Intel Corporation. All Rights Reserved. + Copyright 2005-2015 Intel Corporation. All Rights Reserved. This file is part of Threading Building Blocks. Threading Building Blocks is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License @@ -239,7 +239,7 @@ namespace internal { //and 2 is the minimal index for which it's true __TBB_ASSERT(element_index, "there should be no need to call " "is_first_element_in_segment for 0th element" ); - return is_power_of_two_factor( element_index, 2 ); + return is_power_of_two_at_least( element_index, 2 ); } //! An operation on an n-element array starting at begin. @@ -963,12 +963,14 @@ public: //! the first item reference front() { __TBB_ASSERT( size()>0, NULL); - return (my_segment[0].template load().template pointer())[0]; + const segment_value_t& segment_value = my_segment[0].template load(); + return (segment_value.template pointer())[0]; } //! the first item const const_reference front() const { __TBB_ASSERT( size()>0, NULL); - return static_cast(my_segment[0].array)[0]; + const segment_value_t& segment_value = my_segment[0].template load(); + return (segment_value.template pointer())[0]; } //! the last item reference back() { diff --git a/dependencies64/tbb/include/tbb/critical_section.h b/dependencies64/tbb/include/tbb/critical_section.h index b12cdcd8d..973dd4874 100644 --- a/dependencies64/tbb/include/tbb/critical_section.h +++ b/dependencies64/tbb/include/tbb/critical_section.h @@ -1,5 +1,5 @@ /* - Copyright 2005-2014 Intel Corporation. All Rights Reserved. + Copyright 2005-2015 Intel Corporation. All Rights Reserved. This file is part of Threading Building Blocks. Threading Building Blocks is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License diff --git a/dependencies64/tbb/include/tbb/enumerable_thread_specific.h b/dependencies64/tbb/include/tbb/enumerable_thread_specific.h index e121f8f4f..aee2e5342 100644 --- a/dependencies64/tbb/include/tbb/enumerable_thread_specific.h +++ b/dependencies64/tbb/include/tbb/enumerable_thread_specific.h @@ -1,5 +1,5 @@ /* - Copyright 2005-2014 Intel Corporation. All Rights Reserved. + Copyright 2005-2015 Intel Corporation. All Rights Reserved. This file is part of Threading Building Blocks. Threading Building Blocks is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License @@ -21,12 +21,15 @@ #ifndef __TBB_enumerable_thread_specific_H #define __TBB_enumerable_thread_specific_H +#include "atomic.h" #include "concurrent_vector.h" #include "tbb_thread.h" #include "tbb_allocator.h" -#include "tbb_profiling.h" #include "cache_aligned_allocator.h" #include "aligned_space.h" +#include "internal/_template_helpers.h" +#include "internal/_tbb_hash_compare_impl.h" +#include "tbb_profiling.h" #include // for memcpy #if _WIN32||_WIN64 @@ -35,6 +38,10 @@ #include #endif +#define __TBB_ETS_USE_CPP11 \ + (__TBB_CPP11_RVALUE_REF_PRESENT && __TBB_CPP11_VARIADIC_TEMPLATES_PRESENT \ + && __TBB_CPP11_DECLTYPE_PRESENT && __TBB_CPP11_LAMBDAS_PRESENT) + namespace tbb { //! enum for selecting between single key and key-per-instance versions @@ -42,6 +49,10 @@ enum ets_key_usage_type { ets_key_per_instance, ets_no_key }; namespace interface6 { + // Forward declaration to use in internal classes + template + class enumerable_thread_specific; + //! @cond namespace internal { @@ -50,11 +61,7 @@ namespace interface6 { template class ets_base: tbb::internal::no_copy { protected: -#if _WIN32||_WIN64 - typedef DWORD key_type; -#else - typedef pthread_t key_type; -#endif + typedef tbb_thread::id key_type; #if __TBB_PROTECTED_NESTED_CLASS_BROKEN public: #endif @@ -75,24 +82,17 @@ namespace interface6 { struct slot { key_type key; void* ptr; - bool empty() const {return !key;} - bool match( key_type k ) const {return key==k;} + bool empty() const {return key == key_type();} + bool match( key_type k ) const {return key == k;} bool claim( key_type k ) { - __TBB_ASSERT(sizeof(tbb::atomic)==sizeof(key_type), NULL); - return tbb::internal::punned_cast*>(&key)->compare_and_swap(k,0)==0; + // TODO: maybe claim ptr, because key_type is not guaranteed to fit into word size + return atomic_compare_and_swap(key, k, key_type()) == key_type(); } }; #if __TBB_PROTECTED_NESTED_CLASS_BROKEN protected: #endif - static key_type key_of_current_thread() { - tbb::tbb_thread::id id = tbb::this_tbb_thread::get_id(); - key_type k; - memcpy( &k, &id, sizeof(k) ); - return k; - } - //! Root of linked list of arrays of decreasing size. /** NULL if and only if my_count==0. Each array in the list is half the size of its predecessor. */ @@ -112,38 +112,45 @@ namespace interface6 { size_t n = 1<<(a->lg_size); free_array( (void *)a, size_t(sizeof(array)+n*sizeof(slot)) ); } - static size_t hash( key_type k ) { - // Multiplicative hashing. Client should use *upper* bits. - // casts required for Mac gcc4.* compiler - return uintptr_t(k)*tbb::internal::select_size_t_constant<0x9E3779B9,0x9E3779B97F4A7C15ULL>::value; - } ets_base() {my_root=NULL; my_count=0;} - virtual ~ets_base(); // g++ complains if this is not virtual... + virtual ~ets_base(); // g++ complains if this is not virtual void* table_lookup( bool& exists ); void table_clear(); - // table_find is used in copying ETS, so is not used in concurrent context. So - // we don't need itt annotations for it. - slot& table_find( key_type k ) { - size_t h = hash(k); - array* r = my_root; - size_t mask = r->mask(); - for(size_t i = r->start(h);;i=(i+1)&mask) { - slot& s = r->at(i); - if( s.empty() || s.match(k) ) - return s; - } - } - void table_reserve_for_copy( const ets_base& other ) { + // The following functions are not used in concurrent context, + // so we don't need synchronization and ITT annotations there. + void table_elementwise_copy( const ets_base& other, + void*(*add_element)(ets_base&, void*) ) { __TBB_ASSERT(!my_root,NULL); __TBB_ASSERT(!my_count,NULL); - if( other.my_root ) { - array* a = allocate(other.my_root->lg_size); - a->next = NULL; - my_root = a; - my_count = other.my_count; + if( !other.my_root ) return; + array* root = my_root = allocate(other.my_root->lg_size); + root->next = NULL; + my_count = other.my_count; + size_t mask = root->mask(); + for( array* r=other.my_root; r; r=r->next ) { + for( size_t i=0; isize(); ++i ) { + slot& s1 = r->at(i); + if( !s1.empty() ) { + for( size_t j = root->start(tbb::tbb_hash()(s1.key)); ; j=(j+1)&mask ) { + slot& s2 = root->at(j); + if( s2.empty() ) { + s2.ptr = add_element(*this, s1.ptr); + s2.key = s1.key; + break; + } + else if( s2.match(s1.key) ) + break; + } + } + } } } + void table_swap( ets_base& other ) { + __TBB_ASSERT(this!=&other, "Don't swap an instance with itself"); + tbb::internal::swap(my_root, other.my_root); + tbb::internal::swap(my_count, other.my_count); + } }; template @@ -162,11 +169,11 @@ namespace interface6 { template void* ets_base::table_lookup( bool& exists ) { - const key_type k = key_of_current_thread(); + const key_type k = tbb::this_tbb_thread::get_id(); - __TBB_ASSERT(k!=0,NULL); + __TBB_ASSERT(k != key_type(),NULL); void* found; - size_t h = hash(k); + size_t h = tbb::tbb_hash()(k); for( array* r=my_root; r; r=r->next ) { call_itt_notify(acquired,r); size_t mask=r->mask(); @@ -262,7 +269,7 @@ namespace interface6 { virtual void* create_local() = 0; virtual void* create_array(size_t _size) = 0; // _size in bytes virtual void free_array(void* ptr, size_t _size) = 0; // size in bytes - public: + protected: ets_base() {create_key();} ~ets_base() {destroy_key();} void* table_lookup( bool& exists ) { @@ -280,6 +287,12 @@ namespace interface6 { create_key(); super::table_clear(); } + void table_swap( ets_base& other ) { + using std::swap; + __TBB_ASSERT(this!=&other, "Don't swap an instance with itself"); + swap(my_key, other.my_key); + super::table_swap(other); + } }; //! Random access iterator for traversing the thread local copies. @@ -297,8 +310,8 @@ namespace interface6 { mutable Value *my_value; template - friend enumerable_thread_specific_iterator operator+( ptrdiff_t offset, - const enumerable_thread_specific_iterator& v ); + friend enumerable_thread_specific_iterator + operator+( ptrdiff_t offset, const enumerable_thread_specific_iterator& v ); template friend bool operator==( const enumerable_thread_specific_iterator& i, @@ -309,7 +322,8 @@ namespace interface6 { const enumerable_thread_specific_iterator& j ); template - friend ptrdiff_t operator-( const enumerable_thread_specific_iterator& i, const enumerable_thread_specific_iterator& j ); + friend ptrdiff_t operator-( const enumerable_thread_specific_iterator& i, + const enumerable_thread_specific_iterator& j ); template friend class enumerable_thread_specific_iterator; @@ -349,9 +363,9 @@ namespace interface6 { Value& operator*() const { Value* value = my_value; if( !value ) { - value = my_value = reinterpret_cast(&(*my_container)[my_index].value); + value = my_value = (*my_container)[my_index].value(); } - __TBB_ASSERT( value==reinterpret_cast(&(*my_container)[my_index].value), "corrupt cache" ); + __TBB_ASSERT( value==(*my_container)[my_index].value(), "corrupt cache" ); return *value; } @@ -398,8 +412,8 @@ namespace interface6 { }; template - enumerable_thread_specific_iterator operator+( ptrdiff_t offset, - const enumerable_thread_specific_iterator& v ) { + enumerable_thread_specific_iterator + operator+( ptrdiff_t offset, const enumerable_thread_specific_iterator& v ) { return enumerable_thread_specific_iterator( v.my_container, v.my_index + offset ); } @@ -585,12 +599,6 @@ namespace interface6 { return !(i==j); } - template - struct destruct_only: tbb::internal::no_copy { - tbb::aligned_space value; - ~destruct_only() {value.begin()[0].~T();} - }; - template struct construct_by_default: tbb::internal::no_assign { void construct(void*where) {new(where) T();} // C++ note: the () in T() ensure zero initialization. @@ -602,6 +610,9 @@ namespace interface6 { const T exemplar; void construct(void*where) {new(where) T(exemplar);} construct_by_exemplar( const T& t ) : exemplar(t) {} +#if __TBB_ETS_USE_CPP11 + construct_by_exemplar( T&& t ) : exemplar(std::move(t)) {} +#endif }; template @@ -609,14 +620,31 @@ namespace interface6 { Finit f; void construct(void* where) {new(where) T(f());} construct_by_finit( const Finit& f_ ) : f(f_) {} +#if __TBB_ETS_USE_CPP11 + construct_by_finit( Finit&& f_ ) : f(std::move(f_)) {} +#endif + }; + +#if __TBB_ETS_USE_CPP11 + template + struct construct_by_args: tbb::internal::no_assign { + internal::stored_pack pack; + void construct(void* where) { + internal::call( [where](const typename strip

::type&... args ){ + new(where) T(args...); + }, pack ); + } + construct_by_args( P&& ... args ) : pack(std::forward

(args)...) {} }; +#endif // storage for initialization function pointer + // TODO: consider removing the template parameter T here and in callback_leaf template class callback_base { public: // Clone *this - virtual callback_base* clone() = 0; + virtual callback_base* clone() const = 0; // Destruct and free *this virtual void destroy() = 0; // Need virtual destructor to satisfy GCC compiler warning @@ -627,11 +655,15 @@ namespace interface6 { template class callback_leaf: public callback_base, Constructor { +#if __TBB_ETS_USE_CPP11 + template callback_leaf( P&& ... params ) : Constructor(std::forward

(params)...) {} +#else template callback_leaf( const X& x ) : Constructor(x) {} - +#endif + // TODO: make the construction/destruction consistent (use allocator.construct/destroy) typedef typename tbb::tbb_allocator my_allocator_type; - /*override*/ callback_base* clone() { + /*override*/ callback_base* clone() const { return make(*this); } @@ -644,28 +676,68 @@ namespace interface6 { Constructor::construct(where); } public: +#if __TBB_ETS_USE_CPP11 + template + static callback_base* make( P&& ... params ) { + void* where = my_allocator_type().allocate(1); + return new(where) callback_leaf( std::forward

(params)... ); + } +#else template static callback_base* make( const X& x ) { void* where = my_allocator_type().allocate(1); return new(where) callback_leaf(x); } +#endif }; - //! Template for adding padding in order to avoid false sharing - /** ModularSize should be sizeof(U) modulo the cache line size. - All maintenance of the space will be done explicitly on push_back, + //! Template for recording construction of objects in table + /** All maintenance of the space will be done explicitly on push_back, and all thread local copies must be destroyed before the concurrent vector is deleted. + + The flag is_built is initialized to false. When the local is + successfully-constructed, set the flag to true or call value_committed(). + If the constructor throws, the flag will be false. */ - template + // TODO: make a constructor for ets_element that takes a callback_base. make is_built private + template struct ets_element { - ets_element() { /* avoid cl warning C4345 about default initialization of POD types */ } - char value[ModularSize==0 ? sizeof(U) : sizeof(U)+(tbb::internal::NFS_MaxLineSize-ModularSize)]; - void unconstruct() { - tbb::internal::punned_cast(&value)->~U(); + tbb::aligned_space my_space; + bool is_built; + ets_element() { is_built = false; } // not currently-built + U* value() { return my_space.begin(); } + U* value_committed() { is_built = true; return my_space.begin(); } + ~ets_element() { + if(is_built) { + my_space.begin()->~U(); + is_built = false; + } } }; + // A predicate that can be used for a compile-time compatibility check of ETS instances + // Ideally, it should have been declared inside the ETS class, but unfortunately + // in that case VS2013 does not enable the variadic constructor. + template struct is_compatible_ets { static const bool value = false; }; + template + struct is_compatible_ets< T, enumerable_thread_specific > { static const bool value = internal::is_same_type::value; }; + +#if __TBB_ETS_USE_CPP11 + // A predicate that checks whether, for a variable 'foo' of type T, foo() is a valid expression + template + class is_callable_no_args { + private: + typedef char yes[1]; + typedef char no [2]; + + template static yes& decide( decltype(declval()())* ); + template static no& decide(...); + public: + static const bool value = (sizeof(decide(NULL)) == sizeof(yes)); + }; +#endif + } // namespace internal //! @endcond @@ -684,7 +756,7 @@ namespace interface6 { @par combine and combine_each - Both methods are defined for enumerable_thread_specific. - - combine() requires the the type T have operator=() defined. + - combine() requires the type T have operator=() defined. - neither method modifies the contents of the object (though there is no guarantee that the applied methods do not modify the object.) - Both are evaluated in serial context (the methods are assumed to be non-benign.) @@ -696,7 +768,7 @@ namespace interface6 { template friend class enumerable_thread_specific; - typedef internal::ets_element padded_element; + typedef internal::padded< internal::ets_element > padded_element; //! A generic range, used to create range objects from the iterators template @@ -720,18 +792,30 @@ namespace interface6 { internal_collection_type my_locals; + // TODO: consider unifying the callback mechanism for all create_local* methods below + // (likely non-compatible and requires interface version increase) /*override*/ void* create_local() { - void* lref = &*my_locals.grow_by(1); - my_construct_callback->construct(lref); - return lref; + padded_element& lref = *my_locals.grow_by(1); + my_construct_callback->construct(lref.value()); + return lref.value_committed(); } - void unconstruct_locals() { - for(typename internal_collection_type::iterator cvi = my_locals.begin(); cvi != my_locals.end(); ++cvi) { - cvi->unconstruct(); - } + static void* create_local_by_copy( internal::ets_base& base, void* p ) { + enumerable_thread_specific& ets = static_cast(base); + padded_element& lref = *ets.my_locals.grow_by(1); + new(lref.value()) T(*static_cast(p)); + return lref.value_committed(); } +#if __TBB_ETS_USE_CPP11 + static void* create_local_by_move( internal::ets_base& base, void* p ) { + enumerable_thread_specific& ets = static_cast(base); + padded_element& lref = *ets.my_locals.grow_by(1); + new(lref.value()) T(std::move(*static_cast(p))); + return lref.value_committed(); + } +#endif + typedef typename Allocator::template rebind< uintptr_t >::other array_allocator_type; // _size is in bytes @@ -771,9 +855,13 @@ namespace interface6 { ){} //! Constructor with initializer functor. Each local instance of T is constructed by T(finit()). - template + template ::type>::value>::type +#endif + > enumerable_thread_specific( Finit finit ) : my_construct_callback( - internal::callback_leaf >::make( finit ) + internal::callback_leaf >::make( tbb::internal::move(finit) ) ){} //! Constructor with exemplar. Each local instance of T is copy-constructed from the exemplar. @@ -781,11 +869,27 @@ namespace interface6 { internal::callback_leaf >::make( exemplar ) ){} +#if __TBB_ETS_USE_CPP11 + enumerable_thread_specific( T&& exemplar ) : my_construct_callback( + internal::callback_leaf >::make( std::move(exemplar) ) + ){} + + //! Variadic constructor with initializer arguments. Each local instance of T is constructed by T(args...) + template ::type>::value + && !internal::is_compatible_ets::type>::value + && !internal::is_same_type::type>::value + >::type> + enumerable_thread_specific( P1&& arg1, P&& ... args ) : my_construct_callback( + internal::callback_leaf >::make( std::forward(arg1), std::forward

(args)... ) + ){} +#endif + //! Destructor ~enumerable_thread_specific() { - my_construct_callback->destroy(); - this->clear(); // deallocation before the derived class is finished destructing - // So free(array *) is still accessible + if(my_construct_callback) my_construct_callback->destroy(); + // Deallocate the hash table before overridden free_array() becomes inaccessible + this->internal::ets_base::table_clear(); } //! returns reference to local, discarding exists @@ -825,65 +929,124 @@ namespace interface6 { //! Destroys local copies void clear() { - unconstruct_locals(); my_locals.clear(); this->table_clear(); // callback is not destroyed - // exemplar is not destroyed } private: template - void internal_copy( const enumerable_thread_specific& other); + void internal_copy(const enumerable_thread_specific& other) { +#if __TBB_ETS_USE_CPP11 && TBB_USE_ASSERT + // this tests is_compatible_ets + __TBB_STATIC_ASSERT( (internal::is_compatible_ets::type>::value), "is_compatible_ets fails" ); +#endif + // Initialize my_construct_callback first, so that it is valid even if rest of this routine throws an exception. + my_construct_callback = other.my_construct_callback->clone(); + __TBB_ASSERT(my_locals.size()==0,NULL); + my_locals.reserve(other.size()); + this->table_elementwise_copy( other, create_local_by_copy ); + } + + void internal_swap(enumerable_thread_specific& other) { + using std::swap; + __TBB_ASSERT( this!=&other, NULL ); + swap(my_construct_callback, other.my_construct_callback); + // concurrent_vector::swap() preserves storage space, + // so addresses to the vector kept in ETS hash table remain valid. + swap(my_locals, other.my_locals); + this->internal::ets_base::table_swap(other); + } + +#if __TBB_ETS_USE_CPP11 + template + void internal_move(enumerable_thread_specific&& other) { +#if TBB_USE_ASSERT + // this tests is_compatible_ets + __TBB_STATIC_ASSERT( (internal::is_compatible_ets::type>::value), "is_compatible_ets fails" ); +#endif + my_construct_callback = other.my_construct_callback; + other.my_construct_callback = NULL; + __TBB_ASSERT(my_locals.size()==0,NULL); + my_locals.reserve(other.size()); + this->table_elementwise_copy( other, create_local_by_move ); + } +#endif public: - template - enumerable_thread_specific( const enumerable_thread_specific& other ) : internal::ets_base () + enumerable_thread_specific( const enumerable_thread_specific& other ) + : internal::ets_base() /* prevents GCC warnings with -Wextra */ { internal_copy(other); } - enumerable_thread_specific( const enumerable_thread_specific& other ) : internal::ets_base () + template + enumerable_thread_specific( const enumerable_thread_specific& other ) { internal_copy(other); } - private: +#if __TBB_ETS_USE_CPP11 + enumerable_thread_specific( enumerable_thread_specific&& other ) : my_construct_callback() + { + internal_swap(other); + } - template - enumerable_thread_specific & - internal_assign(const enumerable_thread_specific& other) { - if(static_cast( this ) != static_cast( &other )) { + template + enumerable_thread_specific( enumerable_thread_specific&& other ) : my_construct_callback() + { + internal_move(std::move(other)); + } +#endif + + enumerable_thread_specific& operator=( const enumerable_thread_specific& other ) + { + if( this != &other ) { this->clear(); my_construct_callback->destroy(); - my_construct_callback = 0; internal_copy( other ); } return *this; } - public: + template + enumerable_thread_specific& operator=( const enumerable_thread_specific& other ) + { + __TBB_ASSERT( static_cast(this)!=static_cast(&other), NULL ); // Objects of different types + this->clear(); + my_construct_callback->destroy(); + internal_copy(other); + return *this; + } - // assignment - enumerable_thread_specific& operator=(const enumerable_thread_specific& other) { - return internal_assign(other); +#if __TBB_ETS_USE_CPP11 + enumerable_thread_specific& operator=( enumerable_thread_specific&& other ) + { + if( this != &other ) + internal_swap(other); + return *this; } template - enumerable_thread_specific& operator=(const enumerable_thread_specific& other) + enumerable_thread_specific& operator=( enumerable_thread_specific&& other ) { - return internal_assign(other); + __TBB_ASSERT( static_cast(this)!=static_cast(&other), NULL ); // Objects of different types + this->clear(); + my_construct_callback->destroy(); + internal_move(std::move(other)); + return *this; } +#endif // combine_func_t has signature T(T,T) or T(const T&, const T&) template T combine(combine_func_t f_combine) { if(begin() == end()) { - internal::destruct_only location; - my_construct_callback->construct(location.value.begin()); - return *location.value.begin(); + internal::ets_element location; + my_construct_callback->construct(location.value()); + return *location.value_committed(); } const_iterator ci = begin(); T my_result = *ci; @@ -892,42 +1055,16 @@ namespace interface6 { return my_result; } - // combine_func_t has signature void(T) or void(const T&) + // combine_func_t takes T by value or by [const] reference, and returns nothing template void combine_each(combine_func_t f_combine) { - for(const_iterator ci = begin(); ci != end(); ++ci) { + for(iterator ci = begin(); ci != end(); ++ci) { f_combine( *ci ); } } }; // enumerable_thread_specific - template - template - void enumerable_thread_specific::internal_copy( const enumerable_thread_specific& other) { - // Initialize my_construct_callback first, so that it is valid even if rest of this routine throws an exception. - my_construct_callback = other.my_construct_callback->clone(); - - typedef internal::ets_base base; - __TBB_ASSERT(my_locals.size()==0,NULL); - this->table_reserve_for_copy( other ); - for( base::array* r=other.my_root; r; r=r->next ) { - for( size_t i=0; isize(); ++i ) { - base::slot& s1 = r->at(i); - if( !s1.empty() ) { - base::slot& s2 = this->table_find(s1.key); - if( s2.empty() ) { - void* lref = &*my_locals.grow_by(1); - s2.ptr = new(lref) T(*(T*)s1.ptr); - s2.key = s1.key; - } else { - // Skip the duplicate - } - } - } - } - } - template< typename Container > class flattened2d { diff --git a/dependencies64/tbb/include/tbb/flow_graph.h b/dependencies64/tbb/include/tbb/flow_graph.h index 68626e8a0..77f86b723 100644 --- a/dependencies64/tbb/include/tbb/flow_graph.h +++ b/dependencies64/tbb/include/tbb/flow_graph.h @@ -1,5 +1,5 @@ /* - Copyright 2005-2014 Intel Corporation. All Rights Reserved. + Copyright 2005-2015 Intel Corporation. All Rights Reserved. This file is part of Threading Building Blocks. Threading Building Blocks is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License @@ -30,6 +30,7 @@ #include "task.h" #include "cache_aligned_allocator.h" #include "tbb_exception.h" +#include "internal/_template_helpers.h" #include "internal/_aggregator_impl.h" #include "tbb_profiling.h" @@ -73,14 +74,21 @@ namespace flow { //! An enumeration the provides the two most common concurrency levels: unlimited and serial enum concurrency { unlimited = 0, serial = 1 }; -namespace interface7 { +namespace interface8 { namespace internal { template class successor_cache; template class broadcast_cache; template class round_robin_cache; + +#if TBB_PREVIEW_FLOW_GRAPH_FEATURES + template< typename C> class edge_container; +#endif } +//A generic null type +struct null_type {}; + //! An empty class used for messages that mean "I'm done" class continue_msg {}; @@ -120,33 +128,28 @@ public: #if TBB_PREVIEW_FLOW_GRAPH_FEATURES //! interface to record edges for traversal & deletion + typedef typename internal::edge_container built_successors_type; + typedef typename built_successors_type::edge_list_type successor_list_type; + virtual built_successors_type &built_successors() = 0; virtual void internal_add_built_successor( successor_type & ) = 0; virtual void internal_delete_built_successor( successor_type & ) = 0; - virtual void copy_successors( std::vector &) = 0; + virtual void copy_successors( successor_list_type &) = 0; virtual size_t successor_count() = 0; #endif -}; +}; // class sender template< typename T > class limiter_node; // needed for resetting decrementer template< typename R, typename B > class run_and_put_task; static tbb::task * const SUCCESSFULLY_ENQUEUED = (task *)-1; -#if TBB_PREVIEW_FLOW_GRAPH_FEATURES // flags to modify the behavior of the graph reset(). Can be combined. enum reset_flags { rf_reset_protocol = 0, rf_reset_bodies = 1<<0, // delete the current node body, reset to a copy of the initial node body. - rf_extract = 1<<1 // delete edges (extract() for single node, reset() for graph.) + rf_clear_edges = 1<<1 // delete edges }; -#define __TBB_PFG_RESET_ARG(exp) exp -#define __TBB_COMMA , -#else -#define __TBB_PFG_RESET_ARG(exp) /* nothing */ -#define __TBB_COMMA /* nothing */ -#endif - // enqueue left task if necessary. Returns the non-enqueued task if there is one. static inline tbb::task *combine_tasks( tbb::task * left, tbb::task * right) { // if no RHS task, don't change left. @@ -199,37 +202,41 @@ public: virtual bool remove_predecessor( predecessor_type & ) { return false; } #if TBB_PREVIEW_FLOW_GRAPH_FEATURES + typedef typename internal::edge_container built_predecessors_type; + typedef typename built_predecessors_type::edge_list_type predecessor_list_type; + virtual built_predecessors_type &built_predecessors() = 0; virtual void internal_add_built_predecessor( predecessor_type & ) = 0; virtual void internal_delete_built_predecessor( predecessor_type & ) = 0; - virtual void copy_predecessors( std::vector & ) = 0; + virtual void copy_predecessors( predecessor_list_type & ) = 0; virtual size_t predecessor_count() = 0; #endif protected: //! put receiver back in initial state template friend class limiter_node; - virtual void reset_receiver(__TBB_PFG_RESET_ARG(reset_flags f = rf_reset_protocol ) ) = 0; + virtual void reset_receiver(reset_flags f = rf_reset_protocol) = 0; template friend class internal::successor_cache; virtual bool is_continue_receiver() { return false; } -}; +}; // class receiver #if TBB_PREVIEW_FLOW_GRAPH_FEATURES //* holder of edges both for caches and for those nodes which do not have predecessor caches. // C == receiver< ... > or sender< ... >, depending. +namespace internal { template class edge_container { public: - typedef std::vector edge_vector; + typedef std::list > edge_list_type; void add_edge( C &s) { built_edges.push_back( &s ); } void delete_edge( C &s) { - for ( typename edge_vector::iterator i = built_edges.begin(); i != built_edges.end(); ++i ) { + for ( typename edge_list_type::iterator i = built_edges.begin(); i != built_edges.end(); ++i ) { if ( *i == &s ) { (void)built_edges.erase(i); return; // only remove one predecessor per request @@ -237,7 +244,7 @@ public: } } - void copy_edges( edge_vector &v) { + void copy_edges( edge_list_type &v) { v = built_edges; } @@ -249,12 +256,15 @@ public: built_edges.clear(); } + // methods remove the statement from all predecessors/successors liste in the edge + // container. template< typename S > void sender_extract( S &s ); template< typename R > void receiver_extract( R &r ); private: - edge_vector built_edges; -}; + edge_list_type built_edges; +}; // class edge_container +} // namespace internal #endif /* TBB_PREVIEW_FLOW_GRAPH_FEATURES */ //! Base class for receivers of completion messages @@ -301,7 +311,9 @@ public: } #if TBB_PREVIEW_FLOW_GRAPH_FEATURES - typedef std::vector predecessor_vector_type; + typedef internal::edge_container built_predecessors_type; + typedef built_predecessors_type::edge_list_type predecessor_list_type; + /*override*/ built_predecessors_type &built_predecessors() { return my_built_predecessors; } /*override*/ void internal_add_built_predecessor( predecessor_type &s) { spin_mutex::scoped_lock l(my_mutex); @@ -313,7 +325,7 @@ public: my_built_predecessors.delete_edge(s); } - /*override*/ void copy_predecessors( predecessor_vector_type &v) { + /*override*/ void copy_predecessors( predecessor_list_type &v) { spin_mutex::scoped_lock l(my_mutex); my_built_predecessors.copy_edges(v); } @@ -322,6 +334,7 @@ public: spin_mutex::scoped_lock l(my_mutex); return my_built_predecessors.edge_count(); } + #endif /* TBB_PREVIEW_FLOW_GRAPH_FEATURES */ protected: @@ -343,7 +356,9 @@ protected: } #if TBB_PREVIEW_FLOW_GRAPH_FEATURES - edge_container my_built_predecessors; + // continue_receiver must contain its own built_predecessors because it does + // not have a node_cache. + built_predecessors_type my_built_predecessors; #endif spin_mutex my_mutex; int my_predecessor_count; @@ -352,15 +367,15 @@ protected: // the friend declaration in the base class did not eliminate the "protected class" // error in gcc 4.1.2 template friend class limiter_node; - /*override*/void reset_receiver( __TBB_PFG_RESET_ARG(reset_flags f) ) - { + + /*override*/void reset_receiver( reset_flags f ) { my_current_count = 0; + if(f & rf_clear_edges) { #if TBB_PREVIEW_FLOW_GRAPH_FEATURES - if(f & rf_extract) { - my_built_predecessors.receiver_extract(*this); + my_built_predecessors.clear(); +#endif my_predecessor_count = my_initial_predecessor_count; } -#endif } //! Does whatever should happen when the threshold is reached @@ -370,19 +385,21 @@ protected: template friend class internal::successor_cache; /*override*/ bool is_continue_receiver() { return true; } -}; -} // interface7 + +}; // class continue_receiver +} // interface8 } // flow } // tbb #include "internal/_flow_graph_trace_impl.h" +#include "internal/_tbb_hash_compare_impl.h" namespace tbb { namespace flow { -namespace interface7 { +namespace interface8 { -#include "internal/_flow_graph_types_impl.h" #include "internal/_flow_graph_impl.h" +#include "internal/_flow_graph_types_impl.h" using namespace internal::graph_policy_namespace; class graph; @@ -453,7 +470,7 @@ private: //! Private initializing constructor for begin() and end() iterators graph_iterator(GraphContainerType *g, bool begin); void internal_forward(); -}; +}; // class graph_iterator //! The graph class /** This class serves as a handle to the graph */ @@ -485,6 +502,7 @@ class graph : tbb::internal::no_copy { Receiver &my_receiver; Body my_body; }; + typedef std::list task_list_type; public: //! Constructs a graph with isolated task_group_context @@ -497,9 +515,7 @@ public: my_root_task = ( new ( task::allocate_root(*my_context) ) empty_task ); my_root_task->set_ref_count(1); tbb::internal::fgt_graph( this ); -#if TBB_PREVIEW_FLOW_GRAPH_FEATURES my_is_active = true; -#endif } //! Constructs a graph with use_this_context as context @@ -510,9 +526,7 @@ public: my_root_task = ( new ( task::allocate_root(*my_context) ) empty_task ); my_root_task->set_ref_count(1); tbb::internal::fgt_graph( this ); -#if TBB_PREVIEW_FLOW_GRAPH_FEATURES my_is_active = true; -#endif } //! Destroys the graph. @@ -551,8 +565,10 @@ public: that need to block a wait_for_all() on the graph. For example a one-off source. */ template< typename Receiver, typename Body > void run( Receiver &r, Body body ) { - FLOW_SPAWN( (* new ( task::allocate_additional_child_of( *my_root_task ) ) + if(is_active()) { + FLOW_SPAWN( (* new ( task::allocate_additional_child_of( *root_task() ) ) run_and_put_task< Receiver, Body >( r, body )) ); + } } //! Spawns a task that runs a function object @@ -560,7 +576,9 @@ public: that need to block a wait_for_all() on the graph. For example a one-off source. */ template< typename Body > void run( Body body ) { - FLOW_SPAWN( * new ( task::allocate_additional_child_of( *my_root_task ) ) run_task< Body >( body ) ); + if(is_active()) { + FLOW_SPAWN( * new ( task::allocate_additional_child_of( *root_task() ) ) run_task< Body >( body ) ); + } } //! Wait until graph is idle and decrement_wait_count calls equals increment_wait_count calls. @@ -591,15 +609,9 @@ public: //! Returns the root task of the graph task * root_task() { -#if TBB_PREVIEW_FLOW_GRAPH_FEATURES - if (!my_is_active) - return NULL; - else -#endif - return my_root_task; + return my_root_task; } - -#if TBB_PREVIEW_FLOW_GRAPH_FEATURES + void set_active(bool a = true) { my_is_active = a; } @@ -607,7 +619,10 @@ public: bool is_active() { return my_is_active; } -#endif + + void add_task_to_reset_list(task *tp) { + my_reset_task_list.push_back(tp); + } // ITERATORS template @@ -636,7 +651,7 @@ public: bool exception_thrown() { return caught_exception; } // thread-unsafe state reset. - void reset(__TBB_PFG_RESET_ARG(reset_flags f = rf_reset_protocol)); + void reset(reset_flags f = rf_reset_protocol); private: task *my_root_task; @@ -644,9 +659,8 @@ private: bool own_context; bool cancelled; bool caught_exception; -#if TBB_PREVIEW_FLOW_GRAPH_FEATURES bool my_is_active; -#endif + task_list_type my_reset_task_list; graph_node *my_nodes, *my_nodes_last; @@ -702,17 +716,13 @@ public: #endif #if TBB_PREVIEW_FLOW_GRAPH_FEATURES - virtual void extract( reset_flags f=rf_extract ) { - bool a = my_graph.is_active(); - my_graph.set_active(false); - reset((reset_flags)(f|rf_extract)); - my_graph.set_active(a); - } + virtual void extract( ) = 0; #endif protected: - virtual void reset(__TBB_PFG_RESET_ARG(reset_flags f=rf_reset_protocol)) = 0; -}; + // performs the reset on an individual node. + virtual void reset_node(reset_flags f=rf_reset_protocol) = 0; +}; // class graph_node inline void graph::register_node(graph_node *n) { n->next = NULL; @@ -737,19 +747,23 @@ inline void graph::remove_node(graph_node *n) { n->prev = n->next = NULL; } -inline void graph::reset( __TBB_PFG_RESET_ARG( reset_flags f )) { +inline void graph::reset( reset_flags f ) { // reset context - task *saved_my_root_task = my_root_task; - my_root_task = NULL; + set_active(false); if(my_context) my_context->reset(); cancelled = false; caught_exception = false; // reset all the nodes comprising the graph for(iterator ii = begin(); ii != end(); ++ii) { graph_node *my_p = &(*ii); - my_p->reset(__TBB_PFG_RESET_ARG(f)); + my_p->reset_node(f); + } + set_active(true); + // now spawn the tasks necessary to start the graph + for(task_list_type::iterator rti = my_reset_task_list.begin(); rti != my_reset_task_list.end(); ++rti) { + FLOW_SPAWN(*(*rti)); } - my_root_task = saved_my_root_task; + my_reset_task_list.clear(); } @@ -767,8 +781,12 @@ public: //! The type of successors of this node typedef receiver< Output > successor_type; + //Source node has no input type + typedef null_type input_type; + #if TBB_PREVIEW_FLOW_GRAPH_FEATURES - typedef std::vector successor_vector_type; + typedef typename sender::built_successors_type built_successors_type; + typedef typename sender::successor_list_type successor_list_type; #endif //! Constructor for a node with a successor @@ -776,6 +794,7 @@ public: source_node( graph &g, Body body, bool is_active = true ) : graph_node(g), my_active(is_active), init_my_active(is_active), my_body( new internal::source_body_leaf< output_type, Body>(body) ), + my_init_body( new internal::source_body_leaf< output_type, Body>(body) ), my_reserved(false), my_has_cached_item(false) { my_successors.set_owner(this); @@ -787,7 +806,7 @@ public: source_node( const source_node& src ) : graph_node(src.my_graph), sender(), my_active(src.init_my_active), - init_my_active(src.init_my_active), my_body( src.my_body->clone() ), + init_my_active(src.init_my_active), my_body( src.my_init_body->clone() ), my_init_body(src.my_init_body->clone() ), my_reserved(false), my_has_cached_item(false) { my_successors.set_owner(this); @@ -796,7 +815,7 @@ public: } //! The destructor - ~source_node() { delete my_body; } + ~source_node() { delete my_body; delete my_init_body; } #if TBB_PREVIEW_FLOW_GRAPH_TRACE /* override */ void set_name( const char *name ) { @@ -821,6 +840,9 @@ public: } #if TBB_PREVIEW_FLOW_GRAPH_FEATURES + + /*override*/ built_successors_type &built_successors() { return my_successors.built_successors(); } + /*override*/void internal_add_built_successor( successor_type &r) { spin_mutex::scoped_lock lock(my_mutex); my_successors.internal_add_built_successor(r); @@ -836,7 +858,7 @@ public: return my_successors.successor_count(); } - /*override*/void copy_successors(successor_vector_type &v) { + /*override*/void copy_successors(successor_list_type &v) { spin_mutex::scoped_lock l(my_mutex); my_successors.copy_successors(v); } @@ -912,19 +934,32 @@ public: return dynamic_cast< internal::source_body_leaf & >(body_ref).get_body(); } +#if TBB_PREVIEW_FLOW_GRAPH_FEATURES + /*override*/void extract( ) { + my_successors.built_successors().sender_extract(*this); // removes "my_owner" == this from each successor + my_active = init_my_active; + my_reserved = false; + if(my_has_cached_item) my_has_cached_item = false; + } +#endif + protected: //! resets the source_node to its initial state - void reset( __TBB_PFG_RESET_ARG(reset_flags f)) { + /*override*/void reset_node( reset_flags f) { my_active = init_my_active; my_reserved =false; if(my_has_cached_item) { my_has_cached_item = false; } -#if TBB_PREVIEW_FLOW_GRAPH_FEATURES - my_successors.reset(f); - if(f & rf_reset_bodies) my_body->reset_body(); -#endif + if(f & rf_clear_edges) my_successors.clear(); + if(f & rf_reset_bodies) { + internal::source_body *tmp = my_init_body->clone(); + delete my_body; + my_body = tmp; + } + if(my_active) + this->my_graph.add_task_to_reset_list(create_put_task()); } private: @@ -932,6 +967,7 @@ private: bool my_active; bool init_my_active; internal::source_body *my_body; + internal::source_body *my_init_body; internal::broadcast_cache< output_type > my_successors; bool my_reserved; bool my_has_cached_item; @@ -960,12 +996,19 @@ private: } } + // when resetting, and if the source_node was created with my_active == true, then + // when we reset the node we must store a task to run the node, and spawn it only + // after the reset is complete and is_active() is again true. This is why we don't + // test for is_active() here. + task* create_put_task() { + return ( new ( task::allocate_additional_child_of( *(this->my_graph.root_task()) ) ) + internal:: source_task_bypass < source_node< output_type > >( *this ) ); + } + //! Spawns a task that applies the body /* override */ void spawn_put( ) { - task* tp = this->my_graph.root_task(); - if(tp) { - FLOW_SPAWN( (* new ( task::allocate_additional_child_of( *tp ) ) - internal:: source_task_bypass < source_node< output_type > >( *this ) ) ); + if(this->my_graph.is_active()) { + FLOW_SPAWN( *create_put_task()); } } @@ -983,39 +1026,54 @@ private: try_release(); return last_task; } -}; // source_node +}; // class source_node + +template +struct allocate_buffer { + static const bool value = false; +}; + +template<> +struct allocate_buffer { + static const bool value = true; +}; //! Implements a function node that supports Input -> Output -template < typename Input, typename Output = continue_msg, graph_buffer_policy = queueing, typename Allocator=cache_aligned_allocator > +template < typename Input, typename Output = continue_msg, typename Policy = queueing, typename Allocator=cache_aligned_allocator > class function_node : public graph_node, public internal::function_input, public internal::function_output { -protected: - using graph_node::my_graph; public: typedef Input input_type; typedef Output output_type; typedef sender< input_type > predecessor_type; typedef receiver< output_type > successor_type; typedef internal::function_input fInput_type; + typedef internal::function_input_queue input_queue_type; typedef internal::function_output fOutput_type; #if TBB_PREVIEW_FLOW_GRAPH_FEATURES - using typename internal::function_input::predecessor_vector_type; - using typename internal::function_output::successor_vector_type; + using typename fInput_type::predecessor_list_type; + using typename fOutput_type::successor_list_type; #endif + using fInput_type::my_predecessors; //! Constructor + // input_queue_type is allocated here, but destroyed in the function_input_base. + // TODO: pass the graph_buffer_policy to the function_input_base so it can all + // be done in one place. This would be an interface-breaking change. template< typename Body > function_node( graph &g, size_t concurrency, Body body ) : - graph_node(g), internal::function_input(g, concurrency, body) { - tbb::internal::fgt_node_with_body( tbb::internal::FLOW_FUNCTION_NODE, &this->graph_node::my_graph, static_cast *>(this), - static_cast *>(this), this->my_body ); + graph_node(g), fInput_type(g, concurrency, body, allocate_buffer::value ? + new input_queue_type( ) : NULL ) { + tbb::internal::fgt_node_with_body( tbb::internal::FLOW_FUNCTION_NODE, &this->graph_node::my_graph, + static_cast *>(this), static_cast *>(this), this->my_body ); } //! Copy constructor function_node( const function_node& src ) : - graph_node(src.my_graph), internal::function_input( src ), + graph_node(src.graph_node::my_graph), + fInput_type(src, allocate_buffer::value ? new input_queue_type : NULL), fOutput_type() { - tbb::internal::fgt_node_with_body( tbb::internal::FLOW_FUNCTION_NODE, &this->my_graph, static_cast *>(this), - static_cast *>(this), this->my_body ); + tbb::internal::fgt_node_with_body( tbb::internal::FLOW_FUNCTION_NODE, &this->graph_node::my_graph, + static_cast *>(this), static_cast *>(this), this->my_body ); } #if TBB_PREVIEW_FLOW_GRAPH_TRACE @@ -1024,61 +1082,10 @@ public: } #endif -protected: - template< typename R, typename B > friend class run_and_put_task; - template friend class internal::broadcast_cache; - template friend class internal::round_robin_cache; - using fInput_type::try_put_task; - - // override of graph_node's reset. - /*override*/void reset(__TBB_PFG_RESET_ARG(reset_flags f)) { - fInput_type::reset_function_input(__TBB_PFG_RESET_ARG(f)); #if TBB_PREVIEW_FLOW_GRAPH_FEATURES - successors().reset(f); - __TBB_ASSERT(!(f & rf_extract) || successors().empty(), "function_node successors not empty"); - __TBB_ASSERT(this->my_predecessors.empty(), "function_node predecessors not empty"); -#endif - } - - /* override */ internal::broadcast_cache &successors () { return fOutput_type::my_successors; } -}; - -//! Implements a function node that supports Input -> Output -template < typename Input, typename Output, typename Allocator > -class function_node : public graph_node, public internal::function_input, public internal::function_output { -protected: - using graph_node::my_graph; -public: - typedef Input input_type; - typedef Output output_type; - typedef sender< input_type > predecessor_type; - typedef receiver< output_type > successor_type; - typedef internal::function_input fInput_type; - typedef internal::function_input_queue queue_type; - typedef internal::function_output fOutput_type; -#if TBB_PREVIEW_FLOW_GRAPH_FEATURES - using typename internal::function_input::predecessor_vector_type; - using typename internal::function_output::successor_vector_type; -#endif - - //! Constructor - template< typename Body > - function_node( graph &g, size_t concurrency, Body body ) : - graph_node(g), fInput_type( g, concurrency, body, new queue_type() ) { - tbb::internal::fgt_node_with_body( tbb::internal::FLOW_FUNCTION_NODE, &this->graph_node::my_graph, static_cast *>(this), - static_cast *>(this), this->my_body ); - } - - //! Copy constructor - function_node( const function_node& src ) : - graph_node(src.graph_node::my_graph), fInput_type( src, new queue_type() ), fOutput_type() { - tbb::internal::fgt_node_with_body( tbb::internal::FLOW_FUNCTION_NODE, &this->graph_node::my_graph, static_cast *>(this), - static_cast *>(this), this->my_body ); - } - -#if TBB_PREVIEW_FLOW_GRAPH_TRACE - /* override */ void set_name( const char *name ) { - tbb::internal::fgt_node_desc( this, name ); + /*override*/void extract( ) { + my_predecessors.built_predecessors().receiver_extract(*this); + successors().built_successors().sender_extract(*this); } #endif @@ -1088,22 +1095,26 @@ protected: template friend class internal::round_robin_cache; using fInput_type::try_put_task; - /*override*/void reset( __TBB_PFG_RESET_ARG(reset_flags f)) { - fInput_type::reset_function_input(__TBB_PFG_RESET_ARG(f)); -#if TBB_PREVIEW_FLOW_GRAPH_FEATURES - successors().reset(f); - __TBB_ASSERT(!(f & rf_extract) || successors().empty(), "function_node successors not empty"); - __TBB_ASSERT(!(f & rf_extract) || this->my_predecessors.empty(), "function_node predecessors not empty"); -#endif + /* override */ internal::broadcast_cache &successors () { return fOutput_type::my_successors; } + // override of graph_node's reset. + /*override*/void reset_node(reset_flags f) { + fInput_type::reset_function_input(f); + // TODO: use clear() instead. + if(f & rf_clear_edges) { + successors().clear(); + my_predecessors.clear(); + } + __TBB_ASSERT(!(f & rf_clear_edges) || successors().empty(), "function_node successors not empty"); + __TBB_ASSERT(this->my_predecessors.empty(), "function_node predecessors not empty"); } - /* override */ internal::broadcast_cache &successors () { return fOutput_type::my_successors; } -}; +}; // class function_node + //! implements a function node that supports Input -> (set of outputs) // Output is a tuple of output types. -template < typename Input, typename Output, graph_buffer_policy = queueing, typename Allocator=cache_aligned_allocator > +template < typename Input, typename Output, typename Policy = queueing, typename Allocator=cache_aligned_allocator > class multifunction_node : public graph_node, public internal::multifunction_input @@ -1118,28 +1129,30 @@ class multifunction_node : > { protected: using graph_node::my_graph; -private: static const int N = tbb::flow::tuple_size::value; public: typedef Input input_type; + typedef null_type output_type; typedef typename internal::wrap_tuple_elements::type output_ports_type; + typedef internal::multifunction_input fInput_type; + typedef internal::function_input_queue input_queue_type; private: typedef typename internal::multifunction_input base_type; - typedef typename internal::function_input_queue queue_type; + using fInput_type::my_predecessors; public: template multifunction_node( graph &g, size_t concurrency, Body body ) : - graph_node(g), base_type(g,concurrency, body) { - tbb::internal::fgt_multioutput_node_with_body( tbb::internal::FLOW_MULTIFUNCTION_NODE, - &this->graph_node::my_graph, static_cast *>(this), - this->output_ports(), this->my_body ); + graph_node(g), base_type(g,concurrency, body, allocate_buffer::value ? new input_queue_type : NULL) { + tbb::internal::fgt_multioutput_node_with_body( tbb::internal::FLOW_MULTIFUNCTION_NODE, + &this->graph_node::my_graph, static_cast *>(this), + this->output_ports(), this->my_body ); } multifunction_node( const multifunction_node &other) : - graph_node(other.graph_node::my_graph), base_type(other) { - tbb::internal::fgt_multioutput_node_with_body( tbb::internal::FLOW_MULTIFUNCTION_NODE, - &this->graph_node::my_graph, static_cast *>(this), - this->output_ports(), this->my_body ); + graph_node(other.graph_node::my_graph), base_type(other, allocate_buffer::value ? new input_queue_type : NULL) { + tbb::internal::fgt_multioutput_node_with_body( tbb::internal::FLOW_MULTIFUNCTION_NODE, + &this->graph_node::my_graph, static_cast *>(this), + this->output_ports(), this->my_body ); } #if TBB_PREVIEW_FLOW_GRAPH_TRACE @@ -1148,48 +1161,15 @@ public: } #endif - // all the guts are in multifunction_input... -protected: - /*override*/void reset(__TBB_PFG_RESET_ARG(reset_flags f)) { base_type::reset(__TBB_PFG_RESET_ARG(f)); } -}; // multifunction_node - -template < typename Input, typename Output, typename Allocator > -class multifunction_node : public graph_node, public internal::multifunction_input::value, internal::multifunction_output, Output>::type, Allocator> { -protected: - using graph_node::my_graph; - static const int N = tbb::flow::tuple_size::value; -public: - typedef Input input_type; - typedef typename internal::wrap_tuple_elements::type output_ports_type; -private: - typedef typename internal::multifunction_input base_type; - typedef typename internal::function_input_queue queue_type; -public: - template - multifunction_node( graph &g, size_t concurrency, Body body) : - graph_node(g), base_type(g,concurrency, body, new queue_type()) { - tbb::internal::fgt_multioutput_node_with_body( tbb::internal::FLOW_MULTIFUNCTION_NODE, - &this->graph_node::my_graph, static_cast *>(this), - this->output_ports(), this->my_body ); - } - - multifunction_node( const multifunction_node &other) : - graph_node(other.graph_node::my_graph), base_type(other, new queue_type()) { - tbb::internal::fgt_multioutput_node_with_body( tbb::internal::FLOW_MULTIFUNCTION_NODE, - &this->graph_node::my_graph, static_cast *>(this), - this->output_ports(), this->my_body ); - } - -#if TBB_PREVIEW_FLOW_GRAPH_TRACE - /* override */ void set_name( const char *name ) { - tbb::internal::fgt_multioutput_node_desc( this, name ); +#if TBB_PREVIEW_FLOW_GRAPH_FEATURES + void extract( ) { + my_predecessors.built_predecessors().receiver_extract(*this); + base_type::extract(); } #endif - // all the guts are in multifunction_input... protected: - /*override*/void reset(__TBB_PFG_RESET_ARG(reset_flags f)) { base_type::reset(__TBB_PFG_RESET_ARG(f)); } + /*override*/void reset_node(reset_flags f) { base_type::reset(f); } }; // multifunction_node //! split_node: accepts a tuple as input, forwards each element of the tuple to its @@ -1201,6 +1181,7 @@ class split_node : public multifunction_node base_type; public: typedef typename base_type::output_ports_type output_ports_type; + typedef typename base_type::output_type output_type; private: struct splitting_body { void operator()(const TupleType& t, output_ports_type &p) { @@ -1211,12 +1192,12 @@ public: typedef TupleType input_type; typedef Allocator allocator_type; split_node(graph &g) : base_type(g, unlimited, splitting_body()) { - tbb::internal::fgt_multioutput_node( tbb::internal::FLOW_SPLIT_NODE, &this->graph_node::my_graph, + tbb::internal::fgt_multioutput_node( tbb::internal::FLOW_SPLIT_NODE, &this->graph_node::my_graph, static_cast *>(this), this->output_ports() ); } split_node( const split_node & other) : base_type(other) { - tbb::internal::fgt_multioutput_node( tbb::internal::FLOW_SPLIT_NODE, &this->graph_node::my_graph, + tbb::internal::fgt_multioutput_node( tbb::internal::FLOW_SPLIT_NODE, &this->graph_node::my_graph, static_cast *>(this), this->output_ports() ); } @@ -1275,21 +1256,26 @@ public: } #endif +#if TBB_PREVIEW_FLOW_GRAPH_FEATURES + /*override graph_node*/ void extract() { + fInput_type::my_built_predecessors.receiver_extract(*this); + successors().built_successors().sender_extract(*this); + } +#endif + protected: template< typename R, typename B > friend class run_and_put_task; template friend class internal::broadcast_cache; template friend class internal::round_robin_cache; using fInput_type::try_put_task; + /* override */ internal::broadcast_cache &successors () { return fOutput_type::my_successors; } - /*override*/void reset(__TBB_PFG_RESET_ARG(reset_flags f)) { - fInput_type::reset_receiver(__TBB_PFG_RESET_ARG(f)); -#if TBB_PREVIEW_FLOW_GRAPH_FEATURES - successors().reset(f); - __TBB_ASSERT(!(f & rf_extract) || successors().empty(), "continue_node not reset"); -#endif + /*override*/void reset_node(reset_flags f) { + fInput_type::reset_receiver(f); + if(f & rf_clear_edges)successors().clear(); + __TBB_ASSERT(!(f & rf_clear_edges) || successors().empty(), "continue_node not reset"); } - /* override */ internal::broadcast_cache &successors () { return fOutput_type::my_successors; } }; // continue_node template< typename T > @@ -1302,8 +1288,10 @@ public: typedef sender< input_type > predecessor_type; typedef receiver< output_type > successor_type; #if TBB_PREVIEW_FLOW_GRAPH_FEATURES - typedef std::vector predecessor_vector_type; - typedef std::vector successor_vector_type; + typedef typename receiver::built_predecessors_type built_predecessors_type; + typedef typename sender::built_successors_type built_successors_type; + typedef typename receiver::predecessor_list_type predecessor_list_type; + typedef typename sender::successor_list_type successor_list_type; #endif overwrite_node(graph &g) : graph_node(g), my_buffer_is_valid(false) { @@ -1331,8 +1319,7 @@ public: /* override */ bool register_successor( successor_type &s ) { spin_mutex::scoped_lock l( my_mutex ); - task* tp = this->my_graph.root_task(); // just to test if we are resetting - if (my_buffer_is_valid && tp) { + if (my_buffer_is_valid && this->my_graph.is_active()) { // We have a valid value that must be forwarded immediately. if ( s.try_put( my_buffer ) || !s.register_predecessor( *this ) ) { // We add the successor: it accepted our put or it rejected it but won't let us become a predecessor @@ -1355,6 +1342,9 @@ public: } #if TBB_PREVIEW_FLOW_GRAPH_FEATURES + /*override*/built_predecessors_type &built_predecessors() { return my_built_predecessors; } + /*override*/built_successors_type &built_successors() { return my_successors.built_successors(); } + /*override*/void internal_add_built_successor( successor_type &s) { spin_mutex::scoped_lock l( my_mutex ); my_successors.internal_add_built_successor(s); @@ -1370,7 +1360,7 @@ public: return my_successors.successor_count(); } - /*override*/ void copy_successors(successor_vector_type &v) { + /*override*/ void copy_successors(successor_list_type &v) { spin_mutex::scoped_lock l( my_mutex ); my_successors.copy_successors(v); } @@ -1390,10 +1380,17 @@ public: return my_built_predecessors.edge_count(); } - /*override*/void copy_predecessors(predecessor_vector_type &v) { + /*override*/void copy_predecessors(predecessor_list_type &v) { spin_mutex::scoped_lock l( my_mutex ); my_built_predecessors.copy_edges(v); } + + /*override*/ void extract() { + my_buffer_is_valid = false; + built_successors().sender_extract(*this); + built_predecessors().receiver_extract(*this); + } + #endif /* TBB_PREVIEW_FLOW_GRAPH_FEATURES */ /* override */ bool try_get( input_type &v ) { @@ -1428,24 +1425,21 @@ protected: return rtask; } - /*override*/void reset( __TBB_PFG_RESET_ARG(reset_flags f)) { - my_buffer_is_valid = false; -#if TBB_PREVIEW_FLOW_GRAPH_FEATURES - my_successors.reset(f); - if (f&rf_extract) { - my_built_predecessors.receiver_extract(*this); - } -#endif - } - spin_mutex my_mutex; internal::broadcast_cache< input_type, null_rw_mutex > my_successors; #if TBB_PREVIEW_FLOW_GRAPH_FEATURES - edge_container > my_built_predecessors; + internal::edge_container my_built_predecessors; #endif input_type my_buffer; bool my_buffer_is_valid; - /*override*/void reset_receiver(__TBB_PFG_RESET_ARG(reset_flags /*f*/)) {} + /*override*/void reset_receiver(reset_flags /*f*/) {} + + /*override*/void reset_node( reset_flags f) { + my_buffer_is_valid = false; + if (f&rf_clear_edges) { + my_successors.clear(); + } + } }; // overwrite_node template< typename T > @@ -1505,14 +1499,14 @@ public: typedef sender< input_type > predecessor_type; typedef receiver< output_type > successor_type; #if TBB_PREVIEW_FLOW_GRAPH_FEATURES - typedef std::vector predecessor_vector_type; - typedef std::vector successor_vector_type; + typedef typename receiver::predecessor_list_type predecessor_list_type; + typedef typename sender::successor_list_type successor_list_type; #endif private: internal::broadcast_cache my_successors; #if TBB_PREVIEW_FLOW_GRAPH_FEATURES - edge_container my_built_predecessors; - spin_mutex pred_mutex; + internal::edge_container my_built_predecessors; + spin_mutex pred_mutex; // serialize accesses on edge_container #endif public: @@ -1550,37 +1544,54 @@ public: } #if TBB_PREVIEW_FLOW_GRAPH_FEATURES - /*override*/ void internal_add_built_successor(successor_type &r) { + typedef typename sender::built_successors_type built_successors_type; + + /*override sender*/ built_successors_type &built_successors() { return my_successors.built_successors(); } + + /*override sender*/ void internal_add_built_successor(successor_type &r) { my_successors.internal_add_built_successor(r); } - /*override*/ void internal_delete_built_successor(successor_type &r) { + /*override sender*/ void internal_delete_built_successor(successor_type &r) { my_successors.internal_delete_built_successor(r); } - /*override*/ size_t successor_count() { + /*override sender*/ size_t successor_count() { return my_successors.successor_count(); } - /*override*/ void copy_successors(successor_vector_type &v) { + /*override*/ void copy_successors(successor_list_type &v) { my_successors.copy_successors(v); } + typedef typename receiver::built_predecessors_type built_predecessors_type; + + /*override receiver*/ built_predecessors_type &built_predecessors() { return my_built_predecessors; } + /*override*/ void internal_add_built_predecessor( predecessor_type &p) { + spin_mutex::scoped_lock l(pred_mutex); my_built_predecessors.add_edge(p); } /*override*/ void internal_delete_built_predecessor( predecessor_type &p) { + spin_mutex::scoped_lock l(pred_mutex); my_built_predecessors.delete_edge(p); } /*override*/ size_t predecessor_count() { + spin_mutex::scoped_lock l(pred_mutex); return my_built_predecessors.edge_count(); } - /*override*/ void copy_predecessors(predecessor_vector_type &v) { + /*override*/ void copy_predecessors(predecessor_list_type &v) { + spin_mutex::scoped_lock l(pred_mutex); my_built_predecessors.copy_edges(v); } + + /*override graph_node*/ void extract() { + my_built_predecessors.receiver_extract(*this); + my_successors.built_successors().sender_extract(*this); + } #endif /* TBB_PREVIEW_FLOW_GRAPH_FEATURES */ protected: @@ -1594,16 +1605,17 @@ protected: return new_task; } - /*override*/void reset(__TBB_PFG_RESET_ARG(reset_flags f)) { + /*override*/void reset_receiver(reset_flags /*f*/) {} + + /*override*/void reset_node(reset_flags f) { + if (f&rf_clear_edges) { + my_successors.clear(); #if TBB_PREVIEW_FLOW_GRAPH_FEATURES - my_successors.reset(f); - if (f&rf_extract) { - my_built_predecessors.receiver_extract(*this); - } - __TBB_ASSERT(!(f & rf_extract) || my_successors.empty(), "Error resetting broadcast_node"); + my_built_predecessors.clear(); #endif + } + __TBB_ASSERT(!(f & rf_clear_edges) || my_successors.empty(), "Error resetting broadcast_node"); } - /*override*/void reset_receiver(__TBB_PFG_RESET_ARG(reset_flags /*f*/)) {} }; // broadcast_node //! Forwards messages in arbitrary order @@ -1616,17 +1628,17 @@ public: typedef T output_type; typedef sender< input_type > predecessor_type; typedef receiver< output_type > successor_type; - typedef buffer_node my_class; + typedef buffer_node class_type; #if TBB_PREVIEW_FLOW_GRAPH_FEATURES - typedef std::vector predecessor_vector_type; - typedef std::vector successor_vector_type; + typedef typename receiver::predecessor_list_type predecessor_list_type; + typedef typename sender::successor_list_type successor_list_type; #endif protected: typedef size_t size_type; internal::round_robin_cache< T, null_rw_mutex > my_successors; #if TBB_PREVIEW_FLOW_GRAPH_FEATURES - edge_container my_built_predecessors; + internal::edge_container my_built_predecessors; #endif friend class internal::forward_task_bypass< buffer_node< T, A > >; @@ -1652,8 +1664,8 @@ protected: successor_type *r; predecessor_type *p; size_t cnt_val; - successor_vector_type *svec; - predecessor_vector_type *pvec; + successor_list_type *svec; + predecessor_list_type *pvec; }; #else T *elem; @@ -1672,9 +1684,9 @@ protected: }; bool forwarder_busy; - typedef internal::aggregating_functor my_handler; - friend class internal::aggregating_functor; - internal::aggregator< my_handler, buffer_operation> my_aggregator; + typedef internal::aggregating_functor handler_type; + friend class internal::aggregating_functor; + internal::aggregator< handler_type, buffer_operation> my_aggregator; virtual void handle_operations(buffer_operation *op_list) { buffer_operation *tmp = NULL; @@ -1705,10 +1717,9 @@ protected: } } if (try_forwarding && !forwarder_busy) { - task* tp = this->my_graph.root_task(); - if(tp) { + if(this->my_graph.is_active()) { forwarder_busy = true; - task *new_task = new(task::allocate_additional_child_of(*tp)) internal:: + task *new_task = new(task::allocate_additional_child_of(*(this->my_graph.root_task()))) internal:: forward_task_bypass < buffer_node >(*this); // tmp should point to the last item handled by the aggregator. This is the operation @@ -1717,7 +1728,7 @@ protected: tmp->ltask = combine_tasks(z, new_task); // in case the op generated a task } } - } + } // handle_operations inline task *grab_forwarding_task( buffer_operation &op_data) { return op_data.ltask; @@ -1759,6 +1770,10 @@ protected: } #if TBB_PREVIEW_FLOW_GRAPH_FEATURES + typedef typename sender::built_successors_type built_successors_type; + + /*override sender*/ built_successors_type &built_successors() { return my_successors.built_successors(); } + virtual void internal_add_built_succ(buffer_operation *op) { my_successors.internal_add_built_successor(*(op->r)); __TBB_store_with_release(op->status, SUCCEEDED); @@ -1769,6 +1784,10 @@ protected: __TBB_store_with_release(op->status, SUCCEEDED); } + typedef typename receiver::built_predecessors_type built_predecessors_type; + + /*override receiver*/ built_predecessors_type &built_predecessors() { return my_built_predecessors; } + virtual void internal_add_built_pred(buffer_operation *op) { my_built_predecessors.add_edge(*(op->p)); __TBB_store_with_release(op->status, SUCCEEDED); @@ -1798,6 +1817,7 @@ protected: my_built_predecessors.copy_edges(*(op->pvec)); __TBB_store_with_release(op->status, SUCCEEDED); } + #endif /* TBB_PREVIEW_FLOW_GRAPH_FEATURES */ //! Tries to forward valid items to successors @@ -1868,7 +1888,7 @@ public: buffer_node( graph &g ) : graph_node(g), internal::reservable_item_buffer(), forwarder_busy(false) { my_successors.set_owner(this); - my_aggregator.initialize_handler(my_handler(this)); + my_aggregator.initialize_handler(handler_type(this)); tbb::internal::fgt_node( tbb::internal::FLOW_BUFFER_NODE, &this->my_graph, static_cast *>(this), static_cast *>(this) ); } @@ -1878,7 +1898,7 @@ public: internal::reservable_item_buffer(), receiver(), sender() { forwarder_busy = false; my_successors.set_owner(this); - my_aggregator.initialize_handler(my_handler(this)); + my_aggregator.initialize_handler(handler_type(this)); tbb::internal::fgt_node( tbb::internal::FLOW_BUFFER_NODE, &this->my_graph, static_cast *>(this), static_cast *>(this) ); } @@ -1942,17 +1962,18 @@ public: return op_data.cnt_val; } - /*override*/ void copy_predecessors( predecessor_vector_type &v ) { + /*override*/ void copy_predecessors( predecessor_list_type &v ) { buffer_operation op_data(blt_pred_cpy); op_data.pvec = &v; my_aggregator.execute(&op_data); } - /*override*/ void copy_successors( successor_vector_type &v ) { + /*override*/ void copy_successors( successor_list_type &v ) { buffer_operation op_data(blt_succ_cpy); op_data.svec = &v; my_aggregator.execute(&op_data); } + #endif //! Removes a successor. @@ -2035,18 +2056,29 @@ protected: return ft; } - /*override*/void reset( __TBB_PFG_RESET_ARG(reset_flags f)) { + /*override*/void reset_receiver(reset_flags /*f*/) { } + +#if TBB_PREVIEW_FLOW_GRAPH_FEATURES +public: + /* override*/ void extract() { + my_built_predecessors.receiver_extract(*this); + my_successors.built_successors().sender_extract(*this); + } +#endif + +protected: + /*override*/void reset_node( reset_flags f) { internal::reservable_item_buffer::reset(); + // TODO: just clear structures + if (f&rf_clear_edges) { + my_successors.clear(); #if TBB_PREVIEW_FLOW_GRAPH_FEATURES - my_successors.reset(f); - if (f&rf_extract) { - my_built_predecessors.receiver_extract(*this); - } + my_built_predecessors.clear(); #endif + } forwarder_busy = false; } - /*override*/void reset_receiver(__TBB_PFG_RESET_ARG(reset_flags /*f*/)) { } }; // buffer_node @@ -2137,8 +2169,9 @@ public: } #endif - /*override*/void reset( __TBB_PFG_RESET_ARG(reset_flags f)) { - base_type::reset(__TBB_PFG_RESET_ARG(f)); +protected: + /*override*/void reset_node( reset_flags f) { + base_type::reset_node(f); } }; // queue_node @@ -2246,9 +2279,9 @@ public: protected: - /*override*/void reset( __TBB_PFG_RESET_ARG(reset_flags f)) { + /*override*/void reset_node( reset_flags f) { mark = 0; - base_type::reset(__TBB_PFG_RESET_ARG(f)); + base_type::reset_node(f); } typedef typename buffer_node::size_type size_type; @@ -2290,10 +2323,9 @@ protected: if (markmy_tail) heapify(); __TBB_ASSERT(mark == this->my_tail, "mark unequal after heapify"); if (try_forwarding && !this->forwarder_busy) { // could we also test for this->my_tail (queue non-empty)? - task* tp = this->my_graph.root_task(); - if(tp) { + if(this->my_graph.is_active()) { this->forwarder_busy = true; - task *new_task = new(task::allocate_additional_child_of(*tp)) internal:: + task *new_task = new(task::allocate_additional_child_of(*(this->my_graph.root_task()))) internal:: forward_task_bypass < buffer_node >(*this); // tmp should point to the last item handled by the aggregator. This is the operation @@ -2489,8 +2521,10 @@ public: typedef sender< input_type > predecessor_type; typedef receiver< output_type > successor_type; #if TBB_PREVIEW_FLOW_GRAPH_FEATURES - typedef std::vector successor_vector_type; - typedef std::vector predecessor_vector_type; + typedef typename receiver::built_predecessors_type built_predecessors_type; + typedef typename sender::built_successors_type built_successors_type; + typedef typename receiver::predecessor_list_type predecessor_list_type; + typedef typename sender::successor_list_type successor_list_type; #endif private: @@ -2536,9 +2570,8 @@ private: --my_tries; my_predecessors.try_consume(); if ( check_conditions() ) { - task* tp = this->my_graph.root_task(); - if ( tp ) { - task *rtask = new ( task::allocate_additional_child_of( *tp ) ) + if ( this->my_graph.is_active() ) { + task *rtask = new ( task::allocate_additional_child_of( *(this->my_graph.root_task()) ) ) internal::forward_task_bypass< limiter_node >( *this ); FLOW_SPAWN (*rtask); } @@ -2555,9 +2588,8 @@ private: --my_tries; if (reserved) my_predecessors.try_release(); if ( check_conditions() ) { - task* tp = this->my_graph.root_task(); - if ( tp ) { - task *rtask = new ( task::allocate_additional_child_of( *tp ) ) + if ( this->my_graph.is_active() ) { + task *rtask = new ( task::allocate_additional_child_of( *(this->my_graph.root_task()) ) ) internal::forward_task_bypass< limiter_node >( *this ); __TBB_ASSERT(!rval, "Have two tasks to handle"); return rtask; @@ -2626,9 +2658,8 @@ public: my_successors.register_successor(r); //spawn a forward task if this is the only successor if ( was_empty && !my_predecessors.empty() && my_count + my_tries < my_threshold ) { - task* tp = this->my_graph.root_task(); - if ( tp ) { - FLOW_SPAWN( (* new ( task::allocate_additional_child_of( *tp ) ) + if ( this->my_graph.is_active() ) { + FLOW_SPAWN( (* new ( task::allocate_additional_child_of( *(this->my_graph.root_task()) ) ) internal::forward_task_bypass < limiter_node >( *this ) ) ); } } @@ -2644,6 +2675,9 @@ public: } #if TBB_PREVIEW_FLOW_GRAPH_FEATURES + /*override*/ built_successors_type &built_successors() { return my_successors.built_successors(); } + /*override*/ built_predecessors_type &built_predecessors() { return my_predecessors.built_predecessors(); } + /*override*/void internal_add_built_successor(receiver &src) { my_successors.internal_add_built_successor(src); } @@ -2654,7 +2688,7 @@ public: /*override*/size_t successor_count() { return my_successors.successor_count(); } - /*override*/ void copy_successors(successor_vector_type &v) { + /*override*/ void copy_successors(successor_list_type &v) { my_successors.copy_successors(v); } @@ -2668,18 +2702,24 @@ public: /*override*/size_t predecessor_count() { return my_predecessors.predecessor_count(); } - /*override*/ void copy_predecessors(predecessor_vector_type &v) { + /*override*/ void copy_predecessors(predecessor_list_type &v) { my_predecessors.copy_predecessors(v); } + + /*override*/void extract() { + my_count = 0; + my_successors.built_successors().sender_extract(*this); + my_predecessors.built_predecessors().receiver_extract(*this); + decrement.built_predecessors().receiver_extract(decrement); + } #endif /* TBB_PREVIEW_FLOW_GRAPH_FEATURES */ //! Adds src to the list of cached predecessors. /* override */ bool register_predecessor( predecessor_type &src ) { spin_mutex::scoped_lock lock(my_mutex); my_predecessors.add( src ); - task* tp = this->my_graph.root_task(); - if ( my_count + my_tries < my_threshold && !my_successors.empty() && tp ) { - FLOW_SPAWN( (* new ( task::allocate_additional_child_of( *tp ) ) + if ( my_count + my_tries < my_threshold && !my_successors.empty() && this->my_graph.is_active() ) { + FLOW_SPAWN( (* new ( task::allocate_additional_child_of( *(this->my_graph.root_task()) ) ) internal::forward_task_bypass < limiter_node >( *this ) ) ); } return true; @@ -2711,9 +2751,8 @@ protected: if ( !rtask ) { // try_put_task failed. spin_mutex::scoped_lock lock(my_mutex); --my_tries; - task* tp = this->my_graph.root_task(); - if ( check_conditions() && tp ) { - rtask = new ( task::allocate_additional_child_of( *tp ) ) + if ( check_conditions() && this->my_graph.is_active() ) { + rtask = new ( task::allocate_additional_child_of( *(this->my_graph.root_task()) ) ) internal::forward_task_bypass< limiter_node >( *this ); } } @@ -2725,28 +2764,33 @@ protected: return rtask; } - /*override*/void reset( __TBB_PFG_RESET_ARG(reset_flags f)) { - my_count = 0; - my_predecessors.reset(__TBB_PFG_RESET_ARG(f)); - decrement.reset_receiver(__TBB_PFG_RESET_ARG(f)); -#if TBB_PREVIEW_FLOW_GRAPH_FEATURES - my_successors.reset(f); -#endif + /*override*/void reset_receiver(reset_flags /*f*/) { + __TBB_ASSERT(false,NULL); // should never be called } - /*override*/void reset_receiver(__TBB_PFG_RESET_ARG(reset_flags f)) { my_predecessors.reset(__TBB_PFG_RESET_ARG(f)); } + /*override*/void reset_node( reset_flags f) { + my_count = 0; + if(f & rf_clear_edges) { + my_predecessors.clear(); + my_successors.clear(); + } + else + { + my_predecessors.reset( ); + } + decrement.reset_receiver(f); + } }; // limiter_node #include "internal/_flow_graph_join_impl.h" using internal::reserving_port; using internal::queueing_port; -using internal::tag_matching_port; +using internal::key_matching_port; using internal::input_port; using internal::tag_value; -using internal::NO_TAG; -template class join_node; +template class join_node; template class join_node: public internal::unfolded_join_node::value, reserving_port, OutputTuple, reserving> { @@ -2757,11 +2801,11 @@ public: typedef OutputTuple output_type; typedef typename unfolded_type::input_ports_type input_ports_type; join_node(graph &g) : unfolded_type(g) { - tbb::internal::fgt_multiinput_node( tbb::internal::FLOW_JOIN_NODE_RESERVING, &this->my_graph, + tbb::internal::fgt_multiinput_node( tbb::internal::FLOW_JOIN_NODE_RESERVING, &this->my_graph, this->input_ports(), static_cast< sender< output_type > *>(this) ); } join_node(const join_node &other) : unfolded_type(other) { - tbb::internal::fgt_multiinput_node( tbb::internal::FLOW_JOIN_NODE_RESERVING, &this->my_graph, + tbb::internal::fgt_multiinput_node( tbb::internal::FLOW_JOIN_NODE_RESERVING, &this->my_graph, this->input_ports(), static_cast< sender< output_type > *>(this) ); } @@ -2782,11 +2826,11 @@ public: typedef OutputTuple output_type; typedef typename unfolded_type::input_ports_type input_ports_type; join_node(graph &g) : unfolded_type(g) { - tbb::internal::fgt_multiinput_node( tbb::internal::FLOW_JOIN_NODE_QUEUEING, &this->my_graph, + tbb::internal::fgt_multiinput_node( tbb::internal::FLOW_JOIN_NODE_QUEUEING, &this->my_graph, this->input_ports(), static_cast< sender< output_type > *>(this) ); } join_node(const join_node &other) : unfolded_type(other) { - tbb::internal::fgt_multiinput_node( tbb::internal::FLOW_JOIN_NODE_QUEUEING, &this->my_graph, + tbb::internal::fgt_multiinput_node( tbb::internal::FLOW_JOIN_NODE_QUEUEING, &this->my_graph, this->input_ports(), static_cast< sender< output_type > *>(this) ); } @@ -2798,36 +2842,37 @@ public: }; -// template for tag_matching join_node -template -class join_node : public internal::unfolded_join_node::value, - tag_matching_port, OutputTuple, tag_matching> { +// template for key_matching join_node +// tag_matching join_node is a specialization of key_matching, and is source-compatible. +template +class join_node > : public internal::unfolded_join_node::value, + key_matching_port, OutputTuple, key_matching > { private: static const int N = tbb::flow::tuple_size::value; - typedef typename internal::unfolded_join_node unfolded_type; + typedef typename internal::unfolded_join_node > unfolded_type; public: typedef OutputTuple output_type; typedef typename unfolded_type::input_ports_type input_ports_type; template join_node(graph &g, __TBB_B0 b0, __TBB_B1 b1) : unfolded_type(g, b0, b1) { - tbb::internal::fgt_multiinput_node( tbb::internal::FLOW_JOIN_NODE_TAG_MATCHING, &this->my_graph, + tbb::internal::fgt_multiinput_node( tbb::internal::FLOW_JOIN_NODE_TAG_MATCHING, &this->my_graph, this->input_ports(), static_cast< sender< output_type > *>(this) ); } template join_node(graph &g, __TBB_B0 b0, __TBB_B1 b1, __TBB_B2 b2) : unfolded_type(g, b0, b1, b2) { - tbb::internal::fgt_multiinput_node( tbb::internal::FLOW_JOIN_NODE_TAG_MATCHING, &this->my_graph, + tbb::internal::fgt_multiinput_node( tbb::internal::FLOW_JOIN_NODE_TAG_MATCHING, &this->my_graph, this->input_ports(), static_cast< sender< output_type > *>(this) ); } template join_node(graph &g, __TBB_B0 b0, __TBB_B1 b1, __TBB_B2 b2, __TBB_B3 b3) : unfolded_type(g, b0, b1, b2, b3) { - tbb::internal::fgt_multiinput_node( tbb::internal::FLOW_JOIN_NODE_TAG_MATCHING, &this->my_graph, + tbb::internal::fgt_multiinput_node( tbb::internal::FLOW_JOIN_NODE_TAG_MATCHING, &this->my_graph, this->input_ports(), static_cast< sender< output_type > *>(this) ); } template join_node(graph &g, __TBB_B0 b0, __TBB_B1 b1, __TBB_B2 b2, __TBB_B3 b3, __TBB_B4 b4) : unfolded_type(g, b0, b1, b2, b3, b4) { - tbb::internal::fgt_multiinput_node( tbb::internal::FLOW_JOIN_NODE_TAG_MATCHING, &this->my_graph, + tbb::internal::fgt_multiinput_node( tbb::internal::FLOW_JOIN_NODE_TAG_MATCHING, &this->my_graph, this->input_ports(), static_cast< sender< output_type > *>(this) ); } #if __TBB_VARIADIC_MAX >= 6 @@ -2835,7 +2880,7 @@ public: typename __TBB_B5> join_node(graph &g, __TBB_B0 b0, __TBB_B1 b1, __TBB_B2 b2, __TBB_B3 b3, __TBB_B4 b4, __TBB_B5 b5) : unfolded_type(g, b0, b1, b2, b3, b4, b5) { - tbb::internal::fgt_multiinput_node( tbb::internal::FLOW_JOIN_NODE_TAG_MATCHING, &this->my_graph, + tbb::internal::fgt_multiinput_node( tbb::internal::FLOW_JOIN_NODE_TAG_MATCHING, &this->my_graph, this->input_ports(), static_cast< sender< output_type > *>(this) ); } #endif @@ -2844,7 +2889,7 @@ public: typename __TBB_B5, typename __TBB_B6> join_node(graph &g, __TBB_B0 b0, __TBB_B1 b1, __TBB_B2 b2, __TBB_B3 b3, __TBB_B4 b4, __TBB_B5 b5, __TBB_B6 b6) : unfolded_type(g, b0, b1, b2, b3, b4, b5, b6) { - tbb::internal::fgt_multiinput_node( tbb::internal::FLOW_JOIN_NODE_TAG_MATCHING, &this->my_graph, + tbb::internal::fgt_multiinput_node( tbb::internal::FLOW_JOIN_NODE_TAG_MATCHING, &this->my_graph, this->input_ports(), static_cast< sender< output_type > *>(this) ); } #endif @@ -2853,7 +2898,7 @@ public: typename __TBB_B5, typename __TBB_B6, typename __TBB_B7> join_node(graph &g, __TBB_B0 b0, __TBB_B1 b1, __TBB_B2 b2, __TBB_B3 b3, __TBB_B4 b4, __TBB_B5 b5, __TBB_B6 b6, __TBB_B7 b7) : unfolded_type(g, b0, b1, b2, b3, b4, b5, b6, b7) { - tbb::internal::fgt_multiinput_node( tbb::internal::FLOW_JOIN_NODE_TAG_MATCHING, &this->my_graph, + tbb::internal::fgt_multiinput_node( tbb::internal::FLOW_JOIN_NODE_TAG_MATCHING, &this->my_graph, this->input_ports(), static_cast< sender< output_type > *>(this) ); } #endif @@ -2862,7 +2907,7 @@ public: typename __TBB_B5, typename __TBB_B6, typename __TBB_B7, typename __TBB_B8> join_node(graph &g, __TBB_B0 b0, __TBB_B1 b1, __TBB_B2 b2, __TBB_B3 b3, __TBB_B4 b4, __TBB_B5 b5, __TBB_B6 b6, __TBB_B7 b7, __TBB_B8 b8) : unfolded_type(g, b0, b1, b2, b3, b4, b5, b6, b7, b8) { - tbb::internal::fgt_multiinput_node( tbb::internal::FLOW_JOIN_NODE_TAG_MATCHING, &this->my_graph, + tbb::internal::fgt_multiinput_node( tbb::internal::FLOW_JOIN_NODE_TAG_MATCHING, &this->my_graph, this->input_ports(), static_cast< sender< output_type > *>(this) ); } #endif @@ -2871,12 +2916,12 @@ public: typename __TBB_B5, typename __TBB_B6, typename __TBB_B7, typename __TBB_B8, typename __TBB_B9> join_node(graph &g, __TBB_B0 b0, __TBB_B1 b1, __TBB_B2 b2, __TBB_B3 b3, __TBB_B4 b4, __TBB_B5 b5, __TBB_B6 b6, __TBB_B7 b7, __TBB_B8 b8, __TBB_B9 b9) : unfolded_type(g, b0, b1, b2, b3, b4, b5, b6, b7, b8, b9) { - tbb::internal::fgt_multiinput_node( tbb::internal::FLOW_JOIN_NODE_TAG_MATCHING, &this->my_graph, + tbb::internal::fgt_multiinput_node( tbb::internal::FLOW_JOIN_NODE_TAG_MATCHING, &this->my_graph, this->input_ports(), static_cast< sender< output_type > *>(this) ); } #endif join_node(const join_node &other) : unfolded_type(other) { - tbb::internal::fgt_multiinput_node( tbb::internal::FLOW_JOIN_NODE_TAG_MATCHING, &this->my_graph, + tbb::internal::fgt_multiinput_node( tbb::internal::FLOW_JOIN_NODE_TAG_MATCHING, &this->my_graph, this->input_ports(), static_cast< sender< output_type > *>(this) ); } @@ -2891,11 +2936,9 @@ public: // indexer node #include "internal/_flow_graph_indexer_impl.h" -struct indexer_null_type {}; - -template class indexer_node; +template class indexer_node; //indexer node specializations template @@ -2907,12 +2950,12 @@ public: typedef typename internal::tagged_msg output_type; typedef typename internal::unfolded_indexer_node unfolded_type; indexer_node(graph& g) : unfolded_type(g) { - tbb::internal::fgt_multiinput_node( tbb::internal::FLOW_INDEXER_NODE, &this->my_graph, + tbb::internal::fgt_multiinput_node( tbb::internal::FLOW_INDEXER_NODE, &this->my_graph, this->input_ports(), static_cast< sender< output_type > *>(this) ); } // Copy constructor indexer_node( const indexer_node& other ) : unfolded_type(other) { - tbb::internal::fgt_multiinput_node( tbb::internal::FLOW_INDEXER_NODE, &this->my_graph, + tbb::internal::fgt_multiinput_node( tbb::internal::FLOW_INDEXER_NODE, &this->my_graph, this->input_ports(), static_cast< sender< output_type > *>(this) ); } @@ -2932,12 +2975,12 @@ public: typedef typename internal::tagged_msg output_type; typedef typename internal::unfolded_indexer_node unfolded_type; indexer_node(graph& g) : unfolded_type(g) { - tbb::internal::fgt_multiinput_node( tbb::internal::FLOW_INDEXER_NODE, &this->my_graph, + tbb::internal::fgt_multiinput_node( tbb::internal::FLOW_INDEXER_NODE, &this->my_graph, this->input_ports(), static_cast< sender< output_type > *>(this) ); } // Copy constructor indexer_node( const indexer_node& other ) : unfolded_type(other) { - tbb::internal::fgt_multiinput_node( tbb::internal::FLOW_INDEXER_NODE, &this->my_graph, + tbb::internal::fgt_multiinput_node( tbb::internal::FLOW_INDEXER_NODE, &this->my_graph, this->input_ports(), static_cast< sender< output_type > *>(this) ); } @@ -2957,12 +3000,12 @@ public: typedef typename internal::tagged_msg output_type; typedef typename internal::unfolded_indexer_node unfolded_type; indexer_node(graph& g) : unfolded_type(g) { - tbb::internal::fgt_multiinput_node( tbb::internal::FLOW_INDEXER_NODE, &this->my_graph, + tbb::internal::fgt_multiinput_node( tbb::internal::FLOW_INDEXER_NODE, &this->my_graph, this->input_ports(), static_cast< sender< output_type > *>(this) ); } // Copy constructor indexer_node( const indexer_node& other ) : unfolded_type(other) { - tbb::internal::fgt_multiinput_node( tbb::internal::FLOW_INDEXER_NODE, &this->my_graph, + tbb::internal::fgt_multiinput_node( tbb::internal::FLOW_INDEXER_NODE, &this->my_graph, this->input_ports(), static_cast< sender< output_type > *>(this) ); } @@ -2982,12 +3025,12 @@ public: typedef typename internal::tagged_msg output_type; typedef typename internal::unfolded_indexer_node unfolded_type; indexer_node(graph& g) : unfolded_type(g) { - tbb::internal::fgt_multiinput_node( tbb::internal::FLOW_INDEXER_NODE, &this->my_graph, + tbb::internal::fgt_multiinput_node( tbb::internal::FLOW_INDEXER_NODE, &this->my_graph, this->input_ports(), static_cast< sender< output_type > *>(this) ); } // Copy constructor indexer_node( const indexer_node& other ) : unfolded_type(other) { - tbb::internal::fgt_multiinput_node( tbb::internal::FLOW_INDEXER_NODE, &this->my_graph, + tbb::internal::fgt_multiinput_node( tbb::internal::FLOW_INDEXER_NODE, &this->my_graph, this->input_ports(), static_cast< sender< output_type > *>(this) ); } @@ -3007,12 +3050,12 @@ public: typedef typename internal::tagged_msg output_type; typedef typename internal::unfolded_indexer_node unfolded_type; indexer_node(graph& g) : unfolded_type(g) { - tbb::internal::fgt_multiinput_node( tbb::internal::FLOW_INDEXER_NODE, &this->my_graph, + tbb::internal::fgt_multiinput_node( tbb::internal::FLOW_INDEXER_NODE, &this->my_graph, this->input_ports(), static_cast< sender< output_type > *>(this) ); } // Copy constructor indexer_node( const indexer_node& other ) : unfolded_type(other) { - tbb::internal::fgt_multiinput_node( tbb::internal::FLOW_INDEXER_NODE, &this->my_graph, + tbb::internal::fgt_multiinput_node( tbb::internal::FLOW_INDEXER_NODE, &this->my_graph, this->input_ports(), static_cast< sender< output_type > *>(this) ); } @@ -3033,12 +3076,12 @@ public: typedef typename internal::tagged_msg output_type; typedef typename internal::unfolded_indexer_node unfolded_type; indexer_node(graph& g) : unfolded_type(g) { - tbb::internal::fgt_multiinput_node( tbb::internal::FLOW_INDEXER_NODE, &this->my_graph, + tbb::internal::fgt_multiinput_node( tbb::internal::FLOW_INDEXER_NODE, &this->my_graph, this->input_ports(), static_cast< sender< output_type > *>(this) ); } // Copy constructor indexer_node( const indexer_node& other ) : unfolded_type(other) { - tbb::internal::fgt_multiinput_node( tbb::internal::FLOW_INDEXER_NODE, &this->my_graph, + tbb::internal::fgt_multiinput_node( tbb::internal::FLOW_INDEXER_NODE, &this->my_graph, this->input_ports(), static_cast< sender< output_type > *>(this) ); } @@ -3061,12 +3104,12 @@ public: typedef typename internal::tagged_msg output_type; typedef typename internal::unfolded_indexer_node unfolded_type; indexer_node(graph& g) : unfolded_type(g) { - tbb::internal::fgt_multiinput_node( tbb::internal::FLOW_INDEXER_NODE, &this->my_graph, + tbb::internal::fgt_multiinput_node( tbb::internal::FLOW_INDEXER_NODE, &this->my_graph, this->input_ports(), static_cast< sender< output_type > *>(this) ); } // Copy constructor indexer_node( const indexer_node& other ) : unfolded_type(other) { - tbb::internal::fgt_multiinput_node( tbb::internal::FLOW_INDEXER_NODE, &this->my_graph, + tbb::internal::fgt_multiinput_node( tbb::internal::FLOW_INDEXER_NODE, &this->my_graph, this->input_ports(), static_cast< sender< output_type > *>(this) ); } @@ -3089,12 +3132,12 @@ public: typedef typename internal::tagged_msg output_type; typedef typename internal::unfolded_indexer_node unfolded_type; indexer_node(graph& g) : unfolded_type(g) { - tbb::internal::fgt_multiinput_node( tbb::internal::FLOW_INDEXER_NODE, &this->my_graph, + tbb::internal::fgt_multiinput_node( tbb::internal::FLOW_INDEXER_NODE, &this->my_graph, this->input_ports(), static_cast< sender< output_type > *>(this) ); } // Copy constructor indexer_node( const indexer_node& other ) : unfolded_type(other) { - tbb::internal::fgt_multiinput_node( tbb::internal::FLOW_INDEXER_NODE, &this->my_graph, + tbb::internal::fgt_multiinput_node( tbb::internal::FLOW_INDEXER_NODE, &this->my_graph, this->input_ports(), static_cast< sender< output_type > *>(this) ); } @@ -3117,12 +3160,12 @@ public: typedef typename internal::tagged_msg output_type; typedef typename internal::unfolded_indexer_node unfolded_type; indexer_node(graph& g) : unfolded_type(g) { - tbb::internal::fgt_multiinput_node( tbb::internal::FLOW_INDEXER_NODE, &this->my_graph, + tbb::internal::fgt_multiinput_node( tbb::internal::FLOW_INDEXER_NODE, &this->my_graph, this->input_ports(), static_cast< sender< output_type > *>(this) ); } // Copy constructor indexer_node( const indexer_node& other ) : unfolded_type(other) { - tbb::internal::fgt_multiinput_node( tbb::internal::FLOW_INDEXER_NODE, &this->my_graph, + tbb::internal::fgt_multiinput_node( tbb::internal::FLOW_INDEXER_NODE, &this->my_graph, this->input_ports(), static_cast< sender< output_type > *>(this) ); } @@ -3145,12 +3188,12 @@ public: typedef typename internal::tagged_msg output_type; typedef typename internal::unfolded_indexer_node unfolded_type; indexer_node(graph& g) : unfolded_type(g) { - tbb::internal::fgt_multiinput_node( tbb::internal::FLOW_INDEXER_NODE, &this->my_graph, + tbb::internal::fgt_multiinput_node( tbb::internal::FLOW_INDEXER_NODE, &this->my_graph, this->input_ports(), static_cast< sender< output_type > *>(this) ); } // Copy constructor indexer_node( const indexer_node& other ) : unfolded_type(other) { - tbb::internal::fgt_multiinput_node( tbb::internal::FLOW_INDEXER_NODE, &this->my_graph, + tbb::internal::fgt_multiinput_node( tbb::internal::FLOW_INDEXER_NODE, &this->my_graph, this->input_ports(), static_cast< sender< output_type > *>(this) ); } @@ -3173,7 +3216,30 @@ inline void make_edge( sender &p, receiver &s ) { tbb::internal::fgt_make_edge( &p, &s ); } -//! Makes an edge between a single predecessor and a single successor +#if __TBB_FLOW_GRAPH_CPP11_FEATURES +//Makes an edge from port 0 of a multi-output predecessor to port 0 of a multi-input successor. +template< typename T, typename V, + typename = typename T::output_ports_type, typename = typename V::input_ports_type > +inline void make_edge( T& output, V& input) { + make_edge(get<0>(output.output_ports()), get<0>(input.input_ports())); +} + +//Makes an edge from port 0 of a multi-output predecessor to a receiver. +template< typename T, typename R, + typename = typename T::output_ports_type > +inline void make_edge( T& output, receiver& input) { + make_edge(get<0>(output.output_ports()), input); +} + +//Makes an edge from a sender to port 0 of a multi-input successor. +template< typename S, typename V, + typename = typename V::input_ports_type > +inline void make_edge( sender& output, V& input) { + make_edge(output, get<0>(input.input_ports())); +} +#endif + +//! Removes an edge between a single predecessor and a single successor template< typename T > inline void remove_edge( sender &p, receiver &s ) { p.remove_successor( s ); @@ -3185,25 +3251,47 @@ inline void remove_edge( sender &p, receiver &s ) { tbb::internal::fgt_remove_edge( &p, &s ); } +#if __TBB_FLOW_GRAPH_CPP11_FEATURES +//Removes an edge between port 0 of a multi-output predecessor and port 0 of a multi-input successor. +template< typename T, typename V, + typename = typename T::output_ports_type, typename = typename V::input_ports_type > +inline void remove_edge( T& output, V& input) { + remove_edge(get<0>(output.output_ports()), get<0>(input.input_ports())); +} + +//Removes an edge between port 0 of a multi-output predecessor and a receiver. +template< typename T, typename R, + typename = typename T::output_ports_type > +inline void remove_edge( T& output, receiver& input) { + remove_edge(get<0>(output.output_ports()), input); +} +//Removes an edge between a sender and port 0 of a multi-input successor. +template< typename S, typename V, + typename = typename V::input_ports_type > +inline void remove_edge( sender& output, V& input) { + remove_edge(output, get<0>(input.input_ports())); +} +#endif + #if TBB_PREVIEW_FLOW_GRAPH_FEATURES template template< typename S > -void edge_container::sender_extract( S &s ) { - edge_vector e = built_edges; - for ( typename edge_vector::iterator i = e.begin(); i != e.end(); ++i ) { +void internal::edge_container::sender_extract( S &s ) { + edge_list_type e = built_edges; + for ( typename edge_list_type::iterator i = e.begin(); i != e.end(); ++i ) { remove_edge(s, **i); } } template template< typename R > -void edge_container::receiver_extract( R &r ) { - edge_vector e = built_edges; - for ( typename edge_vector::iterator i = e.begin(); i != e.end(); ++i ) { +void internal::edge_container::receiver_extract( R &r ) { + edge_list_type e = built_edges; + for ( typename edge_list_type::iterator i = e.begin(); i != e.end(); ++i ) { remove_edge(**i, r); } } -#endif +#endif /* TBB_PREVIEW_FLOW_GRAPH_FEATURES */ //! Returns a copy of the body from a function or continue node template< typename Body, typename Node > @@ -3211,49 +3299,385 @@ Body copy_body( Node &n ) { return n.template copy_function_object(); } -} // interface7 +#if __TBB_FLOW_GRAPH_CPP11_FEATURES + +//composite_node +template< typename InputTuple, typename OutputTuple > class composite_node; + +template< typename... InputTypes, typename... OutputTypes> +class composite_node , tbb::flow::tuple > : public graph_node, tbb::internal::no_copy { + +public: + typedef tbb::flow::tuple< receiver&... > input_ports_type; + typedef tbb::flow::tuple< sender&... > output_ports_type; + +private: +#if TBB_PREVIEW_FLOW_GRAPH_TRACE + const char *my_type_name; +#endif + input_ports_type *my_input_ports; + output_ports_type *my_output_ports; + + static const size_t NUM_INPUTS = sizeof...(InputTypes); + static const size_t NUM_OUTPUTS = sizeof...(OutputTypes); + +protected: + /*override*/void reset_node(reset_flags) {} + +public: +#if TBB_PREVIEW_FLOW_GRAPH_TRACE + composite_node( graph &g, const char *type_name = "composite_node") : graph_node(g), my_type_name(type_name), my_input_ports(NULL), my_output_ports(NULL) { + tbb::internal::itt_make_task_group( tbb::internal::ITT_DOMAIN_FLOW, this, tbb::internal::FLOW_NODE, &g, tbb::internal::FLOW_GRAPH, tbb::internal::FLOW_COMPOSITE_NODE ); + tbb::internal::fgt_multiinput_multioutput_node_desc( this, my_type_name ); + } +#else + composite_node( graph &g) : graph_node(g), my_input_ports(NULL), my_output_ports(NULL) {} +#endif + + template + void set_external_ports(T1&& input_ports_tuple, T2&& output_ports_tuple) { + __TBB_STATIC_ASSERT(NUM_INPUTS == tbb::flow::tuple_size::value, "number of arguments does not match number of input ports"); + __TBB_STATIC_ASSERT(NUM_OUTPUTS == tbb::flow::tuple_size::value, "number of arguments does not match number of output ports"); + my_input_ports = new input_ports_type(std::forward(input_ports_tuple)); + my_output_ports = new output_ports_type(std::forward(output_ports_tuple)); + +#if TBB_PREVIEW_FLOW_GRAPH_TRACE + tbb::internal::fgt_internal_input_helper::register_port( this, input_ports_tuple); + tbb::internal::fgt_internal_output_helper::register_port( this, output_ports_tuple); +#endif + } + +#if TBB_PREVIEW_FLOW_GRAPH_TRACE + template< typename... NodeTypes > + void add_visible_nodes(const NodeTypes&... n) { internal::add_nodes_impl(this, true, n...); } + + template< typename... NodeTypes > + void add_nodes(const NodeTypes&... n) { internal::add_nodes_impl(this, false, n...); } +#else + template void add_nodes(Nodes&...) { } + template void add_visible_nodes(Nodes&...) { } +#endif + +#if TBB_PREVIEW_FLOW_GRAPH_TRACE + /* override */ void set_name( const char *name ) { + tbb::internal::fgt_multiinput_multioutput_node_desc( this, name ); + } +#endif + + input_ports_type input_ports() { + __TBB_ASSERT(my_input_ports, "input ports not set, call set_external_ports to set input ports"); + return *my_input_ports; + } + + output_ports_type output_ports() { + __TBB_ASSERT(my_output_ports, "output ports not set, call set_external_ports to set output ports"); + return *my_output_ports; + } + + virtual ~composite_node() { + if(my_input_ports) delete my_input_ports; + if(my_output_ports) delete my_output_ports; + } + +#if TBB_PREVIEW_FLOW_GRAPH_FEATURES + /*override*/void extract() { + __TBB_ASSERT(false, "Current composite_node implementation does not support extract"); + } +#endif +}; // class composite_node + +//composite_node with only input ports +template< typename... InputTypes> +class composite_node , tbb::flow::tuple<> > : public graph_node, tbb::internal::no_copy { +public: + typedef tbb::flow::tuple< receiver&... > input_ports_type; + +private: +#if TBB_PREVIEW_FLOW_GRAPH_TRACE + const char *my_type_name; +#endif + input_ports_type *my_input_ports; + static const size_t NUM_INPUTS = sizeof...(InputTypes); + +protected: + /*override*/void reset_node(reset_flags) {} + +public: +#if TBB_PREVIEW_FLOW_GRAPH_TRACE + composite_node( graph &g, const char *type_name = "composite_node") : graph_node(g), my_type_name(type_name), my_input_ports(NULL) { + tbb::internal::itt_make_task_group( tbb::internal::ITT_DOMAIN_FLOW, this, tbb::internal::FLOW_NODE, &g, tbb::internal::FLOW_GRAPH, tbb::internal::FLOW_COMPOSITE_NODE ); + tbb::internal::fgt_multiinput_multioutput_node_desc( this, my_type_name ); + } +#else + composite_node( graph &g) : graph_node(g), my_input_ports(NULL) {} +#endif + + template + void set_external_ports(T&& input_ports_tuple) { + __TBB_STATIC_ASSERT(NUM_INPUTS == tbb::flow::tuple_size::value, "number of arguments does not match number of input ports"); + + my_input_ports = new input_ports_type(std::forward(input_ports_tuple)); + +#if TBB_PREVIEW_FLOW_GRAPH_TRACE + tbb::internal::fgt_internal_input_helper::register_port( this, std::forward(input_ports_tuple)); +#endif + } + +#if TBB_PREVIEW_FLOW_GRAPH_TRACE + template< typename... NodeTypes > + void add_visible_nodes(const NodeTypes&... n) { internal::add_nodes_impl(this, true, n...); } + + template< typename... NodeTypes > + void add_nodes( const NodeTypes&... n) { internal::add_nodes_impl(this, false, n...); } +#else + template void add_nodes(Nodes&...) {} + template void add_visible_nodes(Nodes&...) {} +#endif + +#if TBB_PREVIEW_FLOW_GRAPH_TRACE + /* override */ void set_name( const char *name ) { + tbb::internal::fgt_multiinput_multioutput_node_desc( this, name ); + } +#endif + + input_ports_type input_ports() { + __TBB_ASSERT(my_input_ports, "input ports not set, call set_external_ports to set input ports"); + return *my_input_ports; + } + + virtual ~composite_node() { + if(my_input_ports) delete my_input_ports; + } + +#if TBB_PREVIEW_FLOW_GRAPH_FEATURES + /*override*/void extract() { + __TBB_ASSERT(false, "Current composite_node implementation does not support extract"); + } +#endif + +}; // class composite_node + +//composite_nodes with only output_ports +template +class composite_node , tbb::flow::tuple > : public graph_node, tbb::internal::no_copy { +public: + typedef tbb::flow::tuple< sender&... > output_ports_type; + +private: +#if TBB_PREVIEW_FLOW_GRAPH_TRACE + const char *my_type_name; +#endif + output_ports_type *my_output_ports; + static const size_t NUM_OUTPUTS = sizeof...(OutputTypes); + +protected: + /*override*/void reset_node(reset_flags) {} + +public: +#if TBB_PREVIEW_FLOW_GRAPH_TRACE + composite_node( graph &g, const char *type_name = "composite_node") : graph_node(g), my_type_name(type_name), my_output_ports(NULL) { + tbb::internal::itt_make_task_group( tbb::internal::ITT_DOMAIN_FLOW, this, tbb::internal::FLOW_NODE, &g, tbb::internal::FLOW_GRAPH, tbb::internal::FLOW_COMPOSITE_NODE ); + tbb::internal::fgt_multiinput_multioutput_node_desc( this, my_type_name ); + } +#else + composite_node( graph &g) : graph_node(g), my_output_ports(NULL) {} +#endif + + template + void set_external_ports(T&& output_ports_tuple) { + __TBB_STATIC_ASSERT(NUM_OUTPUTS == tbb::flow::tuple_size::value, "number of arguments does not match number of output ports"); + + my_output_ports = new output_ports_type(std::forward(output_ports_tuple)); + +#if TBB_PREVIEW_FLOW_GRAPH_TRACE + tbb::internal::fgt_internal_output_helper::register_port( this, std::forward(output_ports_tuple)); +#endif + } + +#if TBB_PREVIEW_FLOW_GRAPH_TRACE + template + void add_visible_nodes(const NodeTypes&... n) { internal::add_nodes_impl(this, true, n...); } + + template + void add_nodes(const NodeTypes&... n) { internal::add_nodes_impl(this, false, n...); } +#else + template void add_nodes(Nodes&...) {} + template void add_visible_nodes(Nodes&...) {} +#endif + +#if TBB_PREVIEW_FLOW_GRAPH_TRACE + /* override */ void set_name( const char *name ) { + tbb::internal::fgt_multiinput_multioutput_node_desc( this, name ); + } +#endif + + output_ports_type output_ports() { + __TBB_ASSERT(my_output_ports, "output ports not set, call set_external_ports to set output ports"); + return *my_output_ports; + } + + virtual ~composite_node() { + if(my_output_ports) delete my_output_ports; + } + +#if TBB_PREVIEW_FLOW_GRAPH_FEATURES + /*override*/void extract() { + __TBB_ASSERT(false, "Current composite_node implementation does not support extract"); + } +#endif + +}; // class composite_node + +#endif // __TBB_PREVIEW_COMPOSITE_NODE + +#if __TBB_PREVIEW_ASYNC_NODE +namespace internal { +//! Pure virtual template class that defines interface for async communication +template < typename Output > +class async_gateway { +public: + typedef Output output_type; + + //! Submit signal from Async Activity to FG + virtual bool async_try_put(const output_type &i ) = 0; + + virtual void async_reserve() = 0; + + virtual void async_commit() = 0; + + virtual ~async_gateway() {} +}; +} + +//! Implements a async node +template < typename Input, typename Output, typename Allocator=cache_aligned_allocator > +class async_node : public graph_node, public internal::async_input >, public internal::function_output, public internal::async_gateway { +protected: + using graph_node::my_graph; +public: + typedef Input input_type; + typedef Output output_type; + typedef async_node< input_type, output_type, Allocator > my_class; + typedef sender< input_type > predecessor_type; + typedef receiver< output_type > successor_type; + typedef internal::async_gateway< output_type > async_gateway_type; + typedef internal::async_input async_input_type; + typedef internal::function_output async_output_type; + + //! Constructor + template< typename Body > + async_node( graph &g, Body body ) : + graph_node( g ), async_input_type( g, body ) { + tbb::internal::fgt_node_with_body( tbb::internal::FLOW_ASYNC_NODE, &this->graph_node::my_graph, + static_cast *>(this), + static_cast *>(this), this->my_body ); + } + + //! Copy constructor + async_node( const async_node& src ) : + graph_node(src.graph_node::my_graph), async_input_type( src ), async_output_type(){ + tbb::internal::fgt_node_with_body( tbb::internal::FLOW_ASYNC_NODE, &this->graph_node::my_graph, + static_cast *>(this), + static_cast *>(this), this->my_body ); + } + + /* override */ async_gateway_type& async_gateway() { + return static_cast< async_gateway_type& >(*this); + } + +#if TBB_PREVIEW_FLOW_GRAPH_TRACE + /* override */ void set_name( const char *name ) { + tbb::internal::fgt_node_desc( this, name ); + } +#endif + +protected: + template< typename R, typename B > friend class run_and_put_task; + template friend class internal::broadcast_cache; + template friend class internal::round_robin_cache; + using async_input_type::try_put_task; + + /*override*/void reset_node( reset_flags f) { + async_input_type::reset_async_input(f); + if(f & rf_clear_edges) successors().clear(); + __TBB_ASSERT(!(f & rf_clear_edges) || successors().empty(), "function_node successors not empty"); + __TBB_ASSERT(!(f & rf_clear_edges) || this->my_predecessors.empty(), "function_node predecessors not empty"); + } #if TBB_PREVIEW_FLOW_GRAPH_FEATURES - using interface7::reset_flags; - using interface7::rf_reset_protocol; - using interface7::rf_reset_bodies; - using interface7::rf_extract; -#endif - - using interface7::graph; - using interface7::graph_node; - using interface7::continue_msg; - using interface7::sender; - using interface7::receiver; - using interface7::continue_receiver; - - using interface7::source_node; - using interface7::function_node; - using interface7::multifunction_node; - using interface7::split_node; - using interface7::internal::output_port; - using interface7::indexer_node; - using interface7::internal::tagged_msg; - using interface7::internal::cast_to; - using interface7::internal::is_a; - using interface7::continue_node; - using interface7::overwrite_node; - using interface7::write_once_node; - using interface7::broadcast_node; - using interface7::buffer_node; - using interface7::queue_node; - using interface7::sequencer_node; - using interface7::priority_queue_node; - using interface7::limiter_node; - using namespace interface7::internal::graph_policy_namespace; - using interface7::join_node; - using interface7::input_port; - using interface7::copy_body; - using interface7::make_edge; - using interface7::remove_edge; - using interface7::internal::NO_TAG; - using interface7::internal::tag_value; + /*override*/void extract() { + this->my_predecessors.built_predecessors().receiver_extract(*this); + successors().built_successors().sender_extract(*this); + } +#endif + internal::broadcast_cache &successors () { return async_output_type::my_successors; } + + //! Submit signal from Async Activity to FG + /*override*/ bool async_try_put(const output_type &i ) { + // TODO: enqueue a task to a FG arena + task *res = successors().try_put_task(i); + if(!res) return false; + if (res != SUCCESSFULLY_ENQUEUED) FLOW_SPAWN(*res); + return true; + } + + /*override*/ void async_reserve() { + my_graph.increment_wait_count(); + } + + /*override*/ void async_commit() { + my_graph.decrement_wait_count(); + } +}; + +#endif // __TBB_PREVIEW_ASYNC_NODE + +} // interface8 + + using interface8::reset_flags; + using interface8::rf_reset_protocol; + using interface8::rf_reset_bodies; + using interface8::rf_clear_edges; + + using interface8::graph; + using interface8::graph_node; + using interface8::continue_msg; + using interface8::sender; + using interface8::receiver; + using interface8::continue_receiver; + + using interface8::source_node; + using interface8::function_node; + using interface8::multifunction_node; + using interface8::split_node; + using interface8::internal::output_port; + using interface8::indexer_node; + using interface8::internal::tagged_msg; + using interface8::internal::cast_to; + using interface8::internal::is_a; + using interface8::continue_node; + using interface8::overwrite_node; + using interface8::write_once_node; + using interface8::broadcast_node; + using interface8::buffer_node; + using interface8::queue_node; + using interface8::sequencer_node; + using interface8::priority_queue_node; + using interface8::limiter_node; + using namespace interface8::internal::graph_policy_namespace; + using interface8::join_node; + using interface8::input_port; + using interface8::copy_body; + using interface8::make_edge; + using interface8::remove_edge; + using interface8::internal::tag_value; +#if __TBB_FLOW_GRAPH_CPP11_FEATURES + using interface8::composite_node; +#endif +#if __TBB_PREVIEW_ASYNC_NODE + using interface8::async_node; +#endif } // flow } // tbb diff --git a/dependencies64/tbb/include/tbb/global_control.h b/dependencies64/tbb/include/tbb/global_control.h new file mode 100644 index 000000000..9b773d310 --- /dev/null +++ b/dependencies64/tbb/include/tbb/global_control.h @@ -0,0 +1,87 @@ +/* + Copyright 2005-2015 Intel Corporation. All Rights Reserved. + + This file is part of Threading Building Blocks. Threading Building Blocks is free software; + you can redistribute it and/or modify it under the terms of the GNU General Public License + version 2 as published by the Free Software Foundation. Threading Building Blocks is + distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the + implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + See the GNU General Public License for more details. You should have received a copy of + the GNU General Public License along with Threading Building Blocks; if not, write to the + Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + As a special exception, you may use this file as part of a free software library without + restriction. Specifically, if other files instantiate templates or use macros or inline + functions from this file, or you compile this file and link it with other files to produce + an executable, this file does not by itself cause the resulting executable to be covered + by the GNU General Public License. This exception does not however invalidate any other + reasons why the executable file might be covered by the GNU General Public License. +*/ + +#ifndef __TBB_global_control_H +#define __TBB_global_control_H + +#if !TBB_PREVIEW_GLOBAL_CONTROL && !__TBB_BUILD +#error Set TBB_PREVIEW_GLOBAL_CONTROL before including global_control.h +#endif + +#include "tbb_stddef.h" + +namespace tbb { +namespace interface9 { + +class global_control { +public: + enum parameter { + max_allowed_parallelism, + thread_stack_size, + parameter_max // insert new parameters above this point + }; + + global_control(parameter p, size_t value) : + my_value(value), my_next(NULL), my_param(p) { + __TBB_ASSERT(my_param < parameter_max, "Invalid parameter"); +#if __TBB_WIN8UI_SUPPORT + // For Windows Store* apps it's impossible to set stack size + if (p==thread_stack_size) + return; +#elif __TBB_x86_64 && (_WIN32 || _WIN64) + if (p==thread_stack_size) + __TBB_ASSERT_RELEASE((unsigned)value == value, "Stack size is limited to unsigned int range"); +#endif + if (my_param==max_allowed_parallelism) + // TODO: support for serialization via max_allowed_parallelism==1 + __TBB_ASSERT_RELEASE(my_value>1, "Values of 1 and 0 are not supported for max_allowed_parallelism."); + internal_create(); + } + + ~global_control() { + __TBB_ASSERT(my_param < parameter_max, "Invalid parameter. Probably the object was corrupted."); +#if __TBB_WIN8UI_SUPPORT + // For Windows Store* apps it's impossible to set stack size + if (my_param==thread_stack_size) + return; +#endif + internal_destroy(); + } + + static size_t active_value(parameter p) { + __TBB_ASSERT(p < parameter_max, "Invalid parameter"); + return active_value((int)p); + } +private: + size_t my_value; + global_control *my_next; + parameter my_param; + + void __TBB_EXPORTED_METHOD internal_create(); + void __TBB_EXPORTED_METHOD internal_destroy(); + static size_t __TBB_EXPORTED_FUNC active_value(int param); +}; +} // namespace interface9 + +using interface9::global_control; + +} // tbb + +#endif // __TBB_global_control_H diff --git a/dependencies64/tbb/include/tbb/index.html b/dependencies64/tbb/include/tbb/index.html index 6ceb5da61..a403e1fa0 100644 --- a/dependencies64/tbb/include/tbb/index.html +++ b/dependencies64/tbb/include/tbb/index.html @@ -19,7 +19,7 @@ Include files for Intel® Threading Building Blocks classes and functions.


Up to parent directory

-Copyright © 2005-2014 Intel Corporation. All Rights Reserved. +Copyright © 2005-2015 Intel Corporation. All Rights Reserved.

Intel is a registered trademark or trademark of Intel Corporation or its subsidiaries in the United States and other countries. diff --git a/dependencies64/tbb/include/tbb/internal/_aggregator_impl.h b/dependencies64/tbb/include/tbb/internal/_aggregator_impl.h index 854cb4eef..6782b6ad3 100644 --- a/dependencies64/tbb/include/tbb/internal/_aggregator_impl.h +++ b/dependencies64/tbb/include/tbb/internal/_aggregator_impl.h @@ -1,5 +1,5 @@ /* - Copyright 2005-2014 Intel Corporation. All Rights Reserved. + Copyright 2005-2015 Intel Corporation. All Rights Reserved. This file is part of Threading Building Blocks. Threading Building Blocks is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License diff --git a/dependencies64/tbb/include/tbb/internal/_concurrent_queue_impl.h b/dependencies64/tbb/include/tbb/internal/_concurrent_queue_impl.h index 8d95cc69e..30b738fc3 100644 --- a/dependencies64/tbb/include/tbb/internal/_concurrent_queue_impl.h +++ b/dependencies64/tbb/include/tbb/internal/_concurrent_queue_impl.h @@ -1,5 +1,5 @@ /* - Copyright 2005-2014 Intel Corporation. All Rights Reserved. + Copyright 2005-2015 Intel Corporation. All Rights Reserved. This file is part of Threading Building Blocks. Threading Building Blocks is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License @@ -1015,11 +1015,11 @@ template class concurrent_queue_iterator: public concurrent_queue_iterator_base, public std::iterator { -#if !defined(_MSC_VER) || defined(__INTEL_COMPILER) +#if !__TBB_TEMPLATE_FRIENDS_BROKEN template friend class ::tbb::concurrent_bounded_queue; #else -public: // workaround for MSVC +public: #endif //! Construct iterator pointing to head of queue. diff --git a/dependencies64/tbb/include/tbb/internal/_concurrent_unordered_impl.h b/dependencies64/tbb/include/tbb/internal/_concurrent_unordered_impl.h index 103654276..dffe4fcde 100644 --- a/dependencies64/tbb/include/tbb/internal/_concurrent_unordered_impl.h +++ b/dependencies64/tbb/include/tbb/internal/_concurrent_unordered_impl.h @@ -1,5 +1,5 @@ /* - Copyright 2005-2014 Intel Corporation. All Rights Reserved. + Copyright 2005-2015 Intel Corporation. All Rights Reserved. This file is part of Threading Building Blocks. Threading Building Blocks is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License @@ -54,6 +54,8 @@ #include #endif +#include "_tbb_hash_compare_impl.h" + namespace tbb { namespace interface5 { //! @cond INTERNAL @@ -258,12 +260,21 @@ public: sokey_t my_order_key; // Order key for this element }; + // Allocate a new node with the given order key; used to allocate dummy nodes + nodeptr_t create_node(sokey_t order_key) { + nodeptr_t pnode = my_node_allocator.allocate(1); + pnode->init(order_key); + return (pnode); + } + // Allocate a new node with the given order key and value - nodeptr_t create_node(sokey_t order_key, const T &value) { + template + nodeptr_t create_node(sokey_t order_key, __TBB_FORWARDING_REF(Arg) t){ nodeptr_t pnode = my_node_allocator.allocate(1); + //TODO: use RAII scoped guard instead of explicit catch __TBB_TRY { - new(static_cast(&pnode->my_element)) T(value); + new(static_cast(&pnode->my_element)) T(tbb::internal::forward(t)); pnode->init(order_key); } __TBB_CATCH(...) { my_node_allocator.deallocate(pnode, 1); @@ -273,16 +284,14 @@ public: return (pnode); } -#if __TBB_CPP11_RVALUE_REF_PRESENT - //TODO: try to combine both implementations using poor man forward - //TODO: use RAII scoped guard instead of explicit catch - // Allocate a new node with the given order key and value - nodeptr_t create_node(sokey_t order_key, T &&value) { + // Allocate a new node with the given parameters for constructing value + template + nodeptr_t create_node_v( __TBB_FORWARDING_REF(Args) __TBB_PARAMETER_PACK args){ nodeptr_t pnode = my_node_allocator.allocate(1); + //TODO: use RAII scoped guard instead of explicit catch __TBB_TRY { - new(static_cast(&pnode->my_element)) T(std::move(value)); - pnode->init(order_key); + new(static_cast(&pnode->my_element)) T(__TBB_PACK_EXPANSION(tbb::internal::forward(args))); } __TBB_CATCH(...) { my_node_allocator.deallocate(pnode, 1); __TBB_RETHROW(); @@ -290,21 +299,13 @@ public: return (pnode); } -#endif //__TBB_CPP11_RVALUE_REF_PRESENT - - // Allocate a new node with the given order key; used to allocate dummy nodes - nodeptr_t create_node(sokey_t order_key) { - nodeptr_t pnode = my_node_allocator.allocate(1); - pnode->init(order_key); - return (pnode); - } split_ordered_list(allocator_type a = allocator_type()) : my_node_allocator(a), my_element_count(0) { // Immediately allocate a dummy node with order key of 0. This node // will always be the head of the list. - my_head = create_node(0); + my_head = create_node(sokey_t(0)); } ~split_ordered_list() @@ -481,30 +482,27 @@ public: my_node_allocator.deallocate(pnode, 1); } - // Try to insert a new element in the list. If insert fails, return the node that - // was inserted instead. - nodeptr_t try_insert(nodeptr_t previous, nodeptr_t new_node, nodeptr_t current_node) { + // Try to insert a new element in the list. + // If insert fails, return the node that was inserted instead. + static nodeptr_t try_insert_atomic(nodeptr_t previous, nodeptr_t new_node, nodeptr_t current_node) { new_node->my_next = current_node; return previous->atomic_set_next(new_node, current_node); } // Insert a new element between passed in iterators - std::pair try_insert(raw_iterator it, raw_iterator next, const value_type &value, sokey_t order_key, size_type *new_count) + std::pair try_insert(raw_iterator it, raw_iterator next, nodeptr_t pnode, size_type *new_count) { - nodeptr_t pnode = create_node(order_key, value); - nodeptr_t inserted_node = try_insert(it.get_node_ptr(), pnode, next.get_node_ptr()); + nodeptr_t inserted_node = try_insert_atomic(it.get_node_ptr(), pnode, next.get_node_ptr()); if (inserted_node == pnode) { // If the insert succeeded, check that the order is correct and increment the element count check_range(it, next); - *new_count = __TBB_FetchAndAddW((uintptr_t*)&my_element_count, uintptr_t(1)); + *new_count = tbb::internal::as_atomic(my_element_count).fetch_and_increment(); return std::pair(iterator(pnode, this), true); } else { - // If the insert failed (element already there), then delete the new one - destroy_node(pnode); return std::pair(end(), false); } } @@ -533,7 +531,7 @@ public: __TBB_ASSERT(get_order_key(it) < order_key, "Invalid node order in the list"); // Try to insert it in the right place - nodeptr_t inserted_node = try_insert(it.get_node_ptr(), dummy_node, where.get_node_ptr()); + nodeptr_t inserted_node = try_insert_atomic(it.get_node_ptr(), dummy_node, where.get_node_ptr()); if (inserted_node == dummy_node) { @@ -606,7 +604,7 @@ public: nodeptr_t pnode = it.get_node_ptr(); nodeptr_t dummy_node = pnode->is_dummy() ? create_node(pnode->get_order_key()) : create_node(pnode->get_order_key(), pnode->my_element); - previous_node = try_insert(previous_node, dummy_node, NULL); + previous_node = try_insert_atomic(previous_node, dummy_node, NULL); __TBB_ASSERT(previous_node != NULL, "Insertion must succeed"); raw_const_iterator where = it++; source.erase_node(get_iterator(begin_iterator), where); @@ -647,32 +645,6 @@ private: nodeptr_t my_head; // pointer to head node }; -// Template class for hash compare -template -class hash_compare -{ -public: - typedef Hasher hasher; - typedef Key_equality key_equal; - - hash_compare() {} - - hash_compare(Hasher a_hasher) : my_hash_object(a_hasher) {} - - hash_compare(Hasher a_hasher, Key_equality a_keyeq) : my_hash_object(a_hasher), my_key_compare_object(a_keyeq) {} - - size_t operator()(const Key& key) const { - return ((size_t)my_hash_object(key)); - } - - bool operator()(const Key& key1, const Key& key2) const { - return (!my_key_compare_object(key1, key2)); - } - - Hasher my_hash_object; // The hash object - Key_equality my_key_compare_object; // The equality comparator object -}; - #if defined(_MSC_VER) && !defined(__INTEL_COMPILER) #pragma warning(push) #pragma warning(disable: 4127) // warning C4127: conditional expression is constant @@ -792,7 +764,7 @@ protected: node = my_solist.create_node(pnode->get_order_key(), std::move(pnode->my_element)); } - previous_node = my_solist.try_insert(previous_node, node, NULL); + previous_node = my_solist.try_insert_atomic(previous_node, node, NULL); __TBB_ASSERT(previous_node != NULL, "Insertion of node failed. Concurrent inserts in constructor ?"); } my_solist.check_range(); @@ -802,7 +774,7 @@ protected: clear_buckets_on_exception.dismiss(); } -#endif //__TBB_CPP11_RVALUE_REF_PRESENT +#endif // __TBB_CPP11_RVALUE_REF_PRESENT concurrent_unordered_base& operator=(const concurrent_unordered_base& right) { if (this != &right) @@ -832,7 +804,7 @@ protected: return *this; } -#endif //__TBB_CPP11_RVALUE_REF_PRESENT +#endif // __TBB_CPP11_RVALUE_REF_PRESENT #if __TBB_INITIALIZER_LISTS_PRESENT //! assignment operator from initializer_list @@ -842,7 +814,7 @@ protected: this->insert(il.begin(),il.end()); return (*this); } -#endif //# __TBB_INITIALIZER_LISTS_PRESENT +#endif // __TBB_INITIALIZER_LISTS_PRESENT ~concurrent_unordered_base() { @@ -994,6 +966,36 @@ public: return insert(value).first; } +#if __TBB_CPP11_RVALUE_REF_PRESENT + std::pair insert(value_type&& value) { + return internal_insert(std::move(value)); + } + + iterator insert(const_iterator, value_type&& value) { + // Ignore hint + return insert(std::move(value)).first; + } + +#if __TBB_CPP11_VARIADIC_TEMPLATES_PRESENT + template + std::pair emplace(Args&&... args) { + nodeptr_t pnode = my_solist.create_node_v(tbb::internal::forward(args)...); + const sokey_t hashed_element_key = (sokey_t) my_hash_compare(get_key(pnode->my_element)); + const sokey_t order_key = split_order_key_regular(hashed_element_key); + pnode->init(order_key); + + return internal_insert(pnode->my_element, pnode); + } + + template + iterator emplace_hint(const_iterator, Args&&... args) { + // Ignore hint + return emplace(tbb::internal::forward(args)...).first; + } + +#endif // __TBB_CPP11_VARIADIC_TEMPLATES_PRESENT +#endif // __TBB_CPP11_RVALUE_REF_PRESENT + template void insert(Iterator first, Iterator last) { for (Iterator it = first; it != last; ++it) @@ -1247,7 +1249,7 @@ private: //TODO: why not use std::distance? // Hash APIs - size_type internal_distance(const_iterator first, const_iterator last) const + static size_type internal_distance(const_iterator first, const_iterator last) { size_type num = 0; @@ -1258,11 +1260,13 @@ private: } // Insert an element in the hash given its value - std::pair internal_insert(const value_type& value) + template< typename ValueType> + std::pair internal_insert( __TBB_FORWARDING_REF(ValueType) value, nodeptr_t pnode = NULL) { sokey_t order_key = (sokey_t) my_hash_compare(get_key(value)); size_type bucket = order_key % my_number_of_buckets; + //TODO:refactor the get_bucket related stuff into separate function something like acquire_bucket(key_type) // If bucket is empty, initialize it first if (!is_initialized(bucket)) init_bucket(bucket); @@ -1280,10 +1284,16 @@ private: for (;;) { - if (where == last || solist_t::get_order_key(where) > order_key) + if (where == last || solist_t::get_order_key(where) > order_key || + // if multimapped, stop at the first item equal to us. + (allow_multimapping && solist_t::get_order_key(where) == order_key && + !my_hash_compare(get_key(*where), get_key(value)))) { - // Try to insert it in the right place - std::pair result = my_solist.try_insert(it, where, value, order_key, &new_count); + if (!pnode) + pnode = my_solist.create_node(order_key, tbb::internal::forward(value)); + + // Try to insert 'pnode' between 'it' and 'where' + std::pair result = my_solist.try_insert(it, where, pnode, &new_count); if (result.second) { @@ -1303,12 +1313,13 @@ private: continue; } } - else if (!allow_multimapping && solist_t::get_order_key(where) == order_key && my_hash_compare(get_key(*where), get_key(value)) == 0) - { - // Element already in the list, return it + else if (!allow_multimapping && solist_t::get_order_key(where) == order_key && + my_hash_compare(get_key(*where), get_key(value)) == 0) + { // Element already in the list, return it + if (pnode) + my_solist.destroy_node(pnode); return std::pair(my_solist.get_iterator(where), false); } - // Move the iterator forward it = where; ++where; @@ -1352,7 +1363,8 @@ private: // Erase an element from the list. This is not a concurrency safe function. iterator internal_erase(const_iterator it) { - key_type key = get_key(*it); + //const reference extends lifetime of possible temporary coming from get_key + const key_type& key = get_key(*it); sokey_t order_key = (sokey_t) my_hash_compare(key); size_type bucket = order_key % my_number_of_buckets; @@ -1528,47 +1540,8 @@ private: #pragma warning(pop) // warning 4127 is back #endif -//! Hash multiplier -static const size_t hash_multiplier = tbb::internal::select_size_t_constant<2654435769U, 11400714819323198485ULL>::value; } // namespace internal //! @endcond -//! Hasher functions -template -inline size_t tbb_hasher( const T& t ) { - return static_cast( t ) * internal::hash_multiplier; -} -template -inline size_t tbb_hasher( P* ptr ) { - size_t const h = reinterpret_cast( ptr ); - return (h >> 3) ^ h; -} -template -inline size_t tbb_hasher( const std::basic_string& s ) { - size_t h = 0; - for( const E* c = s.c_str(); *c; ++c ) - h = static_cast(*c) ^ (h * internal::hash_multiplier); - return h; -} -template -inline size_t tbb_hasher( const std::pair& p ) { - return tbb_hasher(p.first) ^ tbb_hasher(p.second); -} } // namespace interface5 -using interface5::tbb_hasher; - - -// Template class for hash compare -template -class tbb_hash -{ -public: - tbb_hash() {} - - size_t operator()(const Key& key) const - { - return tbb_hasher(key); - } -}; - } // namespace tbb -#endif// __TBB__concurrent_unordered_impl_H +#endif // __TBB__concurrent_unordered_impl_H diff --git a/dependencies64/tbb/include/tbb/internal/_flow_graph_impl.h b/dependencies64/tbb/include/tbb/internal/_flow_graph_impl.h index 97da56df7..c2f73b75d 100644 --- a/dependencies64/tbb/include/tbb/internal/_flow_graph_impl.h +++ b/dependencies64/tbb/include/tbb/internal/_flow_graph_impl.h @@ -1,5 +1,5 @@ /* - Copyright 2005-2014 Intel Corporation. All Rights Reserved. + Copyright 2005-2015 Intel Corporation. All Rights Reserved. This file is part of Threading Building Blocks. Threading Building Blocks is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License @@ -25,10 +25,32 @@ #error Do not #include this internal file directly; use public TBB headers instead. #endif +// included in namespace tbb::flow::interface8 (in flow_graph.h) + namespace internal { + typedef tbb::internal::uint64_t tag_value; + + using tbb::internal::strip; + namespace graph_policy_namespace { - enum graph_buffer_policy { rejecting, reserving, queueing, tag_matching }; + + struct rejecting { }; + struct reserving { }; + struct queueing { }; + + // K == type of field used for key-matching. Each tag-matching port will be provided + // functor that, given an object accepted by the port, will return the + /// field of type K being used for matching. + template::type > > + struct key_matching { + typedef K key_type; + typedef typename strip::type base_key_type; + typedef KHash hash_compare_type; + }; + + // old tag_matching join's new specifier + typedef key_matching tag_matching; } // -------------- function_body containers ---------------------- @@ -40,29 +62,20 @@ namespace internal { virtual ~source_body() {} virtual bool operator()(Output &output) = 0; virtual source_body* clone() = 0; -#if TBB_PREVIEW_FLOW_GRAPH_FEATURES - virtual void reset_body() = 0; -#endif }; //! The leaf for source_body template< typename Output, typename Body> class source_body_leaf : public source_body { public: - source_body_leaf( const Body &_body ) : body(_body), init_body(_body) { } + source_body_leaf( const Body &_body ) : body(_body) { } /*override*/ bool operator()(Output &output) { return body( output ); } /*override*/ source_body_leaf* clone() { - return new source_body_leaf< Output, Body >(init_body); - } -#if TBB_PREVIEW_FLOW_GRAPH_FEATURES - /*override*/ void reset_body() { - body = init_body; + return new source_body_leaf< Output, Body >(body); } -#endif Body get_body() { return body; } private: Body body; - Body init_body; }; //! A functor that takes an Input and generates an Output @@ -72,97 +85,70 @@ namespace internal { virtual ~function_body() {} virtual Output operator()(const Input &input) = 0; virtual function_body* clone() = 0; -#if TBB_PREVIEW_FLOW_GRAPH_FEATURES - virtual void reset_body() = 0; -#endif }; //! the leaf for function_body template class function_body_leaf : public function_body< Input, Output > { public: - function_body_leaf( const B &_body ) : body(_body), init_body(_body) { } + function_body_leaf( const B &_body ) : body(_body) { } Output operator()(const Input &i) { return body(i); } -#if TBB_PREVIEW_FLOW_GRAPH_FEATURES - /*override*/ void reset_body() { - body = init_body; - } -#endif B get_body() { return body; } /*override*/ function_body_leaf* clone() { - return new function_body_leaf< Input, Output, B >(init_body); + return new function_body_leaf< Input, Output, B >(body); } private: B body; - B init_body; }; //! the leaf for function_body specialized for Input and output of continue_msg template class function_body_leaf< continue_msg, continue_msg, B> : public function_body< continue_msg, continue_msg > { public: - function_body_leaf( const B &_body ) : body(_body), init_body(_body) { } + function_body_leaf( const B &_body ) : body(_body) { } continue_msg operator()( const continue_msg &i ) { body(i); return i; } -#if TBB_PREVIEW_FLOW_GRAPH_FEATURES - /*override*/ void reset_body() { - body = init_body; - } -#endif B get_body() { return body; } /*override*/ function_body_leaf* clone() { - return new function_body_leaf< continue_msg, continue_msg, B >(init_body); + return new function_body_leaf< continue_msg, continue_msg, B >(body); } private: B body; - B init_body; }; //! the leaf for function_body specialized for Output of continue_msg template class function_body_leaf< Input, continue_msg, B> : public function_body< Input, continue_msg > { public: - function_body_leaf( const B &_body ) : body(_body), init_body(_body) { } + function_body_leaf( const B &_body ) : body(_body) { } continue_msg operator()(const Input &i) { body(i); return continue_msg(); } -#if TBB_PREVIEW_FLOW_GRAPH_FEATURES - /*override*/ void reset_body() { - body = init_body; - } -#endif B get_body() { return body; } /*override*/ function_body_leaf* clone() { - return new function_body_leaf< Input, continue_msg, B >(init_body); + return new function_body_leaf< Input, continue_msg, B >(body); } private: B body; - B init_body; }; //! the leaf for function_body specialized for Input of continue_msg template class function_body_leaf< continue_msg, Output, B > : public function_body< continue_msg, Output > { public: - function_body_leaf( const B &_body ) : body(_body), init_body(_body) { } + function_body_leaf( const B &_body ) : body(_body) { } Output operator()(const continue_msg &i) { return body(i); } -#if TBB_PREVIEW_FLOW_GRAPH_FEATURES - /*override*/ void reset_body() { - body = init_body; - } -#endif B get_body() { return body; } /*override*/ function_body_leaf* clone() { - return new function_body_leaf< continue_msg, Output, B >(init_body); + return new function_body_leaf< continue_msg, Output, B >(body); } private: B body; - B init_body; }; //! function_body that takes an Input and a set of output ports @@ -172,33 +158,101 @@ namespace internal { virtual ~multifunction_body () {} virtual void operator()(const Input &/* input*/, OutputSet &/*oset*/) = 0; virtual multifunction_body* clone() = 0; -#if TBB_PREVIEW_FLOW_GRAPH_FEATURES - virtual void reset_body() = 0; -#endif }; //! leaf for multifunction. OutputSet can be a std::tuple or a vector. template class multifunction_body_leaf : public multifunction_body { public: - multifunction_body_leaf(const B &_body) : body(_body), init_body(_body) { } + multifunction_body_leaf(const B &_body) : body(_body) { } void operator()(const Input &input, OutputSet &oset) { body(input, oset); // body may explicitly put() to one or more of oset. } -#if TBB_PREVIEW_FLOW_GRAPH_FEATURES - /*override*/ void reset_body() { - body = init_body; - } -#endif B get_body() { return body; } /*override*/ multifunction_body_leaf* clone() { - return new multifunction_body_leaf(init_body); + return new multifunction_body_leaf(body); } private: B body; - B init_body; }; +// ------ function bodies for hash_buffers and key-matching joins. + +template +class type_to_key_function_body : tbb::internal::no_assign { + public: + virtual ~type_to_key_function_body() {} + virtual Output operator()(const Input &input) = 0; // returns an Output + virtual type_to_key_function_body* clone() = 0; +}; + +// specialization for ref output +template +class type_to_key_function_body : tbb::internal::no_assign { + public: + virtual ~type_to_key_function_body() {} + virtual const Output & operator()(const Input &input) = 0; // returns a const Output& + virtual type_to_key_function_body* clone() = 0; +}; + +template +class type_to_key_function_body_leaf : public type_to_key_function_body { +public: + type_to_key_function_body_leaf( const B &_body ) : body(_body) { } + /*override*/Output operator()(const Input &i) { return body(i); } + B get_body() { return body; } + /*override*/ type_to_key_function_body_leaf* clone() { + return new type_to_key_function_body_leaf< Input, Output, B>(body); + } +private: + B body; +}; + +template +class type_to_key_function_body_leaf : public type_to_key_function_body< Input, Output&> { +public: + type_to_key_function_body_leaf( const B &_body ) : body(_body) { } + + /*override*/const Output& operator()(const Input &i) { + return const_cast(body(i)); + } + + B get_body() { return body; } + + /*override*/ type_to_key_function_body_leaf* clone() { + return new type_to_key_function_body_leaf< Input, Output&, B>(body); + } + +private: + B body; +}; + +#if __TBB_PREVIEW_ASYNC_NODE + + //! A functor that takes Input and submit it to Asynchronous Activity + template< typename Input, typename AsyncGateway > + class async_body : tbb::internal::no_assign { + public: + virtual ~async_body() {} + virtual void operator()(const Input &output, AsyncGateway& gateway) = 0; + virtual async_body* clone() = 0; + }; + + //! The leaf for async_body + template< typename Input, typename Body, typename AsyncGateway > + class async_body_leaf : public async_body< Input, AsyncGateway > { + public: + async_body_leaf( const Body &_body ) : body(_body) { } + /*override*/ void operator()(const Input &input, AsyncGateway& gateway) { body( input, gateway ); } + /*override*/ async_body_leaf* clone() { + return new async_body_leaf< Input, Body, AsyncGateway >(body); + } + Body get_body() { return body; } + private: + Body body; + }; +#endif + // --------------------------- end of function_body containers ------------------------ // --------------------------- node task bodies --------------------------------------- @@ -272,17 +326,17 @@ namespace internal { typedef size_t size_type; bool empty() { - typename my_mutex_type::scoped_lock lock( my_mutex ); + typename mutex_type::scoped_lock lock( my_mutex ); return internal_empty(); } void add( T &n ) { - typename my_mutex_type::scoped_lock lock( my_mutex ); + typename mutex_type::scoped_lock lock( my_mutex ); internal_push(n); } void remove( T &n ) { - typename my_mutex_type::scoped_lock lock( my_mutex ); + typename mutex_type::scoped_lock lock( my_mutex ); for ( size_t i = internal_size(); i != 0; --i ) { T &s = internal_pop(); if ( &s == &n ) return; // only remove one predecessor per request @@ -290,36 +344,46 @@ namespace internal { } } + void clear() { + while( !my_q.empty()) (void)my_q.pop(); +#if TBB_PREVIEW_FLOW_GRAPH_FEATURES + my_built_predecessors.clear(); +#endif + } + #if TBB_PREVIEW_FLOW_GRAPH_FEATURES - typedef std::vector predecessor_vector_type; + typedef edge_container built_predecessors_type; + built_predecessors_type &built_predecessors() { return my_built_predecessors; } + + typedef typename edge_container::edge_list_type predecessor_list_type; void internal_add_built_predecessor( T &n ) { - typename my_mutex_type::scoped_lock lock( my_mutex ); + typename mutex_type::scoped_lock lock( my_mutex ); my_built_predecessors.add_edge(n); } void internal_delete_built_predecessor( T &n ) { - typename my_mutex_type::scoped_lock lock( my_mutex ); + typename mutex_type::scoped_lock lock( my_mutex ); my_built_predecessors.delete_edge(n); } - void copy_predecessors( predecessor_vector_type &v) { - typename my_mutex_type::scoped_lock lock( my_mutex ); + void copy_predecessors( predecessor_list_type &v) { + typename mutex_type::scoped_lock lock( my_mutex ); my_built_predecessors.copy_edges(v); } size_t predecessor_count() { - typename my_mutex_type::scoped_lock lock(my_mutex); + typename mutex_type::scoped_lock lock(my_mutex); return (size_t)(my_built_predecessors.edge_count()); } -#endif /* TBB_PREVIEW_FLOW_GRAPH_FEATURES */ +#endif /* TBB_PREVIEW_FLOW_GRAPH_FEATURES */ protected: - typedef M my_mutex_type; - my_mutex_type my_mutex; + typedef M mutex_type; + mutex_type my_mutex; std::queue< T * > my_q; #if TBB_PREVIEW_FLOW_GRAPH_FEATURES - edge_container my_built_predecessors; + built_predecessors_type my_built_predecessors; #endif // Assumes lock is held @@ -350,7 +414,7 @@ namespace internal { template< typename T, typename M=spin_mutex > class predecessor_cache : public node_cache< sender, M > { public: - typedef M my_mutex_type; + typedef M mutex_type; typedef T output_type; typedef sender predecessor_type; typedef receiver successor_type; @@ -366,7 +430,7 @@ namespace internal { do { predecessor_type *src; { - typename my_mutex_type::scoped_lock lock(this->my_mutex); + typename mutex_type::scoped_lock lock(this->my_mutex); if ( this->internal_empty() ) { break; } @@ -388,7 +452,8 @@ namespace internal { return msg; } - void reset( __TBB_PFG_RESET_ARG(reset_flags f)) { + // If we are removing arcs (rf_clear_edges), call clear() rather than reset(). + void reset() { if(my_owner) { for(;;) { predecessor_type *src; @@ -396,14 +461,9 @@ namespace internal { if(this->internal_empty()) break; src = &this->internal_pop(); } - src->register_successor( *my_owner); + src->register_successor( *my_owner); } } -#if TBB_PREVIEW_FLOW_GRAPH_FEATURES - if (f&rf_extract && my_owner) - my_built_predecessors.receiver_extract(*my_owner); - __TBB_ASSERT(!(f&rf_extract) || this->internal_empty(), "predecessor cache not empty"); -#endif } protected: @@ -418,7 +478,7 @@ namespace internal { template< typename T, typename M=spin_mutex > class reservable_predecessor_cache : public predecessor_cache< T, M > { public: - typedef M my_mutex_type; + typedef M mutex_type; typedef T output_type; typedef sender predecessor_type; typedef receiver successor_type; @@ -431,7 +491,7 @@ namespace internal { do { { - typename my_mutex_type::scoped_lock lock(this->my_mutex); + typename mutex_type::scoped_lock lock(this->my_mutex); if ( reserved_src || this->internal_empty() ) return false; @@ -442,7 +502,7 @@ namespace internal { msg = reserved_src->try_reserve( v ); if (msg == false) { - typename my_mutex_type::scoped_lock lock(this->my_mutex); + typename mutex_type::scoped_lock lock(this->my_mutex); // Relinquish ownership of the edge reserved_src->register_successor( *this->my_owner ); reserved_src = NULL; @@ -469,9 +529,14 @@ namespace internal { return true; } - void reset( __TBB_PFG_RESET_ARG(reset_flags f)) { + void reset( ) { + reserved_src = NULL; + predecessor_cache::reset( ); + } + + void clear() { reserved_src = NULL; - predecessor_cache::reset(__TBB_PFG_RESET_ARG(f)); + predecessor_cache::clear(); } private: @@ -484,45 +549,45 @@ namespace internal { class successor_cache : tbb::internal::no_copy { protected: - typedef M my_mutex_type; - my_mutex_type my_mutex; + typedef M mutex_type; + mutex_type my_mutex; + typedef receiver successor_type; typedef receiver *pointer_type; - typedef std::list< pointer_type > my_successors_type; + typedef std::list< pointer_type > successors_type; #if TBB_PREVIEW_FLOW_GRAPH_FEATURES - edge_container > my_built_successors; + edge_container my_built_successors; #endif - my_successors_type my_successors; + successors_type my_successors; sender *my_owner; public: #if TBB_PREVIEW_FLOW_GRAPH_FEATURES - typedef std::vector successor_vector_type; - void internal_add_built_successor( receiver &r) { - typename my_mutex_type::scoped_lock l(my_mutex, true); + typedef typename edge_container::edge_list_type successor_list_type; + + edge_container &built_successors() { return my_built_successors; } + + void internal_add_built_successor( successor_type &r) { + typename mutex_type::scoped_lock l(my_mutex, true); my_built_successors.add_edge( r ); } - void internal_delete_built_successor( receiver &r) { - typename my_mutex_type::scoped_lock l(my_mutex, true); + void internal_delete_built_successor( successor_type &r) { + typename mutex_type::scoped_lock l(my_mutex, true); my_built_successors.delete_edge(r); } - void copy_successors( successor_vector_type &v) { - typename my_mutex_type::scoped_lock l(my_mutex, false); + void copy_successors( successor_list_type &v) { + typename mutex_type::scoped_lock l(my_mutex, false); my_built_successors.copy_edges(v); } size_t successor_count() { - typename my_mutex_type::scoped_lock l(my_mutex,false); + typename mutex_type::scoped_lock l(my_mutex,false); return my_built_successors.edge_count(); } - void reset( __TBB_PFG_RESET_ARG(reset_flags f)) { - if (f&rf_extract && my_owner) - my_built_successors.sender_extract(*my_owner); - } #endif /* TBB_PREVIEW_FLOW_GRAPH_FEATURES */ successor_cache( ) : my_owner(NULL) {} @@ -531,14 +596,14 @@ namespace internal { virtual ~successor_cache() {} - void register_successor( receiver &r ) { - typename my_mutex_type::scoped_lock l(my_mutex, true); + void register_successor( successor_type &r ) { + typename mutex_type::scoped_lock l(my_mutex, true); my_successors.push_back( &r ); } - void remove_successor( receiver &r ) { - typename my_mutex_type::scoped_lock l(my_mutex, true); - for ( typename my_successors_type::iterator i = my_successors.begin(); + void remove_successor( successor_type &r ) { + typename mutex_type::scoped_lock l(my_mutex, true); + for ( typename successors_type::iterator i = my_successors.begin(); i != my_successors.end(); ++i ) { if ( *i == & r ) { my_successors.erase(i); @@ -548,7 +613,7 @@ namespace internal { } bool empty() { - typename my_mutex_type::scoped_lock l(my_mutex, false); + typename mutex_type::scoped_lock l(my_mutex, false); return my_successors.empty(); } @@ -560,21 +625,23 @@ namespace internal { } virtual task * try_put_task( const T &t ) = 0; - }; + }; // successor_cache //! An abstract cache of successors, specialized to continue_msg template<> class successor_cache< continue_msg > : tbb::internal::no_copy { protected: - typedef spin_rw_mutex my_mutex_type; - my_mutex_type my_mutex; + typedef spin_rw_mutex mutex_type; + mutex_type my_mutex; + typedef receiver successor_type; typedef receiver *pointer_type; - typedef std::list< pointer_type > my_successors_type; - my_successors_type my_successors; + typedef std::list< pointer_type > successors_type; + successors_type my_successors; #if TBB_PREVIEW_FLOW_GRAPH_FEATURES - edge_container > my_built_successors; + edge_container my_built_successors; + typedef edge_container::edge_list_type successor_list_type; #endif sender *my_owner; @@ -582,31 +649,29 @@ namespace internal { public: #if TBB_PREVIEW_FLOW_GRAPH_FEATURES - typedef std::vector successor_vector_type; - void internal_add_built_successor( receiver &r) { - my_mutex_type::scoped_lock l(my_mutex, true); + + edge_container &built_successors() { return my_built_successors; } + + void internal_add_built_successor( successor_type &r) { + mutex_type::scoped_lock l(my_mutex, true); my_built_successors.add_edge( r ); } - void internal_delete_built_successor( receiver &r) { - my_mutex_type::scoped_lock l(my_mutex, true); + void internal_delete_built_successor( successor_type &r) { + mutex_type::scoped_lock l(my_mutex, true); my_built_successors.delete_edge(r); } - void copy_successors( successor_vector_type &v) { - my_mutex_type::scoped_lock l(my_mutex, false); + void copy_successors( successor_list_type &v) { + mutex_type::scoped_lock l(my_mutex, false); my_built_successors.copy_edges(v); } size_t successor_count() { - my_mutex_type::scoped_lock l(my_mutex,false); + mutex_type::scoped_lock l(my_mutex,false); return my_built_successors.edge_count(); } - void reset( __TBB_PFG_RESET_ARG(reset_flags f)) { - if (f&rf_extract && my_owner) - my_built_successors.sender_extract(*my_owner); - } #endif /* TBB_PREVIEW_FLOW_GRAPH_FEATURES */ successor_cache( ) : my_owner(NULL) {} @@ -615,17 +680,17 @@ namespace internal { virtual ~successor_cache() {} - void register_successor( receiver &r ) { - my_mutex_type::scoped_lock l(my_mutex, true); + void register_successor( successor_type &r ) { + mutex_type::scoped_lock l(my_mutex, true); my_successors.push_back( &r ); if ( my_owner && r.is_continue_receiver() ) { r.register_predecessor( *my_owner ); } } - void remove_successor( receiver &r ) { - my_mutex_type::scoped_lock l(my_mutex, true); - for ( my_successors_type::iterator i = my_successors.begin(); + void remove_successor( successor_type &r ) { + mutex_type::scoped_lock l(my_mutex, true); + for ( successors_type::iterator i = my_successors.begin(); i != my_successors.end(); ++i ) { if ( *i == & r ) { // TODO: Check if we need to test for continue_receiver before @@ -639,7 +704,7 @@ namespace internal { } bool empty() { - my_mutex_type::scoped_lock l(my_mutex, false); + mutex_type::scoped_lock l(my_mutex, false); return my_successors.empty(); } @@ -652,13 +717,13 @@ namespace internal { virtual task * try_put_task( const continue_msg &t ) = 0; - }; + }; // successor_cache< continue_msg > //! A cache of successors that are broadcast to template class broadcast_cache : public successor_cache { - typedef M my_mutex_type; - typedef std::list< receiver * > my_successors_type; + typedef M mutex_type; + typedef typename successor_cache::successors_type successors_type; public: @@ -668,8 +733,8 @@ namespace internal { /*override*/ task * try_put_task( const T &t ) { task * last_task = NULL; bool upgraded = true; - typename my_mutex_type::scoped_lock l(this->my_mutex, upgraded); - typename my_successors_type::iterator i = this->my_successors.begin(); + typename mutex_type::scoped_lock l(this->my_mutex, upgraded); + typename successors_type::iterator i = this->my_successors.begin(); while ( i != this->my_successors.end() ) { task *new_task = (*i)->try_put_task(t); last_task = combine_tasks(last_task, new_task); // enqueue if necessary @@ -697,22 +762,22 @@ namespace internal { template class round_robin_cache : public successor_cache { typedef size_t size_type; - typedef M my_mutex_type; - typedef std::list< receiver * > my_successors_type; + typedef M mutex_type; + typedef typename successor_cache::successors_type successors_type; public: round_robin_cache( ) {} size_type size() { - typename my_mutex_type::scoped_lock l(this->my_mutex, false); + typename mutex_type::scoped_lock l(this->my_mutex, false); return this->my_successors.size(); } /*override*/task *try_put_task( const T &t ) { bool upgraded = true; - typename my_mutex_type::scoped_lock l(this->my_mutex, upgraded); - typename my_successors_type::iterator i = this->my_successors.begin(); + typename mutex_type::scoped_lock l(this->my_mutex, upgraded); + typename successors_type::iterator i = this->my_successors.begin(); while ( i != this->my_successors.end() ) { task *new_task = (*i)->try_put_task(t); if ( new_task ) { diff --git a/dependencies64/tbb/include/tbb/internal/_flow_graph_indexer_impl.h b/dependencies64/tbb/include/tbb/internal/_flow_graph_indexer_impl.h index 947e1d414..0ad4a993e 100644 --- a/dependencies64/tbb/include/tbb/internal/_flow_graph_indexer_impl.h +++ b/dependencies64/tbb/include/tbb/internal/_flow_graph_indexer_impl.h @@ -1,5 +1,5 @@ /* - Copyright 2005-2014 Intel Corporation. All Rights Reserved. + Copyright 2005-2015 Intel Corporation. All Rights Reserved. This file is part of Threading Building Blocks. Threading Building Blocks is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License @@ -49,12 +49,17 @@ namespace internal { tbb::flow::get(my_input).set_up(p, indexer_node_put_task); indexer_helper::template set_indexer_node_pointer(my_input, p); } -#if TBB_PREVIEW_FLOW_GRAPH_FEATURES template static inline void reset_inputs(InputTuple &my_input, reset_flags f) { - join_helper::reset_inputs(my_input, f); + indexer_helper::reset_inputs(my_input, f); tbb::flow::get(my_input).reset_receiver(f); } +#if TBB_PREVIEW_FLOW_GRAPH_FEATURES + template + static inline void extract(InputTuple &my_input) { + indexer_helper::extract(my_input); + tbb::flow::get(my_input).extract_receiver(); + } #endif }; @@ -66,11 +71,15 @@ namespace internal { task *(*indexer_node_put_task)(const T&, void *) = do_try_put; tbb::flow::get<0>(my_input).set_up(p, indexer_node_put_task); } -#if TBB_PREVIEW_FLOW_GRAPH_FEATURES template static inline void reset_inputs(InputTuple &my_input, reset_flags f) { tbb::flow::get<0>(my_input).reset_receiver(f); } +#if TBB_PREVIEW_FLOW_GRAPH_FEATURES + template + static inline void extract(InputTuple &my_input) { + tbb::flow::get<0>(my_input).extract_receiver(); + } #endif }; @@ -82,7 +91,8 @@ namespace internal { forward_function_ptr my_try_put_task; #if TBB_PREVIEW_FLOW_GRAPH_FEATURES spin_mutex my_pred_mutex; - edge_container > my_built_predecessors; + typedef typename receiver::built_predecessors_type built_predecessors_type; + built_predecessors_type my_built_predecessors; #endif /* TBB_PREVIEW_FLOW_GRAPH_FEATURES */ public: #if TBB_PREVIEW_FLOW_GRAPH_FEATURES @@ -95,7 +105,10 @@ namespace internal { my_try_put_task = f; } #if TBB_PREVIEW_FLOW_GRAPH_FEATURES - typedef std::vector *> predecessor_vector_type; + typedef typename receiver::predecessor_list_type predecessor_list_type; + + /*override*/ built_predecessors_type &built_predecessors() { return my_built_predecessors; } + /*override*/size_t predecessor_count() { spin_mutex::scoped_lock l(my_pred_mutex); return my_built_predecessors.edge_count(); @@ -108,10 +121,14 @@ namespace internal { spin_mutex::scoped_lock l(my_pred_mutex); my_built_predecessors.delete_edge(p); } - /*override*/void copy_predecessors( predecessor_vector_type &v) { + /*override*/void copy_predecessors( predecessor_list_type &v) { spin_mutex::scoped_lock l(my_pred_mutex); return my_built_predecessors.copy_edges(v); } + /*override*/void clear_predecessors() { + spin_mutex::scoped_lock l(my_pred_mutex); + my_built_predecessors.clear(); + } #endif /* TBB_PREVIEW_FLOW_GRAPH_FEATURES */ protected: template< typename R, typename B > friend class run_and_put_task; @@ -121,15 +138,16 @@ namespace internal { return my_try_put_task(v, my_indexer_ptr); } -#if TBB_PREVIEW_FLOW_GRAPH_FEATURES public: - /*override*/void reset_receiver(__TBB_PFG_RESET_ARG(reset_flags f)) { - if(f&rf_extract) my_built_predecessors.receiver_extract(*this); - } +#if TBB_PREVIEW_FLOW_GRAPH_FEATURES + /*override*/void reset_receiver(reset_flags f) { if(f&rf_clear_edges) my_built_predecessors.clear(); } #else - /*override*/void reset_receiver(__TBB_PFG_RESET_ARG(reset_flags /*f*/)) { } + /*override*/void reset_receiver(reset_flags /*f*/) { } #endif +#if TBB_PREVIEW_FLOW_GRAPH_FEATURES + void extract_receiver() { my_built_predecessors.receiver_extract(*this); } +#endif }; template @@ -157,7 +175,8 @@ namespace internal { typedef receiver successor_type; typedef indexer_node_FE input_ports_type; #if TBB_PREVIEW_FLOW_GRAPH_FEATURES - typedef std::vector successor_vector_type; + typedef typename sender::built_successors_type built_successors_type; + typedef typename sender::successor_list_type successor_list_type; #endif private: @@ -169,7 +188,7 @@ namespace internal { #endif }; enum op_stat {WAIT=0, SUCCEEDED, FAILED}; - typedef indexer_node_base my_class; + typedef indexer_node_base class_type; class indexer_node_base_operation : public aggregated_operation { public: @@ -180,7 +199,7 @@ namespace internal { task *bypass_t; #if TBB_PREVIEW_FLOW_GRAPH_FEATURES size_t cnt_val; - successor_vector_type *succv; + successor_list_type *succv; #endif }; indexer_node_base_operation(const output_type* e, op_type t) : @@ -190,9 +209,9 @@ namespace internal { indexer_node_base_operation(op_type t) : type(char(t)) {} }; - typedef internal::aggregating_functor my_handler; - friend class internal::aggregating_functor; - aggregator my_aggregator; + typedef internal::aggregating_functor handler_type; + friend class internal::aggregating_functor; + aggregator my_aggregator; void handle_operations(indexer_node_base_operation* op_list) { indexer_node_base_operation *current; @@ -241,13 +260,13 @@ namespace internal { indexer_node_base(graph& g) : graph_node(g), input_ports_type() { indexer_helper::set_indexer_node_pointer(this->my_inputs, this); my_successors.set_owner(this); - my_aggregator.initialize_handler(my_handler(this)); + my_aggregator.initialize_handler(handler_type(this)); } indexer_node_base(const indexer_node_base& other) : graph_node(other.my_graph), input_ports_type(), sender() { indexer_helper::set_indexer_node_pointer(this->my_inputs, this); my_successors.set_owner(this); - my_aggregator.initialize_handler(my_handler(this)); + my_aggregator.initialize_handler(handler_type(this)); } bool register_successor(successor_type &r) { @@ -269,6 +288,9 @@ namespace internal { } #if TBB_PREVIEW_FLOW_GRAPH_FEATURES + + built_successors_type &built_successors() { return my_successors.built_successors(); } + void internal_add_built_successor( successor_type &r) { indexer_node_base_operation op_data(r, add_blt_succ); my_aggregator.execute(&op_data); @@ -285,18 +307,22 @@ namespace internal { return op_data.cnt_val; } - void copy_successors( successor_vector_type &v) { + void copy_successors( successor_list_type &v) { indexer_node_base_operation op_data(blt_succ_cpy); op_data.succv = &v; my_aggregator.execute(&op_data); } + void extract() { + my_successors.built_successors().sender_extract(*this); + indexer_helper::extract(this->my_inputs); + } #endif /* TBB_PREVIEW_FLOW_GRAPH_FEATURES */ protected: - /*override*/void reset(__TBB_PFG_RESET_ARG(reset_flags f)) { -#if TBB_PREVIEW_FLOW_GRAPH_FEATURES - my_successors.reset(f); - indexer_helper::reset_inputs(this->my_inputs, f); -#endif + /*override*/void reset_node(reset_flags f) { + if(f & rf_clear_edges) { + my_successors.clear(); + indexer_helper::reset_inputs(this->my_inputs,f); + } } private: diff --git a/dependencies64/tbb/include/tbb/internal/_flow_graph_item_buffer_impl.h b/dependencies64/tbb/include/tbb/internal/_flow_graph_item_buffer_impl.h index 11665acf9..7a96734c2 100644 --- a/dependencies64/tbb/include/tbb/internal/_flow_graph_item_buffer_impl.h +++ b/dependencies64/tbb/include/tbb/internal/_flow_graph_item_buffer_impl.h @@ -1,5 +1,5 @@ /* - Copyright 2005-2014 Intel Corporation. All Rights Reserved. + Copyright 2005-2015 Intel Corporation. All Rights Reserved. This file is part of Threading Building Blocks. Threading Building Blocks is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License @@ -27,7 +27,7 @@ #include "tbb/internal/_flow_graph_types_impl.h" // for aligned_pair -// in namespace tbb::flow::interface7 (included in _flow_graph_node_impl.h) +// in namespace tbb::flow::interface8 (included in _flow_graph_node_impl.h) //! Expandable buffer of items. The possible operations are push, pop, //* tests for empty and so forth. No mutual exclusion is built in. diff --git a/dependencies64/tbb/include/tbb/internal/_flow_graph_join_impl.h b/dependencies64/tbb/include/tbb/internal/_flow_graph_join_impl.h index 3a8712134..f86d68dd5 100644 --- a/dependencies64/tbb/include/tbb/internal/_flow_graph_join_impl.h +++ b/dependencies64/tbb/include/tbb/internal/_flow_graph_join_impl.h @@ -1,5 +1,5 @@ /* - Copyright 2005-2014 Intel Corporation. All Rights Reserved. + Copyright 2005-2015 Intel Corporation. All Rights Reserved. This file is part of Threading Building Blocks. Threading Building Blocks is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License @@ -25,24 +25,27 @@ #error Do not #include this internal file directly; use public TBB headers instead. #endif -#include "_flow_graph_types_impl.h" - namespace internal { - typedef size_t tag_value; - static const tag_value NO_TAG = tag_value(-1); - struct forwarding_base { - forwarding_base(graph &g) : my_graph_ptr(&g), current_tag(NO_TAG) {} + forwarding_base(graph &g) : graph_pointer(&g) {} virtual ~forwarding_base() {} // decrement_port_count may create a forwarding task. If we cannot handle the task // ourselves, ask decrement_port_count to deal with it. virtual task * decrement_port_count(bool handle_task) = 0; virtual void increment_port_count() = 0; - virtual task * increment_tag_count(tag_value /*t*/, bool /*handle_task*/) {return NULL;} // moved here so input ports can queue tasks - graph* my_graph_ptr; - tag_value current_tag; // so ports can refer to FE's desired items + graph* graph_pointer; + }; + + // specialization that lets us keep a copy of the current_key for building results. + // KeyType can be a reference type. + template + struct matching_forwarding_base :public forwarding_base { + typedef typename tbb::internal::strip::type current_key_type; + matching_forwarding_base(graph &g) : forwarding_base(g) { } + virtual task * increment_key_count(current_key_type const & /*t*/, bool /*handle_task*/) = 0; // {return NULL;} + current_key_type current_key; // so ports can refer to FE's desired items }; template< int N > @@ -102,29 +105,35 @@ namespace internal { reset_my_port(my_input); } - template - static inline void set_tag_func(InputTuple &my_input, TagFuncTuple &my_tag_funcs) { - tbb::flow::get(my_input).set_my_original_tag_func(tbb::flow::get(my_tag_funcs)); - tbb::flow::get(my_input).set_my_tag_func(tbb::flow::get(my_input).my_original_func()->clone()); - tbb::flow::get(my_tag_funcs) = NULL; - join_helper::set_tag_func(my_input, my_tag_funcs); + template + static inline void set_key_functors(InputTuple &my_input, KeyFuncTuple &my_key_funcs) { + tbb::flow::get(my_input).set_my_key_func(tbb::flow::get(my_key_funcs)); + tbb::flow::get(my_key_funcs) = NULL; + join_helper::set_key_functors(my_input, my_key_funcs); } - template< typename TagFuncTuple1, typename TagFuncTuple2> - static inline void copy_tag_functors(TagFuncTuple1 &my_inputs, TagFuncTuple2 &other_inputs) { - if(tbb::flow::get(other_inputs).my_original_func()) { - tbb::flow::get(my_inputs).set_my_tag_func(tbb::flow::get(other_inputs).my_original_func()->clone()); - tbb::flow::get(my_inputs).set_my_original_tag_func(tbb::flow::get(other_inputs).my_original_func()->clone()); + template< typename KeyFuncTuple> + static inline void copy_key_functors(KeyFuncTuple &my_inputs, KeyFuncTuple &other_inputs) { + if(tbb::flow::get(other_inputs).get_my_key_func()) { + tbb::flow::get(my_inputs).set_my_key_func(tbb::flow::get(other_inputs).get_my_key_func()->clone()); } - join_helper::copy_tag_functors(my_inputs, other_inputs); + join_helper::copy_key_functors(my_inputs, other_inputs); } template - static inline void reset_inputs(InputTuple &my_input __TBB_PFG_RESET_ARG(__TBB_COMMA reset_flags f)) { - join_helper::reset_inputs(my_input __TBB_PFG_RESET_ARG(__TBB_COMMA f)); - tbb::flow::get(my_input).reset_receiver(__TBB_PFG_RESET_ARG(f)); + static inline void reset_inputs(InputTuple &my_input, reset_flags f) { + join_helper::reset_inputs(my_input, f); + tbb::flow::get(my_input).reset_receiver(f); } - }; + +#if TBB_PREVIEW_FLOW_GRAPH_FEATURES + template + static inline void extract_inputs(InputTuple &my_input) { + join_helper::extract_inputs(my_input); + tbb::flow::get(my_input).extract_receiver(); + } +#endif + }; // join_helper template< > struct join_helper<1> { @@ -174,25 +183,30 @@ namespace internal { reset_my_port(my_input); } - template - static inline void set_tag_func(InputTuple &my_input, TagFuncTuple &my_tag_funcs) { - tbb::flow::get<0>(my_input).set_my_original_tag_func(tbb::flow::get<0>(my_tag_funcs)); - tbb::flow::get<0>(my_input).set_my_tag_func(tbb::flow::get<0>(my_input).my_original_func()->clone()); - tbb::flow::get<0>(my_tag_funcs) = NULL; + template + static inline void set_key_functors(InputTuple &my_input, KeyFuncTuple &my_key_funcs) { + tbb::flow::get<0>(my_input).set_my_key_func(tbb::flow::get<0>(my_key_funcs)); + tbb::flow::get<0>(my_key_funcs) = NULL; } - template< typename TagFuncTuple1, typename TagFuncTuple2> - static inline void copy_tag_functors(TagFuncTuple1 &my_inputs, TagFuncTuple2 &other_inputs) { - if(tbb::flow::get<0>(other_inputs).my_original_func()) { - tbb::flow::get<0>(my_inputs).set_my_tag_func(tbb::flow::get<0>(other_inputs).my_original_func()->clone()); - tbb::flow::get<0>(my_inputs).set_my_original_tag_func(tbb::flow::get<0>(other_inputs).my_original_func()->clone()); + template< typename KeyFuncTuple> + static inline void copy_key_functors(KeyFuncTuple &my_inputs, KeyFuncTuple &other_inputs) { + if(tbb::flow::get<0>(other_inputs).get_my_key_func()) { + tbb::flow::get<0>(my_inputs).set_my_key_func(tbb::flow::get<0>(other_inputs).get_my_key_func()->clone()); } } template - static inline void reset_inputs(InputTuple &my_input __TBB_PFG_RESET_ARG(__TBB_COMMA reset_flags f)) { - tbb::flow::get<0>(my_input).reset_receiver(__TBB_PFG_RESET_ARG(f)); + static inline void reset_inputs(InputTuple &my_input, reset_flags f) { + tbb::flow::get<0>(my_input).reset_receiver(f); } - }; + +#if TBB_PREVIEW_FLOW_GRAPH_FEATURES + template + static inline void extract_inputs(InputTuple &my_input) { + tbb::flow::get<0>(my_input).extract_receiver(); + } +#endif + }; // join_helper<1> //! The two-phase join port template< typename T > @@ -201,7 +215,8 @@ namespace internal { typedef T input_type; typedef sender predecessor_type; #if TBB_PREVIEW_FLOW_GRAPH_FEATURES - typedef std::vector predecessor_vector_type; + typedef typename receiver::predecessor_list_type predecessor_list_type; + typedef typename receiver::built_predecessors_type built_predecessors_type; #endif private: // ----------- Aggregator ------------ @@ -211,7 +226,7 @@ namespace internal { #endif }; enum op_stat {WAIT=0, SUCCEEDED, FAILED}; - typedef reserving_port my_class; + typedef reserving_port class_type; class reserving_port_operation : public aggregated_operation { public: @@ -221,7 +236,7 @@ namespace internal { predecessor_type *my_pred; #if TBB_PREVIEW_FLOW_GRAPH_FEATURES size_t cnt_val; - predecessor_vector_type *pvec; + predecessor_list_type *plist; #endif }; reserving_port_operation(const T& e, op_type t) : @@ -231,9 +246,9 @@ namespace internal { reserving_port_operation(op_type t) : type(char(t)) {} }; - typedef internal::aggregating_functor my_handler; - friend class internal::aggregating_functor; - aggregator my_aggregator; + typedef internal::aggregating_functor handler_type; + friend class internal::aggregating_functor; + aggregator my_aggregator; void handle_operations(reserving_port_operation* op_list) { reserving_port_operation *current; @@ -293,7 +308,7 @@ namespace internal { __TBB_store_with_release(current->status, SUCCEEDED); break; case blt_pred_cpy: - my_predecessors.copy_predecessors(*(current->pvec)); + my_predecessors.copy_predecessors(*(current->plist)); __TBB_store_with_release(current->status, SUCCEEDED); break; #endif /* TBB_PREVIEW_FLOW_GRAPH_FEATURES */ @@ -315,7 +330,7 @@ namespace internal { reserving_port() : reserved(false) { my_join = NULL; my_predecessors.set_owner( this ); - my_aggregator.initialize_handler(my_handler(this)); + my_aggregator.initialize_handler(handler_type(this)); } // copy constructor @@ -323,7 +338,7 @@ namespace internal { reserved = false; my_join = NULL; my_predecessors.set_owner( this ); - my_aggregator.initialize_handler(my_handler(this)); + my_aggregator.initialize_handler(handler_type(this)); } void set_join_node_pointer(forwarding_base *join) { @@ -364,6 +379,7 @@ namespace internal { } #if TBB_PREVIEW_FLOW_GRAPH_FEATURES + /*override*/ built_predecessors_type &built_predecessors() { return my_predecessors.built_predecessors(); } /*override*/void internal_add_built_predecessor(predecessor_type &src) { reserving_port_operation op_data(src, add_blt_pred); my_aggregator.execute(&op_data); @@ -380,26 +396,31 @@ namespace internal { return op_data.cnt_val; } - /*override*/void copy_predecessors(predecessor_vector_type &v) { + /*override*/void copy_predecessors(predecessor_list_type &l) { reserving_port_operation op_data(blt_pred_cpy); - op_data.pvec = &v; + op_data.plist = &l; my_aggregator.execute(&op_data); } + + void extract_receiver() { + my_predecessors.built_predecessors().receiver_extract(*this); + } + #endif /* TBB_PREVIEW_FLOW_GRAPH_FEATURES */ - /*override*/void reset_receiver( __TBB_PFG_RESET_ARG(reset_flags f)) { - my_predecessors.reset(__TBB_PFG_RESET_ARG(f)); + /*override*/void reset_receiver( reset_flags f) { + if(f & rf_clear_edges) my_predecessors.clear(); + else + my_predecessors.reset(); reserved = false; -#if TBB_PREVIEW_FLOW_GRAPH_FEATURES - __TBB_ASSERT(!(f&rf_extract) || my_predecessors.empty(), "port edges not removed"); -#endif + __TBB_ASSERT(!(f&rf_clear_edges) || my_predecessors.empty(), "port edges not removed"); } private: forwarding_base *my_join; reservable_predecessor_cache< T, null_mutex > my_predecessors; bool reserved; - }; + }; // reserving_port //! queueing join_port template @@ -407,20 +428,20 @@ namespace internal { public: typedef T input_type; typedef sender predecessor_type; - typedef queueing_port my_node_type; + typedef queueing_port class_type; #if TBB_PREVIEW_FLOW_GRAPH_FEATURES - typedef std::vector predecessor_vector_type; + typedef typename receiver::built_predecessors_type built_predecessors_type; + typedef typename receiver::predecessor_list_type predecessor_list_type; #endif // ----------- Aggregator ------------ private: enum op_type { get__item, res_port, try__put_task #if TBB_PREVIEW_FLOW_GRAPH_FEATURES - , add_blt_pred, del_blt_pred, blt_pred_cnt, blt_pred_cpy + , add_blt_pred, del_blt_pred, blt_pred_cnt, blt_pred_cpy #endif }; enum op_stat {WAIT=0, SUCCEEDED, FAILED}; - typedef queueing_port my_class; class queueing_port_operation : public aggregated_operation { public: @@ -430,7 +451,7 @@ namespace internal { #if TBB_PREVIEW_FLOW_GRAPH_FEATURES sender *pred; size_t cnt_val; - predecessor_vector_type *pvec; + predecessor_list_type *plist; #endif task * bypass_t; // constructor for value parameter @@ -449,9 +470,9 @@ namespace internal { {} }; - typedef internal::aggregating_functor my_handler; - friend class internal::aggregating_functor; - aggregator my_aggregator; + typedef internal::aggregating_functor handler_type; + friend class internal::aggregating_functor; + aggregator my_aggregator; void handle_operations(queueing_port_operation* op_list) { queueing_port_operation *current; @@ -502,7 +523,7 @@ namespace internal { __TBB_store_with_release(current->status, SUCCEEDED); break; case blt_pred_cpy: - my_built_predecessors.copy_edges(*(current->pvec)); + my_built_predecessors.copy_edges(*(current->plist)); __TBB_store_with_release(current->status, SUCCEEDED); break; #endif /* TBB_PREVIEW_FLOW_GRAPH_FEATURES */ @@ -528,13 +549,13 @@ namespace internal { //! Constructor queueing_port() : item_buffer() { my_join = NULL; - my_aggregator.initialize_handler(my_handler(this)); + my_aggregator.initialize_handler(handler_type(this)); } //! copy constructor queueing_port(const queueing_port& /* other */) : receiver(), item_buffer() { my_join = NULL; - my_aggregator.initialize_handler(my_handler(this)); + my_aggregator.initialize_handler(handler_type(this)); } //! record parent for tallying available items @@ -557,6 +578,8 @@ namespace internal { } #if TBB_PREVIEW_FLOW_GRAPH_FEATURES + /*override*/ built_predecessors_type &built_predecessors() { return my_built_predecessors; } + /*override*/void internal_add_built_predecessor(sender &p) { queueing_port_operation op_data(add_blt_pred); op_data.pred = &p; @@ -575,97 +598,127 @@ namespace internal { return op_data.cnt_val; } - /*override*/void copy_predecessors(predecessor_vector_type &v) { + /*override*/void copy_predecessors(predecessor_list_type &l) { queueing_port_operation op_data(blt_pred_cpy); - op_data.pvec = &v; + op_data.plist = &l; my_aggregator.execute(&op_data); } - /*override*/void reset_receiver(__TBB_PFG_RESET_ARG(reset_flags f)) { + void extract_receiver() { item_buffer::reset(); - if (f & rf_extract) - my_built_predecessors.receiver_extract(*this); + my_built_predecessors.receiver_extract(*this); } -#else - /*override*/void reset_receiver(__TBB_PFG_RESET_ARG(reset_flags /*f*/)) { item_buffer::reset(); } #endif /* TBB_PREVIEW_FLOW_GRAPH_FEATURES */ + /*override*/void reset_receiver(reset_flags f) { + tbb::internal::suppress_unused_warning(f); + item_buffer::reset(); +#if TBB_PREVIEW_FLOW_GRAPH_FEATURES + if (f & rf_clear_edges) + my_built_predecessors.clear(); +#endif + } + private: forwarding_base *my_join; #if TBB_PREVIEW_FLOW_GRAPH_FEATURES edge_container > my_built_predecessors; #endif - }; + }; // queueing_port #include "_flow_graph_tagged_buffer_impl.h" - template< typename T > - class tag_matching_port : public receiver, public tagged_buffer< tag_value, T, NO_TAG > { + template + struct count_element { + K my_key; + size_t my_value; + }; + + // method to access the key in the counting table + // the ref has already been removed from K + template< typename K > + struct key_to_count_functor { + typedef count_element table_item_type; + const K& operator()(const table_item_type& v) { return v.my_key; } + }; + + // the ports can have only one template parameter. We wrap the types needed in + // a traits type + template< class TraitsType > + class key_matching_port : + public receiver, + public hash_buffer< typename TraitsType::K, typename TraitsType::T, typename TraitsType::TtoK, + typename TraitsType::KHash > { public: - typedef T input_type; - typedef sender predecessor_type; - typedef tag_matching_port my_node_type; // for forwarding, if needed - typedef function_body my_tag_func_type; - typedef tagged_buffer my_buffer_type; + typedef TraitsType traits; + typedef key_matching_port class_type; + typedef typename TraitsType::T input_type; + typedef typename TraitsType::K key_type; + typedef typename tbb::internal::strip::type noref_key_type; + typedef sender predecessor_type; + typedef typename TraitsType::TtoK type_to_key_func_type; + typedef typename TraitsType::KHash hash_compare_type; + typedef hash_buffer< key_type, input_type, type_to_key_func_type, hash_compare_type > buffer_type; #if TBB_PREVIEW_FLOW_GRAPH_FEATURES - typedef std::vector predecessor_vector_type; + typedef typename receiver::built_predecessors_type built_predecessors_type; + typedef typename receiver::predecessor_list_type predecessor_list_type; #endif private: // ----------- Aggregator ------------ private: - enum op_type { try__put, get__item, res_port, - add_blt_pred, del_blt_pred, blt_pred_cnt, blt_pred_cpy + enum op_type { try__put, get__item, res_port +#if TBB_PREVIEW_FLOW_GRAPH_FEATURES + , add_blt_pred, del_blt_pred, blt_pred_cnt, blt_pred_cpy +#endif }; enum op_stat {WAIT=0, SUCCEEDED, FAILED}; - typedef tag_matching_port my_class; - class tag_matching_port_operation : public aggregated_operation { + class key_matching_port_operation : public aggregated_operation { public: char type; - T my_val; - T *my_arg; + input_type my_val; + input_type *my_arg; #if TBB_PREVIEW_FLOW_GRAPH_FEATURES predecessor_type *pred; size_t cnt_val; - predecessor_vector_type *pvec; + predecessor_list_type *plist; #endif - tag_value my_tag_value; // constructor for value parameter - tag_matching_port_operation(const T& e, op_type t) : + key_matching_port_operation(const input_type& e, op_type t) : type(char(t)), my_val(e) {} // constructor for pointer parameter - tag_matching_port_operation(const T* p, op_type t) : - type(char(t)), my_arg(const_cast(p)) {} + key_matching_port_operation(const input_type* p, op_type t) : + type(char(t)), my_arg(const_cast(p)) {} // constructor with no parameter - tag_matching_port_operation(op_type t) : type(char(t)) {} + key_matching_port_operation(op_type t) : type(char(t)) {} }; - typedef internal::aggregating_functor my_handler; - friend class internal::aggregating_functor; - aggregator my_aggregator; + typedef internal::aggregating_functor handler_type; + friend class internal::aggregating_functor; + aggregator my_aggregator; - void handle_operations(tag_matching_port_operation* op_list) { - tag_matching_port_operation *current; + void handle_operations(key_matching_port_operation* op_list) { + key_matching_port_operation *current; while(op_list) { current = op_list; op_list = op_list->next; switch(current->type) { case try__put: { - bool was_inserted = this->tagged_insert(current->my_tag_value, current->my_val); + bool was_inserted = this->insert_with_key(current->my_val); // return failure if a duplicate insertion occurs __TBB_store_with_release(current->status, was_inserted ? SUCCEEDED : FAILED); } break; case get__item: - // use current_tag from FE for item - if(!this->tagged_find(my_join->current_tag, *(current->my_arg))) { - __TBB_ASSERT(false, "Failed to find item corresponding to current_tag."); + // use current_key from FE for item + if(!this->find_with_key(my_join->current_key, *(current->my_arg))) { + __TBB_ASSERT(false, "Failed to find item corresponding to current_key."); } __TBB_store_with_release(current->status, SUCCEEDED); break; case res_port: - // use current_tag from FE for item - this->tagged_delete(my_join->current_tag); + // use current_key from FE for item + this->delete_with_key(my_join->current_key); __TBB_store_with_release(current->status, SUCCEEDED); break; #if TBB_PREVIEW_FLOW_GRAPH_FEATURES @@ -682,7 +735,7 @@ namespace internal { __TBB_store_with_release(current->status, SUCCEEDED); break; case blt_pred_cpy: - my_built_predecessors.copy_edges(*(current->pvec)); + my_built_predecessors.copy_edges(*(current->plist)); __TBB_store_with_release(current->status, SUCCEEDED); break; #endif @@ -694,13 +747,12 @@ namespace internal { template< typename R, typename B > friend class run_and_put_task; template friend class internal::broadcast_cache; template friend class internal::round_robin_cache; - /*override*/task *try_put_task(const T& v) { - tag_matching_port_operation op_data(v, try__put); - op_data.my_tag_value = (*my_tag_func)(v); + /*override*/task *try_put_task(const input_type& v) { + key_matching_port_operation op_data(v, try__put); task *rtask = NULL; my_aggregator.execute(&op_data); if(op_data.status == SUCCEEDED) { - rtask = my_join->increment_tag_count(op_data.my_tag_value, false); // may spawn + rtask = my_join->increment_key_count((*(this->get_key_func()))(v), false); // may spawn // rtask has to reflect the return status of the try_put if(!rtask) rtask = SUCCESSFULLY_ENQUEUED; } @@ -709,67 +761,58 @@ namespace internal { public: - tag_matching_port() : receiver(), tagged_buffer() { + key_matching_port() : receiver(), buffer_type() { my_join = NULL; - my_tag_func = NULL; - my_original_tag_func = NULL; - my_aggregator.initialize_handler(my_handler(this)); + my_aggregator.initialize_handler(handler_type(this)); } // copy constructor - tag_matching_port(const tag_matching_port& /*other*/) : receiver(), tagged_buffer() { + key_matching_port(const key_matching_port& /*other*/) : receiver(), buffer_type() { my_join = NULL; - // setting the tag methods is done in the copy-constructor for the front-end. - my_tag_func = NULL; - my_original_tag_func = NULL; - my_aggregator.initialize_handler(my_handler(this)); + my_aggregator.initialize_handler(handler_type(this)); } - ~tag_matching_port() { - if (my_tag_func) delete my_tag_func; - if (my_original_tag_func) delete my_original_tag_func; - } + ~key_matching_port() { } void set_join_node_pointer(forwarding_base *join) { - my_join = join; + my_join = dynamic_cast*>(join); } - void set_my_original_tag_func(my_tag_func_type *f) { - my_original_tag_func = f; - } + void set_my_key_func(type_to_key_func_type *f) { this->set_key_func(f); } - void set_my_tag_func(my_tag_func_type *f) { - my_tag_func = f; - } + type_to_key_func_type* get_my_key_func() { return this->get_key_func(); } - bool get_item( T &v ) { - tag_matching_port_operation op_data(&v, get__item); + bool get_item( input_type &v ) { + // aggregator uses current_key from FE for Key + key_matching_port_operation op_data(&v, get__item); my_aggregator.execute(&op_data); return op_data.status == SUCCEEDED; } #if TBB_PREVIEW_FLOW_GRAPH_FEATURES - /*override*/void internal_add_built_predecessor(sender &p) { - tag_matching_port_operation op_data(add_blt_pred); + /*override*/built_predecessors_type &built_predecessors() { return my_built_predecessors; } + + /*override*/void internal_add_built_predecessor(sender &p) { + key_matching_port_operation op_data(add_blt_pred); op_data.pred = &p; my_aggregator.execute(&op_data); } - /*override*/void internal_delete_built_predecessor(sender &p) { - tag_matching_port_operation op_data(del_blt_pred); + /*override*/void internal_delete_built_predecessor(sender &p) { + key_matching_port_operation op_data(del_blt_pred); op_data.pred = &p; my_aggregator.execute(&op_data); } /*override*/size_t predecessor_count() { - tag_matching_port_operation op_data(blt_pred_cnt); + key_matching_port_operation op_data(blt_pred_cnt); my_aggregator.execute(&op_data); return op_data.cnt_val; } - /*override*/void copy_predecessors(predecessor_vector_type &v) { - tag_matching_port_operation op_data(blt_pred_cpy); - op_data.pvec = &v; + /*override*/void copy_predecessors(predecessor_list_type &l) { + key_matching_port_operation op_data(blt_pred_cpy); + op_data.plist = &l; my_aggregator.execute(&op_data); } #endif @@ -777,41 +820,42 @@ namespace internal { // reset_port is called when item is accepted by successor, but // is initiated by join_node. void reset_port() { - tag_matching_port_operation op_data(res_port); + key_matching_port_operation op_data(res_port); my_aggregator.execute(&op_data); return; } - my_tag_func_type *my_func() { return my_tag_func; } - my_tag_func_type *my_original_func() { return my_original_tag_func; } - #if TBB_PREVIEW_FLOW_GRAPH_FEATURES - /*override*/void reset_receiver(__TBB_PFG_RESET_ARG(reset_flags f)) { - my_buffer_type::reset(); - if (f & rf_extract) - my_built_predecessors.receiver_extract(*this); + void extract_receiver() { + buffer_type::reset(); + my_built_predecessors.receiver_extract(*this); } -#else - /*override*/void reset_receiver(__TBB_PFG_RESET_ARG(reset_flags /*f*/)) { my_buffer_type::reset(); } #endif + /*override*/void reset_receiver(reset_flags f ) { + tbb::internal::suppress_unused_warning(f); + buffer_type::reset(); +#if TBB_PREVIEW_FLOW_GRAPH_FEATURES + if (f & rf_clear_edges) + my_built_predecessors.clear(); +#endif + } private: - // need map of tags to values - forwarding_base *my_join; + // my_join forwarding base used to count number of inputs that + // received key. + matching_forwarding_base *my_join; #if TBB_PREVIEW_FLOW_GRAPH_FEATURES edge_container my_built_predecessors; #endif - my_tag_func_type *my_tag_func; - my_tag_func_type *my_original_tag_func; - }; // tag_matching_port + }; // key_matching_port using namespace graph_policy_namespace; - template + template class join_node_base; //! join_node_FE : implements input port policy - template + template class join_node_FE; template @@ -820,19 +864,19 @@ namespace internal { static const int N = tbb::flow::tuple_size::value; typedef OutputTuple output_type; typedef InputTuple input_type; - typedef join_node_base my_node_type; // for forwarding + typedef join_node_base base_node_type; // for forwarding join_node_FE(graph &g) : forwarding_base(g), my_node(NULL) { ports_with_no_inputs = N; join_helper::set_join_node_pointer(my_inputs, this); } - join_node_FE(const join_node_FE& other) : forwarding_base(*(other.forwarding_base::my_graph_ptr)), my_node(NULL) { + join_node_FE(const join_node_FE& other) : forwarding_base(*(other.forwarding_base::graph_pointer)), my_node(NULL) { ports_with_no_inputs = N; join_helper::set_join_node_pointer(my_inputs, this); } - void set_my_node(my_node_type *new_my_node) { my_node = new_my_node; } + void set_my_node(base_node_type *new_my_node) { my_node = new_my_node; } void increment_port_count() { ++ports_with_no_inputs; @@ -841,10 +885,9 @@ namespace internal { // if all input_ports have predecessors, spawn forward to try and consume tuples task * decrement_port_count(bool handle_task) { if(ports_with_no_inputs.fetch_and_decrement() == 1) { - task* tp = this->my_graph_ptr->root_task(); - if(tp) { - task *rtask = new ( task::allocate_additional_child_of( *tp ) ) - forward_task_bypass(*my_node); + if(this->graph_pointer->is_active()) { + task *rtask = new ( task::allocate_additional_child_of( *(this->graph_pointer->root_task()) ) ) + forward_task_bypass(*my_node); if(!handle_task) return rtask; FLOW_SPAWN(*rtask); } @@ -856,12 +899,20 @@ namespace internal { protected: - void reset( __TBB_PFG_RESET_ARG( reset_flags f)) { + void reset( reset_flags f) { // called outside of parallel contexts ports_with_no_inputs = N; - join_helper::reset_inputs(my_inputs __TBB_PFG_RESET_ARG( __TBB_COMMA f)); + join_helper::reset_inputs(my_inputs, f); } +#if TBB_PREVIEW_FLOW_GRAPH_FEATURES + void extract( ) { + // called outside of parallel contexts + ports_with_no_inputs = N; + join_helper::extract_inputs(my_inputs); + } +#endif + // all methods on input ports should be called under mutual exclusion from join_node_base. bool tuple_build_may_succeed() { @@ -881,9 +932,9 @@ namespace internal { } input_type my_inputs; - my_node_type *my_node; + base_node_type *my_node; atomic ports_with_no_inputs; - }; + }; // join_node_FE template class join_node_FE : public forwarding_base { @@ -891,20 +942,20 @@ namespace internal { static const int N = tbb::flow::tuple_size::value; typedef OutputTuple output_type; typedef InputTuple input_type; - typedef join_node_base my_node_type; // for forwarding + typedef join_node_base base_node_type; // for forwarding join_node_FE(graph &g) : forwarding_base(g), my_node(NULL) { ports_with_no_items = N; join_helper::set_join_node_pointer(my_inputs, this); } - join_node_FE(const join_node_FE& other) : forwarding_base(*(other.forwarding_base::my_graph_ptr)), my_node(NULL) { + join_node_FE(const join_node_FE& other) : forwarding_base(*(other.forwarding_base::graph_pointer)), my_node(NULL) { ports_with_no_items = N; join_helper::set_join_node_pointer(my_inputs, this); } // needed for forwarding - void set_my_node(my_node_type *new_my_node) { my_node = new_my_node; } + void set_my_node(base_node_type *new_my_node) { my_node = new_my_node; } void reset_port_count() { ports_with_no_items = N; @@ -914,10 +965,9 @@ namespace internal { task * decrement_port_count(bool handle_task) { if(ports_with_no_items.fetch_and_decrement() == 1) { - task* tp = this->my_graph_ptr->root_task(); - if(tp) { - task *rtask = new ( task::allocate_additional_child_of( *tp ) ) - forward_task_bypass (*my_node); + if(this->graph_pointer->is_active()) { + task *rtask = new ( task::allocate_additional_child_of( *(this->graph_pointer->root_task()) ) ) + forward_task_bypass (*my_node); if(!handle_task) return rtask; FLOW_SPAWN( *rtask); } @@ -931,11 +981,17 @@ namespace internal { protected: - void reset( __TBB_PFG_RESET_ARG( reset_flags f)) { + void reset( reset_flags f) { reset_port_count(); - join_helper::reset_inputs(my_inputs __TBB_PFG_RESET_ARG( __TBB_COMMA f) ); + join_helper::reset_inputs(my_inputs, f ); } +#if TBB_PREVIEW_FLOW_GRAPH_FEATURES + void extract() { + reset_port_count(); + join_helper::extract_inputs(my_inputs); + } +#endif // all methods on input ports should be called under mutual exclusion from join_node_base. bool tuple_build_may_succeed() { @@ -956,22 +1012,43 @@ namespace internal { } input_type my_inputs; - my_node_type *my_node; + base_node_type *my_node; atomic ports_with_no_items; - }; - - // tag_matching join input port. - template - class join_node_FE : public forwarding_base, - // buffer of tag value counts buffer of output items - public tagged_buffer, public item_buffer { + }; // join_node_FE + + // key_matching join front-end. + template + class join_node_FE, InputTuple, OutputTuple> : public matching_forwarding_base, + // buffer of key value counts + public hash_buffer< // typedefed below to key_to_count_buffer_type + typename tbb::internal::strip::type&, // force ref type on K + count_element::type>, + internal::type_to_key_function_body< + count_element::type>, + typename tbb::internal::strip::type& >, + KHash >, + // buffer of output items + public item_buffer { public: static const int N = tbb::flow::tuple_size::value; typedef OutputTuple output_type; typedef InputTuple input_type; - typedef tagged_buffer my_tag_buffer; + typedef K key_type; + typedef typename tbb::internal::strip::type unref_key_type; + typedef KHash key_hash_compare; + // must use K without ref. + typedef count_element count_element_type; + // method that lets us refer to the key of this type. + typedef key_to_count_functor key_to_count_func; + typedef internal::type_to_key_function_body< count_element_type, unref_key_type&> TtoK_function_body_type; + typedef internal::type_to_key_function_body_leaf TtoK_function_body_leaf_type; + // this is the type of the special table that keeps track of the number of discrete + // elements corresponding to each key that we've seen. + typedef hash_buffer< unref_key_type&, count_element_type, TtoK_function_body_type, key_hash_compare > + key_to_count_buffer_type; typedef item_buffer output_buffer_type; - typedef join_node_base my_node_type; // for forwarding + typedef join_node_base, InputTuple, OutputTuple> base_node_type; // for forwarding + typedef matching_forwarding_base forwarding_base_type; // ----------- Aggregator ------------ // the aggregator is only needed to serialize the access to the hash table. @@ -979,46 +1056,42 @@ namespace internal { private: enum op_type { res_count, inc_count, may_succeed, try_make }; enum op_stat {WAIT=0, SUCCEEDED, FAILED}; - typedef join_node_FE my_class; + typedef join_node_FE, InputTuple, OutputTuple> class_type; - class tag_matching_FE_operation : public aggregated_operation { + class key_matching_FE_operation : public aggregated_operation { public: char type; - union { - tag_value my_val; - output_type* my_output; - }; + unref_key_type my_val; + output_type* my_output; task *bypass_t; bool enqueue_task; // constructor for value parameter - tag_matching_FE_operation(const tag_value& e , bool q_task , op_type t) : type(char(t)), my_val(e), - bypass_t(NULL), enqueue_task(q_task) {} - tag_matching_FE_operation(output_type *p, op_type t) : type(char(t)), my_output(p), bypass_t(NULL), + key_matching_FE_operation(const unref_key_type& e , bool q_task , op_type t) : type(char(t)), my_val(e), + my_output(NULL), bypass_t(NULL), enqueue_task(q_task) {} + key_matching_FE_operation(output_type *p, op_type t) : type(char(t)), my_output(p), bypass_t(NULL), enqueue_task(true) {} // constructor with no parameter - tag_matching_FE_operation(op_type t) : type(char(t)), bypass_t(NULL), enqueue_task(true) {} + key_matching_FE_operation(op_type t) : type(char(t)), my_output(NULL), bypass_t(NULL), enqueue_task(true) {} }; - typedef internal::aggregating_functor my_handler; - friend class internal::aggregating_functor; - aggregator my_aggregator; + typedef internal::aggregating_functor handler_type; + friend class internal::aggregating_functor; + aggregator my_aggregator; // called from aggregator, so serialized - // construct as many output objects as possible. // returns a task pointer if the a task would have been enqueued but we asked that // it be returned. Otherwise returns NULL. - task * fill_output_buffer(tag_value t, bool should_enqueue, bool handle_task) { + task * fill_output_buffer(unref_key_type &t, bool should_enqueue, bool handle_task) { output_type l_out; task *rtask = NULL; - task* tp = this->my_graph_ptr->root_task(); - bool do_fwd = should_enqueue && this->buffer_empty() && tp; - this->current_tag = t; - this->tagged_delete(this->current_tag); // remove the tag + bool do_fwd = should_enqueue && this->buffer_empty() && this->graph_pointer->is_active(); + this->current_key = t; + this->delete_with_key(this->current_key); // remove the key if(join_helper::get_items(my_inputs, l_out)) { // <== call back this->push_back(l_out); if(do_fwd) { // we enqueue if receiving an item from predecessor, not if successor asks for item - rtask = new ( task::allocate_additional_child_of( *tp ) ) - forward_task_bypass(*my_node); + rtask = new ( task::allocate_additional_child_of( *(this->graph_pointer->root_task()) ) ) + forward_task_bypass(*my_node); if(handle_task) { FLOW_SPAWN(*rtask); rtask = NULL; @@ -1027,7 +1100,6 @@ namespace internal { } // retire the input values join_helper::reset_ports(my_inputs); // <== call back - this->current_tag = NO_TAG; } else { __TBB_ASSERT(false, "should have had something to push"); @@ -1035,8 +1107,8 @@ namespace internal { return rtask; } - void handle_operations(tag_matching_FE_operation* op_list) { - tag_matching_FE_operation *current; + void handle_operations(key_matching_FE_operation* op_list) { + key_matching_FE_operation *current; while(op_list) { current = op_list; op_list = op_list->next; @@ -1048,16 +1120,19 @@ namespace internal { } break; case inc_count: { // called from input ports - size_t *p = 0; - tag_value t = current->my_val; + count_element_type *p = 0; + unref_key_type &t = current->my_val; bool do_enqueue = current->enqueue_task; - if(!(this->tagged_find_ref(t,p))) { - this->tagged_insert(t, 0); - if(!(this->tagged_find_ref(t,p))) { - __TBB_ASSERT(false, "should find tag after inserting it"); + if(!(this->find_ref_with_key(t,p))) { + count_element_type ev; + ev.my_key = t; + ev.my_value = 0; + this->insert_with_key(ev); + if(!(this->find_ref_with_key(t,p))) { + __TBB_ASSERT(false, "should find key after inserting it"); } } - if(++(*p) == size_t(N)) { + if(++(p->my_value) == size_t(N)) { task *rtask = fill_output_buffer(t, true, do_enqueue); __TBB_ASSERT(!rtask || !do_enqueue, "task should not be returned"); current->bypass_t = rtask; @@ -1084,33 +1159,37 @@ namespace internal { public: template - join_node_FE(graph &g, FunctionTuple tag_funcs) : forwarding_base(g), my_node(NULL) { + join_node_FE(graph &g, FunctionTuple &TtoK_funcs) : forwarding_base_type(g), my_node(NULL) { join_helper::set_join_node_pointer(my_inputs, this); - join_helper::set_tag_func(my_inputs, tag_funcs); - my_aggregator.initialize_handler(my_handler(this)); + join_helper::set_key_functors(my_inputs, TtoK_funcs); + my_aggregator.initialize_handler(handler_type(this)); + TtoK_function_body_type *cfb = new TtoK_function_body_leaf_type(key_to_count_func()); + this->set_key_func(cfb); } - join_node_FE(const join_node_FE& other) : forwarding_base(*(other.forwarding_base::my_graph_ptr)), my_tag_buffer(), + join_node_FE(const join_node_FE& other) : forwarding_base_type(*(other.forwarding_base_type::graph_pointer)), key_to_count_buffer_type(), output_buffer_type() { my_node = NULL; join_helper::set_join_node_pointer(my_inputs, this); - join_helper::copy_tag_functors(my_inputs, const_cast(other.my_inputs)); - my_aggregator.initialize_handler(my_handler(this)); + join_helper::copy_key_functors(my_inputs, const_cast(other.my_inputs)); + my_aggregator.initialize_handler(handler_type(this)); + TtoK_function_body_type *cfb = new TtoK_function_body_leaf_type(key_to_count_func()); + this->set_key_func(cfb); } // needed for forwarding - void set_my_node(my_node_type *new_my_node) { my_node = new_my_node; } + void set_my_node(base_node_type *new_my_node) { my_node = new_my_node; } void reset_port_count() { // called from BE - tag_matching_FE_operation op_data(res_count); + key_matching_FE_operation op_data(res_count); my_aggregator.execute(&op_data); return; } // if all input_ports have items, spawn forward to try and consume tuples // return a task if we are asked and did create one. - task *increment_tag_count(tag_value t, bool handle_task) { // called from input_ports - tag_matching_FE_operation op_data(t, handle_task, inc_count); + /*override*/ task *increment_key_count(unref_key_type const & t, bool handle_task) { // called from input_ports + key_matching_FE_operation op_data(t, handle_task, inc_count); my_aggregator.execute(&op_data); return op_data.bypass_t; } @@ -1123,33 +1202,41 @@ namespace internal { protected: - void reset( __TBB_PFG_RESET_ARG( reset_flags f )) { + void reset( reset_flags f ) { // called outside of parallel contexts - join_helper::reset_inputs(my_inputs __TBB_PFG_RESET_ARG( __TBB_COMMA f)); + join_helper::reset_inputs(my_inputs, f); - my_tag_buffer::reset(); // have to reset the tag counts - output_buffer_type::reset(); // also the queue of outputs - my_node->current_tag = NO_TAG; + key_to_count_buffer_type::reset(); + output_buffer_type::reset(); } +#if TBB_PREVIEW_FLOW_GRAPH_FEATURES + void extract() { + // called outside of parallel contexts + join_helper::extract_inputs(my_inputs); + key_to_count_buffer_type::reset(); // have to reset the tag counts + output_buffer_type::reset(); // also the queue of outputs + // my_node->current_tag = NO_TAG; + } +#endif // all methods on input ports should be called under mutual exclusion from join_node_base. bool tuple_build_may_succeed() { // called from back-end - tag_matching_FE_operation op_data(may_succeed); + key_matching_FE_operation op_data(may_succeed); my_aggregator.execute(&op_data); return op_data.status == SUCCEEDED; } - // cannot lock while calling back to input_ports. current_tag will only be set + // cannot lock while calling back to input_ports. current_key will only be set // and reset under the aggregator, so it will remain consistent. bool try_to_make_tuple(output_type &out) { - tag_matching_FE_operation op_data(&out,try_make); + key_matching_FE_operation op_data(&out,try_make); my_aggregator.execute(&op_data); return op_data.status == SUCCEEDED; } void tuple_accepted() { - reset_port_count(); // reset current_tag after ports reset. + reset_port_count(); // reset current_key after ports reset. } void tuple_rejected() { @@ -1157,11 +1244,11 @@ namespace internal { } input_type my_inputs; // input ports - my_node_type *my_node; - }; // join_node_FE + base_node_type *my_node; + }; // join_node_FE, InputTuple, OutputTuple> //! join_node_base - template + template class join_node_base : public graph_node, public join_node_FE, public sender { protected: @@ -1176,7 +1263,8 @@ namespace internal { using input_ports_type::tuple_accepted; using input_ports_type::tuple_rejected; #if TBB_PREVIEW_FLOW_GRAPH_FEATURES - typedef std::vector successor_vector_type; + typedef typename sender::built_successors_type built_successors_type; + typedef typename sender::successor_list_type successor_list_type; #endif private: @@ -1187,7 +1275,7 @@ namespace internal { #endif }; enum op_stat {WAIT=0, SUCCEEDED, FAILED}; - typedef join_node_base my_class; + typedef join_node_base class_type; class join_node_base_operation : public aggregated_operation { public: @@ -1197,7 +1285,7 @@ namespace internal { successor_type *my_succ; #if TBB_PREVIEW_FLOW_GRAPH_FEATURES size_t cnt_val; - successor_vector_type *svec; + successor_list_type *slist; #endif }; task *bypass_t; @@ -1208,10 +1296,10 @@ namespace internal { join_node_base_operation(op_type t) : type(char(t)), bypass_t(NULL) {} }; - typedef internal::aggregating_functor my_handler; - friend class internal::aggregating_functor; + typedef internal::aggregating_functor handler_type; + friend class internal::aggregating_functor; bool forwarder_busy; - aggregator my_aggregator; + aggregator my_aggregator; void handle_operations(join_node_base_operation* op_list) { join_node_base_operation *current; @@ -1221,9 +1309,8 @@ namespace internal { switch(current->type) { case reg_succ: { my_successors.register_successor(*(current->my_succ)); - task* tp = this->graph_node::my_graph.root_task(); - if(tuple_build_may_succeed() && !forwarder_busy && tp) { - task *rtask = new ( task::allocate_additional_child_of(*tp) ) + if(tuple_build_may_succeed() && !forwarder_busy && this->graph_node::my_graph.is_active()) { + task *rtask = new ( task::allocate_additional_child_of(*(this->graph_node::my_graph.root_task())) ) forward_task_bypass >(*this); FLOW_SPAWN(*rtask); @@ -1250,9 +1337,9 @@ namespace internal { bool build_succeeded; task *last_task = NULL; output_type out; - if(tuple_build_may_succeed()) { + if(tuple_build_may_succeed()) { // checks output queue of FE do { - build_succeeded = try_to_make_tuple(out); + build_succeeded = try_to_make_tuple(out); // fetch front_end of queue if(build_succeeded) { task *new_task = my_successors.try_put_task(out); last_task = combine_tasks(last_task, new_task); @@ -1285,7 +1372,7 @@ namespace internal { __TBB_store_with_release(current->status, SUCCEEDED); break; case blt_succ_cpy: - my_successors.copy_successors(*(current->svec)); + my_successors.copy_successors(*(current->slist)); __TBB_store_with_release(current->status, SUCCEEDED); break; #endif /* TBB_PREVIEW_FLOW_GRAPH_FEATURES */ @@ -1297,7 +1384,7 @@ namespace internal { join_node_base(graph &g) : graph_node(g), input_ports_type(g), forwarder_busy(false) { my_successors.set_owner(this); input_ports_type::set_my_node(this); - my_aggregator.initialize_handler(my_handler(this)); + my_aggregator.initialize_handler(handler_type(this)); } join_node_base(const join_node_base& other) : @@ -1305,14 +1392,14 @@ namespace internal { sender(), forwarder_busy(false), my_successors() { my_successors.set_owner(this); input_ports_type::set_my_node(this); - my_aggregator.initialize_handler(my_handler(this)); + my_aggregator.initialize_handler(handler_type(this)); } template join_node_base(graph &g, FunctionTuple f) : graph_node(g), input_ports_type(g, f), forwarder_busy(false) { my_successors.set_owner(this); input_ports_type::set_my_node(this); - my_aggregator.initialize_handler(my_handler(this)); + my_aggregator.initialize_handler(handler_type(this)); } bool register_successor(successor_type &r) { @@ -1334,6 +1421,8 @@ namespace internal { } #if TBB_PREVIEW_FLOW_GRAPH_FEATURES + /*override*/built_successors_type &built_successors() { return my_successors.built_successors(); } + /*override*/void internal_add_built_successor( successor_type &r) { join_node_base_operation op_data(r, add_blt_succ); my_aggregator.execute(&op_data); @@ -1350,20 +1439,25 @@ namespace internal { return op_data.cnt_val; } - /*override*/ void copy_successors(successor_vector_type &v) { + /*override*/ void copy_successors(successor_list_type &l) { join_node_base_operation op_data(blt_succ_cpy); - op_data.svec = &v; + op_data.slist = &l; my_aggregator.execute(&op_data); } #endif /* TBB_PREVIEW_FLOW_GRAPH_FEATURES */ - protected: - - /*override*/void reset(__TBB_PFG_RESET_ARG(reset_flags f)) { - input_ports_type::reset(__TBB_PFG_RESET_ARG(f)); #if TBB_PREVIEW_FLOW_GRAPH_FEATURES - my_successors.reset(f); + /*override*/void extract() { + input_ports_type::extract(); + my_successors.built_successors().sender_extract(*this); + } #endif + + protected: + + /*override*/void reset_node(reset_flags f) { + input_ports_type::reset(f); + if(f & rf_clear_edges) my_successors.clear(); } private: @@ -1376,19 +1470,30 @@ namespace internal { return op_data.bypass_t; } - }; + }; // join_node_base // join base class type generator - template class PT, typename OutputTuple, graph_buffer_policy JP> + template class PT, typename OutputTuple, typename JP> struct join_base { typedef typename internal::join_node_base::type, OutputTuple> type; }; + template + struct join_base > { + typedef key_matching key_traits_type; + typedef K key_type; + typedef KHash key_hash_compare; + typedef typename internal::join_node_base< key_traits_type, + // ports type + typename wrap_key_tuple_elements::type, + OutputTuple > type; + }; + //! unfolded_join_node : passes input_ports_type to join_node_base. We build the input port type - // using tuple_element. The class PT is the port type (reserving_port, queueing_port, tag_matching_port) - // and should match the graph_buffer_policy. + // using tuple_element. The class PT is the port type (reserving_port, queueing_port, key_matching_port) + // and should match the typename. - template class PT, typename OutputTuple, graph_buffer_policy JP> + template class PT, typename OutputTuple, typename JP> class unfolded_join_node : public join_base::type { public: typedef typename wrap_tuple_elements::type input_ports_type; @@ -1400,123 +1505,131 @@ namespace internal { unfolded_join_node(const unfolded_join_node &other) : base_type(other) {} }; - // tag_matching unfolded_join_node. This must be a separate specialization because the constructors + // key_matching unfolded_join_node. This must be a separate specialization because the constructors // differ. - template - class unfolded_join_node<2,tag_matching_port,OutputTuple,tag_matching> : public - join_base<2,tag_matching_port,OutputTuple,tag_matching>::type { + template + class unfolded_join_node<2,key_matching_port,OutputTuple,key_matching > : public + join_base<2,key_matching_port,OutputTuple,key_matching >::type { typedef typename tbb::flow::tuple_element<0, OutputTuple>::type T0; typedef typename tbb::flow::tuple_element<1, OutputTuple>::type T1; public: - typedef typename wrap_tuple_elements<2,tag_matching_port,OutputTuple>::type input_ports_type; + typedef typename wrap_key_tuple_elements<2,key_matching_port,key_matching,OutputTuple>::type input_ports_type; typedef OutputTuple output_type; private: - typedef join_node_base base_type; - typedef typename internal::function_body *f0_p; - typedef typename internal::function_body *f1_p; + typedef join_node_base, input_ports_type, output_type > base_type; + typedef typename internal::type_to_key_function_body *f0_p; + typedef typename internal::type_to_key_function_body *f1_p; typedef typename tbb::flow::tuple< f0_p, f1_p > func_initializer_type; public: template unfolded_join_node(graph &g, Body0 body0, Body1 body1) : base_type(g, func_initializer_type( - new internal::function_body_leaf(body0), - new internal::function_body_leaf(body1) - ) ) {} + new internal::type_to_key_function_body_leaf(body0), + new internal::type_to_key_function_body_leaf(body1) + ) ) { + __TBB_STATIC_ASSERT(tbb::flow::tuple_size::value == 2, "wrong number of body initializers"); + } unfolded_join_node(const unfolded_join_node &other) : base_type(other) {} }; - template - class unfolded_join_node<3,tag_matching_port,OutputTuple,tag_matching> : public - join_base<3,tag_matching_port,OutputTuple,tag_matching>::type { + template + class unfolded_join_node<3,key_matching_port,OutputTuple,key_matching > : public + join_base<3,key_matching_port,OutputTuple,key_matching >::type { typedef typename tbb::flow::tuple_element<0, OutputTuple>::type T0; typedef typename tbb::flow::tuple_element<1, OutputTuple>::type T1; typedef typename tbb::flow::tuple_element<2, OutputTuple>::type T2; public: - typedef typename wrap_tuple_elements<3, tag_matching_port, OutputTuple>::type input_ports_type; + typedef typename wrap_key_tuple_elements<3,key_matching_port,key_matching,OutputTuple>::type input_ports_type; typedef OutputTuple output_type; private: - typedef join_node_base base_type; - typedef typename internal::function_body *f0_p; - typedef typename internal::function_body *f1_p; - typedef typename internal::function_body *f2_p; + typedef join_node_base, input_ports_type, output_type > base_type; + typedef typename internal::type_to_key_function_body *f0_p; + typedef typename internal::type_to_key_function_body *f1_p; + typedef typename internal::type_to_key_function_body *f2_p; typedef typename tbb::flow::tuple< f0_p, f1_p, f2_p > func_initializer_type; public: template unfolded_join_node(graph &g, Body0 body0, Body1 body1, Body2 body2) : base_type(g, func_initializer_type( - new internal::function_body_leaf(body0), - new internal::function_body_leaf(body1), - new internal::function_body_leaf(body2) - ) ) {} + new internal::type_to_key_function_body_leaf(body0), + new internal::type_to_key_function_body_leaf(body1), + new internal::type_to_key_function_body_leaf(body2) + ) ) { + __TBB_STATIC_ASSERT(tbb::flow::tuple_size::value == 3, "wrong number of body initializers"); + } unfolded_join_node(const unfolded_join_node &other) : base_type(other) {} }; - template - class unfolded_join_node<4,tag_matching_port,OutputTuple,tag_matching> : public - join_base<4,tag_matching_port,OutputTuple,tag_matching>::type { + template + class unfolded_join_node<4,key_matching_port,OutputTuple,key_matching > : public + join_base<4,key_matching_port,OutputTuple,key_matching >::type { typedef typename tbb::flow::tuple_element<0, OutputTuple>::type T0; typedef typename tbb::flow::tuple_element<1, OutputTuple>::type T1; typedef typename tbb::flow::tuple_element<2, OutputTuple>::type T2; typedef typename tbb::flow::tuple_element<3, OutputTuple>::type T3; public: - typedef typename wrap_tuple_elements<4, tag_matching_port, OutputTuple>::type input_ports_type; + typedef typename wrap_key_tuple_elements<4,key_matching_port,key_matching,OutputTuple>::type input_ports_type; typedef OutputTuple output_type; private: - typedef join_node_base base_type; - typedef typename internal::function_body *f0_p; - typedef typename internal::function_body *f1_p; - typedef typename internal::function_body *f2_p; - typedef typename internal::function_body *f3_p; + typedef join_node_base, input_ports_type, output_type > base_type; + typedef typename internal::type_to_key_function_body *f0_p; + typedef typename internal::type_to_key_function_body *f1_p; + typedef typename internal::type_to_key_function_body *f2_p; + typedef typename internal::type_to_key_function_body *f3_p; typedef typename tbb::flow::tuple< f0_p, f1_p, f2_p, f3_p > func_initializer_type; public: template unfolded_join_node(graph &g, Body0 body0, Body1 body1, Body2 body2, Body3 body3) : base_type(g, func_initializer_type( - new internal::function_body_leaf(body0), - new internal::function_body_leaf(body1), - new internal::function_body_leaf(body2), - new internal::function_body_leaf(body3) - ) ) {} + new internal::type_to_key_function_body_leaf(body0), + new internal::type_to_key_function_body_leaf(body1), + new internal::type_to_key_function_body_leaf(body2), + new internal::type_to_key_function_body_leaf(body3) + ) ) { + __TBB_STATIC_ASSERT(tbb::flow::tuple_size::value == 4, "wrong number of body initializers"); + } unfolded_join_node(const unfolded_join_node &other) : base_type(other) {} }; - template - class unfolded_join_node<5,tag_matching_port,OutputTuple,tag_matching> : public - join_base<5,tag_matching_port,OutputTuple,tag_matching>::type { + template + class unfolded_join_node<5,key_matching_port,OutputTuple,key_matching > : public + join_base<5,key_matching_port,OutputTuple,key_matching >::type { typedef typename tbb::flow::tuple_element<0, OutputTuple>::type T0; typedef typename tbb::flow::tuple_element<1, OutputTuple>::type T1; typedef typename tbb::flow::tuple_element<2, OutputTuple>::type T2; typedef typename tbb::flow::tuple_element<3, OutputTuple>::type T3; typedef typename tbb::flow::tuple_element<4, OutputTuple>::type T4; public: - typedef typename wrap_tuple_elements<5, tag_matching_port, OutputTuple>::type input_ports_type; + typedef typename wrap_key_tuple_elements<5,key_matching_port,key_matching,OutputTuple>::type input_ports_type; typedef OutputTuple output_type; private: - typedef join_node_base base_type; - typedef typename internal::function_body *f0_p; - typedef typename internal::function_body *f1_p; - typedef typename internal::function_body *f2_p; - typedef typename internal::function_body *f3_p; - typedef typename internal::function_body *f4_p; + typedef join_node_base , input_ports_type, output_type > base_type; + typedef typename internal::type_to_key_function_body *f0_p; + typedef typename internal::type_to_key_function_body *f1_p; + typedef typename internal::type_to_key_function_body *f2_p; + typedef typename internal::type_to_key_function_body *f3_p; + typedef typename internal::type_to_key_function_body *f4_p; typedef typename tbb::flow::tuple< f0_p, f1_p, f2_p, f3_p, f4_p > func_initializer_type; public: template unfolded_join_node(graph &g, Body0 body0, Body1 body1, Body2 body2, Body3 body3, Body4 body4) : base_type(g, func_initializer_type( - new internal::function_body_leaf(body0), - new internal::function_body_leaf(body1), - new internal::function_body_leaf(body2), - new internal::function_body_leaf(body3), - new internal::function_body_leaf(body4) - ) ) {} + new internal::type_to_key_function_body_leaf(body0), + new internal::type_to_key_function_body_leaf(body1), + new internal::type_to_key_function_body_leaf(body2), + new internal::type_to_key_function_body_leaf(body3), + new internal::type_to_key_function_body_leaf(body4) + ) ) { + __TBB_STATIC_ASSERT(tbb::flow::tuple_size::value == 5, "wrong number of body initializers"); + } unfolded_join_node(const unfolded_join_node &other) : base_type(other) {} }; #if __TBB_VARIADIC_MAX >= 6 - template - class unfolded_join_node<6,tag_matching_port,OutputTuple,tag_matching> : public - join_base<6,tag_matching_port,OutputTuple,tag_matching>::type { + template + class unfolded_join_node<6,key_matching_port,OutputTuple,key_matching > : public + join_base<6,key_matching_port,OutputTuple,key_matching >::type { typedef typename tbb::flow::tuple_element<0, OutputTuple>::type T0; typedef typename tbb::flow::tuple_element<1, OutputTuple>::type T1; typedef typename tbb::flow::tuple_element<2, OutputTuple>::type T2; @@ -1524,36 +1637,38 @@ namespace internal { typedef typename tbb::flow::tuple_element<4, OutputTuple>::type T4; typedef typename tbb::flow::tuple_element<5, OutputTuple>::type T5; public: - typedef typename wrap_tuple_elements<6, tag_matching_port, OutputTuple>::type input_ports_type; + typedef typename wrap_key_tuple_elements<6,key_matching_port,key_matching,OutputTuple>::type input_ports_type; typedef OutputTuple output_type; private: - typedef join_node_base base_type; - typedef typename internal::function_body *f0_p; - typedef typename internal::function_body *f1_p; - typedef typename internal::function_body *f2_p; - typedef typename internal::function_body *f3_p; - typedef typename internal::function_body *f4_p; - typedef typename internal::function_body *f5_p; + typedef join_node_base , input_ports_type, output_type > base_type; + typedef typename internal::type_to_key_function_body *f0_p; + typedef typename internal::type_to_key_function_body *f1_p; + typedef typename internal::type_to_key_function_body *f2_p; + typedef typename internal::type_to_key_function_body *f3_p; + typedef typename internal::type_to_key_function_body *f4_p; + typedef typename internal::type_to_key_function_body *f5_p; typedef typename tbb::flow::tuple< f0_p, f1_p, f2_p, f3_p, f4_p, f5_p > func_initializer_type; public: template unfolded_join_node(graph &g, Body0 body0, Body1 body1, Body2 body2, Body3 body3, Body4 body4, Body5 body5) : base_type(g, func_initializer_type( - new internal::function_body_leaf(body0), - new internal::function_body_leaf(body1), - new internal::function_body_leaf(body2), - new internal::function_body_leaf(body3), - new internal::function_body_leaf(body4), - new internal::function_body_leaf(body5) - ) ) {} + new internal::type_to_key_function_body_leaf(body0), + new internal::type_to_key_function_body_leaf(body1), + new internal::type_to_key_function_body_leaf(body2), + new internal::type_to_key_function_body_leaf(body3), + new internal::type_to_key_function_body_leaf(body4), + new internal::type_to_key_function_body_leaf(body5) + ) ) { + __TBB_STATIC_ASSERT(tbb::flow::tuple_size::value == 6, "wrong number of body initializers"); + } unfolded_join_node(const unfolded_join_node &other) : base_type(other) {} }; #endif #if __TBB_VARIADIC_MAX >= 7 - template - class unfolded_join_node<7,tag_matching_port,OutputTuple,tag_matching> : public - join_base<7,tag_matching_port,OutputTuple,tag_matching>::type { + template + class unfolded_join_node<7,key_matching_port,OutputTuple,key_matching > : public + join_base<7,key_matching_port,OutputTuple,key_matching >::type { typedef typename tbb::flow::tuple_element<0, OutputTuple>::type T0; typedef typename tbb::flow::tuple_element<1, OutputTuple>::type T1; typedef typename tbb::flow::tuple_element<2, OutputTuple>::type T2; @@ -1562,39 +1677,41 @@ namespace internal { typedef typename tbb::flow::tuple_element<5, OutputTuple>::type T5; typedef typename tbb::flow::tuple_element<6, OutputTuple>::type T6; public: - typedef typename wrap_tuple_elements<7, tag_matching_port, OutputTuple>::type input_ports_type; + typedef typename wrap_key_tuple_elements<7,key_matching_port,key_matching,OutputTuple>::type input_ports_type; typedef OutputTuple output_type; private: - typedef join_node_base base_type; - typedef typename internal::function_body *f0_p; - typedef typename internal::function_body *f1_p; - typedef typename internal::function_body *f2_p; - typedef typename internal::function_body *f3_p; - typedef typename internal::function_body *f4_p; - typedef typename internal::function_body *f5_p; - typedef typename internal::function_body *f6_p; + typedef join_node_base , input_ports_type, output_type > base_type; + typedef typename internal::type_to_key_function_body *f0_p; + typedef typename internal::type_to_key_function_body *f1_p; + typedef typename internal::type_to_key_function_body *f2_p; + typedef typename internal::type_to_key_function_body *f3_p; + typedef typename internal::type_to_key_function_body *f4_p; + typedef typename internal::type_to_key_function_body *f5_p; + typedef typename internal::type_to_key_function_body *f6_p; typedef typename tbb::flow::tuple< f0_p, f1_p, f2_p, f3_p, f4_p, f5_p, f6_p > func_initializer_type; public: template unfolded_join_node(graph &g, Body0 body0, Body1 body1, Body2 body2, Body3 body3, Body4 body4, Body5 body5, Body6 body6) : base_type(g, func_initializer_type( - new internal::function_body_leaf(body0), - new internal::function_body_leaf(body1), - new internal::function_body_leaf(body2), - new internal::function_body_leaf(body3), - new internal::function_body_leaf(body4), - new internal::function_body_leaf(body5), - new internal::function_body_leaf(body6) - ) ) {} + new internal::type_to_key_function_body_leaf(body0), + new internal::type_to_key_function_body_leaf(body1), + new internal::type_to_key_function_body_leaf(body2), + new internal::type_to_key_function_body_leaf(body3), + new internal::type_to_key_function_body_leaf(body4), + new internal::type_to_key_function_body_leaf(body5), + new internal::type_to_key_function_body_leaf(body6) + ) ) { + __TBB_STATIC_ASSERT(tbb::flow::tuple_size::value == 7, "wrong number of body initializers"); + } unfolded_join_node(const unfolded_join_node &other) : base_type(other) {} }; #endif #if __TBB_VARIADIC_MAX >= 8 - template - class unfolded_join_node<8,tag_matching_port,OutputTuple,tag_matching> : public - join_base<8,tag_matching_port,OutputTuple,tag_matching>::type { + template + class unfolded_join_node<8,key_matching_port,OutputTuple,key_matching > : public + join_base<8,key_matching_port,OutputTuple,key_matching >::type { typedef typename tbb::flow::tuple_element<0, OutputTuple>::type T0; typedef typename tbb::flow::tuple_element<1, OutputTuple>::type T1; typedef typename tbb::flow::tuple_element<2, OutputTuple>::type T2; @@ -1604,41 +1721,43 @@ namespace internal { typedef typename tbb::flow::tuple_element<6, OutputTuple>::type T6; typedef typename tbb::flow::tuple_element<7, OutputTuple>::type T7; public: - typedef typename wrap_tuple_elements<8, tag_matching_port, OutputTuple>::type input_ports_type; + typedef typename wrap_key_tuple_elements<8,key_matching_port,key_matching,OutputTuple>::type input_ports_type; typedef OutputTuple output_type; private: - typedef join_node_base base_type; - typedef typename internal::function_body *f0_p; - typedef typename internal::function_body *f1_p; - typedef typename internal::function_body *f2_p; - typedef typename internal::function_body *f3_p; - typedef typename internal::function_body *f4_p; - typedef typename internal::function_body *f5_p; - typedef typename internal::function_body *f6_p; - typedef typename internal::function_body *f7_p; + typedef join_node_base , input_ports_type, output_type > base_type; + typedef typename internal::type_to_key_function_body *f0_p; + typedef typename internal::type_to_key_function_body *f1_p; + typedef typename internal::type_to_key_function_body *f2_p; + typedef typename internal::type_to_key_function_body *f3_p; + typedef typename internal::type_to_key_function_body *f4_p; + typedef typename internal::type_to_key_function_body *f5_p; + typedef typename internal::type_to_key_function_body *f6_p; + typedef typename internal::type_to_key_function_body *f7_p; typedef typename tbb::flow::tuple< f0_p, f1_p, f2_p, f3_p, f4_p, f5_p, f6_p, f7_p > func_initializer_type; public: template unfolded_join_node(graph &g, Body0 body0, Body1 body1, Body2 body2, Body3 body3, Body4 body4, Body5 body5, Body6 body6, Body7 body7) : base_type(g, func_initializer_type( - new internal::function_body_leaf(body0), - new internal::function_body_leaf(body1), - new internal::function_body_leaf(body2), - new internal::function_body_leaf(body3), - new internal::function_body_leaf(body4), - new internal::function_body_leaf(body5), - new internal::function_body_leaf(body6), - new internal::function_body_leaf(body7) - ) ) {} + new internal::type_to_key_function_body_leaf(body0), + new internal::type_to_key_function_body_leaf(body1), + new internal::type_to_key_function_body_leaf(body2), + new internal::type_to_key_function_body_leaf(body3), + new internal::type_to_key_function_body_leaf(body4), + new internal::type_to_key_function_body_leaf(body5), + new internal::type_to_key_function_body_leaf(body6), + new internal::type_to_key_function_body_leaf(body7) + ) ) { + __TBB_STATIC_ASSERT(tbb::flow::tuple_size::value == 8, "wrong number of body initializers"); + } unfolded_join_node(const unfolded_join_node &other) : base_type(other) {} }; #endif #if __TBB_VARIADIC_MAX >= 9 - template - class unfolded_join_node<9,tag_matching_port,OutputTuple,tag_matching> : public - join_base<9,tag_matching_port,OutputTuple,tag_matching>::type { + template + class unfolded_join_node<9,key_matching_port,OutputTuple,key_matching > : public + join_base<9,key_matching_port,OutputTuple,key_matching >::type { typedef typename tbb::flow::tuple_element<0, OutputTuple>::type T0; typedef typename tbb::flow::tuple_element<1, OutputTuple>::type T1; typedef typename tbb::flow::tuple_element<2, OutputTuple>::type T2; @@ -1649,43 +1768,45 @@ namespace internal { typedef typename tbb::flow::tuple_element<7, OutputTuple>::type T7; typedef typename tbb::flow::tuple_element<8, OutputTuple>::type T8; public: - typedef typename wrap_tuple_elements<9, tag_matching_port, OutputTuple>::type input_ports_type; + typedef typename wrap_key_tuple_elements<9,key_matching_port,key_matching,OutputTuple>::type input_ports_type; typedef OutputTuple output_type; private: - typedef join_node_base base_type; - typedef typename internal::function_body *f0_p; - typedef typename internal::function_body *f1_p; - typedef typename internal::function_body *f2_p; - typedef typename internal::function_body *f3_p; - typedef typename internal::function_body *f4_p; - typedef typename internal::function_body *f5_p; - typedef typename internal::function_body *f6_p; - typedef typename internal::function_body *f7_p; - typedef typename internal::function_body *f8_p; + typedef join_node_base , input_ports_type, output_type > base_type; + typedef typename internal::type_to_key_function_body *f0_p; + typedef typename internal::type_to_key_function_body *f1_p; + typedef typename internal::type_to_key_function_body *f2_p; + typedef typename internal::type_to_key_function_body *f3_p; + typedef typename internal::type_to_key_function_body *f4_p; + typedef typename internal::type_to_key_function_body *f5_p; + typedef typename internal::type_to_key_function_body *f6_p; + typedef typename internal::type_to_key_function_body *f7_p; + typedef typename internal::type_to_key_function_body *f8_p; typedef typename tbb::flow::tuple< f0_p, f1_p, f2_p, f3_p, f4_p, f5_p, f6_p, f7_p, f8_p > func_initializer_type; public: template unfolded_join_node(graph &g, Body0 body0, Body1 body1, Body2 body2, Body3 body3, Body4 body4, Body5 body5, Body6 body6, Body7 body7, Body8 body8) : base_type(g, func_initializer_type( - new internal::function_body_leaf(body0), - new internal::function_body_leaf(body1), - new internal::function_body_leaf(body2), - new internal::function_body_leaf(body3), - new internal::function_body_leaf(body4), - new internal::function_body_leaf(body5), - new internal::function_body_leaf(body6), - new internal::function_body_leaf(body7), - new internal::function_body_leaf(body8) - ) ) {} + new internal::type_to_key_function_body_leaf(body0), + new internal::type_to_key_function_body_leaf(body1), + new internal::type_to_key_function_body_leaf(body2), + new internal::type_to_key_function_body_leaf(body3), + new internal::type_to_key_function_body_leaf(body4), + new internal::type_to_key_function_body_leaf(body5), + new internal::type_to_key_function_body_leaf(body6), + new internal::type_to_key_function_body_leaf(body7), + new internal::type_to_key_function_body_leaf(body8) + ) ) { + __TBB_STATIC_ASSERT(tbb::flow::tuple_size::value == 9, "wrong number of body initializers"); + } unfolded_join_node(const unfolded_join_node &other) : base_type(other) {} }; #endif #if __TBB_VARIADIC_MAX >= 10 - template - class unfolded_join_node<10,tag_matching_port,OutputTuple,tag_matching> : public - join_base<10,tag_matching_port,OutputTuple,tag_matching>::type { + template + class unfolded_join_node<10,key_matching_port,OutputTuple,key_matching > : public + join_base<10,key_matching_port,OutputTuple,key_matching >::type { typedef typename tbb::flow::tuple_element<0, OutputTuple>::type T0; typedef typename tbb::flow::tuple_element<1, OutputTuple>::type T1; typedef typename tbb::flow::tuple_element<2, OutputTuple>::type T2; @@ -1697,37 +1818,39 @@ namespace internal { typedef typename tbb::flow::tuple_element<8, OutputTuple>::type T8; typedef typename tbb::flow::tuple_element<9, OutputTuple>::type T9; public: - typedef typename wrap_tuple_elements<10, tag_matching_port, OutputTuple>::type input_ports_type; + typedef typename wrap_key_tuple_elements<10,key_matching_port,key_matching,OutputTuple>::type input_ports_type; typedef OutputTuple output_type; private: - typedef join_node_base base_type; - typedef typename internal::function_body *f0_p; - typedef typename internal::function_body *f1_p; - typedef typename internal::function_body *f2_p; - typedef typename internal::function_body *f3_p; - typedef typename internal::function_body *f4_p; - typedef typename internal::function_body *f5_p; - typedef typename internal::function_body *f6_p; - typedef typename internal::function_body *f7_p; - typedef typename internal::function_body *f8_p; - typedef typename internal::function_body *f9_p; + typedef join_node_base , input_ports_type, output_type > base_type; + typedef typename internal::type_to_key_function_body *f0_p; + typedef typename internal::type_to_key_function_body *f1_p; + typedef typename internal::type_to_key_function_body *f2_p; + typedef typename internal::type_to_key_function_body *f3_p; + typedef typename internal::type_to_key_function_body *f4_p; + typedef typename internal::type_to_key_function_body *f5_p; + typedef typename internal::type_to_key_function_body *f6_p; + typedef typename internal::type_to_key_function_body *f7_p; + typedef typename internal::type_to_key_function_body *f8_p; + typedef typename internal::type_to_key_function_body *f9_p; typedef typename tbb::flow::tuple< f0_p, f1_p, f2_p, f3_p, f4_p, f5_p, f6_p, f7_p, f8_p, f9_p > func_initializer_type; public: template unfolded_join_node(graph &g, Body0 body0, Body1 body1, Body2 body2, Body3 body3, Body4 body4, Body5 body5, Body6 body6, Body7 body7, Body8 body8, Body9 body9) : base_type(g, func_initializer_type( - new internal::function_body_leaf(body0), - new internal::function_body_leaf(body1), - new internal::function_body_leaf(body2), - new internal::function_body_leaf(body3), - new internal::function_body_leaf(body4), - new internal::function_body_leaf(body5), - new internal::function_body_leaf(body6), - new internal::function_body_leaf(body7), - new internal::function_body_leaf(body8), - new internal::function_body_leaf(body9) - ) ) {} + new internal::type_to_key_function_body_leaf(body0), + new internal::type_to_key_function_body_leaf(body1), + new internal::type_to_key_function_body_leaf(body2), + new internal::type_to_key_function_body_leaf(body3), + new internal::type_to_key_function_body_leaf(body4), + new internal::type_to_key_function_body_leaf(body5), + new internal::type_to_key_function_body_leaf(body6), + new internal::type_to_key_function_body_leaf(body7), + new internal::type_to_key_function_body_leaf(body8), + new internal::type_to_key_function_body_leaf(body9) + ) ) { + __TBB_STATIC_ASSERT(tbb::flow::tuple_size::value == 10, "wrong number of body initializers"); + } unfolded_join_node(const unfolded_join_node &other) : base_type(other) {} }; #endif diff --git a/dependencies64/tbb/include/tbb/internal/_flow_graph_node_impl.h b/dependencies64/tbb/include/tbb/internal/_flow_graph_node_impl.h index 837d83449..a18855d5a 100644 --- a/dependencies64/tbb/include/tbb/internal/_flow_graph_node_impl.h +++ b/dependencies64/tbb/include/tbb/internal/_flow_graph_node_impl.h @@ -1,5 +1,5 @@ /* - Copyright 2005-2014 Intel Corporation. All Rights Reserved. + Copyright 2005-2015 Intel Corporation. All Rights Reserved. This file is part of Threading Building Blocks. Threading Building Blocks is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License @@ -58,37 +58,44 @@ namespace internal { blt_pred_cnt, blt_pred_cpy // create vector copies of preds and succs #endif }; - typedef function_input_base my_class; + typedef function_input_base class_type; public: //! The input type of this receiver typedef Input input_type; typedef sender predecessor_type; + typedef predecessor_cache predecessor_cache_type; + typedef function_input_queue input_queue_type; + typedef typename A::template rebind< input_queue_type >::other queue_allocator_type; #if TBB_PREVIEW_FLOW_GRAPH_FEATURES - typedef std::vector predecessor_vector_type; + typedef typename predecessor_cache_type::built_predecessors_type built_predecessors_type; + typedef typename receiver::predecessor_list_type predecessor_list_type; #endif //! Constructor for function_input_base - function_input_base( graph &g, size_t max_concurrency, function_input_queue *q = NULL ) + function_input_base( graph &g, size_t max_concurrency, input_queue_type *q = NULL) : my_graph(g), my_max_concurrency(max_concurrency), my_concurrency(0), my_queue(q), forwarder_busy(false) { my_predecessors.set_owner(this); - my_aggregator.initialize_handler(my_handler(this)); + my_aggregator.initialize_handler(handler_type(this)); } //! Copy constructor - function_input_base( const function_input_base& src, function_input_queue *q = NULL ) : + function_input_base( const function_input_base& src, input_queue_type *q = NULL) : receiver(), tbb::internal::no_assign(), my_graph(src.my_graph), my_max_concurrency(src.my_max_concurrency), my_concurrency(0), my_queue(q), forwarder_busy(false) { my_predecessors.set_owner(this); - my_aggregator.initialize_handler(my_handler(this)); + my_aggregator.initialize_handler(handler_type(this)); } //! Destructor + // The queue is allocated by the constructor for {multi}function_node. + // TODO: pass the graph_buffer_policy to the base so it can allocate the queue instead. + // This would be an interface-breaking change. virtual ~function_input_base() { if ( my_queue ) delete my_queue; } @@ -98,7 +105,7 @@ namespace internal { if ( my_max_concurrency == 0 ) { return create_body_task( t ); } else { - my_operation op_data(t, tryput_bypass); + operation_type op_data(t, tryput_bypass); my_aggregator.execute(&op_data); if(op_data.status == SUCCEEDED ) { return op_data.bypass_t; @@ -109,7 +116,7 @@ namespace internal { //! Adds src to the list of cached predecessors. /* override */ bool register_predecessor( predecessor_type &src ) { - my_operation op_data(reg_pred); + operation_type op_data(reg_pred); op_data.r = &src; my_aggregator.execute(&op_data); return true; @@ -117,7 +124,7 @@ namespace internal { //! Removes src from the list of cached predecessors. /* override */ bool remove_predecessor( predecessor_type &src ) { - my_operation op_data(rem_pred); + operation_type op_data(rem_pred); op_data.r = &src; my_aggregator.execute(&op_data); return true; @@ -126,61 +133,65 @@ namespace internal { #if TBB_PREVIEW_FLOW_GRAPH_FEATURES //! Adds to list of predecessors added by make_edge /*override*/ void internal_add_built_predecessor( predecessor_type &src) { - my_operation op_data(add_blt_pred); + operation_type op_data(add_blt_pred); op_data.r = &src; my_aggregator.execute(&op_data); } //! removes from to list of predecessors (used by remove_edge) /*override*/ void internal_delete_built_predecessor( predecessor_type &src) { - my_operation op_data(del_blt_pred); + operation_type op_data(del_blt_pred); op_data.r = &src; my_aggregator.execute(&op_data); } /*override*/ size_t predecessor_count() { - my_operation op_data(blt_pred_cnt); + operation_type op_data(blt_pred_cnt); my_aggregator.execute(&op_data); return op_data.cnt_val; } - /*override*/ void copy_predecessors(predecessor_vector_type &v) { - my_operation op_data(blt_pred_cpy); + /*override*/ void copy_predecessors(predecessor_list_type &v) { + operation_type op_data(blt_pred_cpy); op_data.predv = &v; my_aggregator.execute(&op_data); } + + /*override*/built_predecessors_type &built_predecessors() { + return my_predecessors.built_predecessors(); + } #endif /* TBB_PREVIEW_FLOW_GRAPH_FEATURES */ protected: - void reset_function_input_base( __TBB_PFG_RESET_ARG(reset_flags f)) { + void reset_function_input_base( reset_flags f) { my_concurrency = 0; if(my_queue) { my_queue->reset(); } - reset_receiver(__TBB_PFG_RESET_ARG(f)); + reset_receiver(f); forwarder_busy = false; } graph& my_graph; const size_t my_max_concurrency; size_t my_concurrency; - function_input_queue *my_queue; + input_queue_type *my_queue; predecessor_cache my_predecessors; - /*override*/void reset_receiver( __TBB_PFG_RESET_ARG(reset_flags f)) { - my_predecessors.reset(__TBB_PFG_RESET_ARG(f)); -#if TBB_PREVIEW_FLOW_GRAPH_FEATURES - __TBB_ASSERT(!(f & rf_extract) || my_predecessors.empty(), "function_input_base reset failed"); -#endif + /*override*/void reset_receiver( reset_flags f) { + if( f & rf_clear_edges) my_predecessors.clear(); + else + my_predecessors.reset(); + __TBB_ASSERT(!(f & rf_clear_edges) || my_predecessors.empty(), "function_input_base reset failed"); } private: - friend class apply_body_task_bypass< my_class, input_type >; - friend class forward_task_bypass< my_class >; + friend class apply_body_task_bypass< class_type, input_type >; + friend class forward_task_bypass< class_type >; - class my_operation : public aggregated_operation< my_operation > { + class operation_type : public aggregated_operation< operation_type > { public: char type; union { @@ -188,22 +199,22 @@ namespace internal { predecessor_type *r; #if TBB_PREVIEW_FLOW_GRAPH_FEATURES size_t cnt_val; - predecessor_vector_type *predv; + predecessor_list_type *predv; #endif /* TBB_PREVIEW_FLOW_GRAPH_FEATURES */ }; tbb::task *bypass_t; - my_operation(const input_type& e, op_type t) : + operation_type(const input_type& e, op_type t) : type(char(t)), elem(const_cast(&e)) {} - my_operation(op_type t) : type(char(t)), r(NULL) {} + operation_type(op_type t) : type(char(t)), r(NULL) {} }; bool forwarder_busy; - typedef internal::aggregating_functor my_handler; - friend class internal::aggregating_functor; - aggregator< my_handler, my_operation > my_aggregator; + typedef internal::aggregating_functor handler_type; + friend class internal::aggregating_functor; + aggregator< handler_type, operation_type > my_aggregator; - void handle_operations(my_operation *op_list) { - my_operation *tmp; + void handle_operations(operation_type *op_list) { + operation_type *tmp; while (op_list) { tmp = op_list; op_list = op_list->next; @@ -283,7 +294,7 @@ namespace internal { } //! Put to the node, but return the task instead of enqueueing it - void internal_try_put_task(my_operation *op) { + void internal_try_put_task(operation_type *op) { __TBB_ASSERT(my_max_concurrency != 0, NULL); if (my_concurrency < my_max_concurrency) { ++my_concurrency; @@ -300,7 +311,7 @@ namespace internal { } //! Tries to spawn bodies if available and if concurrency allows - void internal_forward(my_operation *op) { + void internal_forward(operation_type *op) { op->bypass_t = NULL; if (my_concurrency(this)->apply_body_impl_bypass(i); if ( my_max_concurrency != 0 ) { - my_operation op_data(app_body_bypass); // tries to pop an item or get_item, enqueues another apply_body + operation_type op_data(app_body_bypass); // tries to pop an item or get_item, enqueues another apply_body my_aggregator.execute(&op_data); tbb::task *ttask = op_data.bypass_t; new_task = combine_tasks(new_task, ttask); @@ -346,10 +357,9 @@ namespace internal { //! allocates a task to call apply_body( input ) inline task * create_body_task( const input_type &input ) { - task* tp = my_graph.root_task(); - return (tp) ? - new(task::allocate_additional_child_of(*tp)) - apply_body_task_bypass < my_class, input_type >(*this, input) : + return (my_graph.is_active()) ? + new(task::allocate_additional_child_of(*(my_graph.root_task()))) + apply_body_task_bypass < class_type, input_type >(*this, input) : NULL; } @@ -364,7 +374,7 @@ namespace internal { //! This is executed by an enqueued task, the "forwarder" task *forward_task() { - my_operation op_data(try_fwd); + operation_type op_data(try_fwd); task *rval = NULL; do { op_data.status = WAIT; @@ -378,9 +388,8 @@ namespace internal { } inline task *create_forward_task() { - task* tp = my_graph.root_task(); - return (tp) ? - new(task::allocate_additional_child_of(*tp)) forward_task_bypass< my_class >(*this) : + return (my_graph.is_active()) ? + new(task::allocate_additional_child_of(*(my_graph.root_task()))) forward_task_bypass< class_type >(*this) : NULL; } @@ -400,31 +409,34 @@ namespace internal { public: typedef Input input_type; typedef Output output_type; + typedef function_body function_body_type; typedef function_input my_class; typedef function_input_base base_type; typedef function_input_queue input_queue_type; - // constructor template - function_input( graph &g, size_t max_concurrency, Body& body, function_input_queue *q = NULL ) : + function_input( graph &g, size_t max_concurrency, Body& body, input_queue_type *q = NULL ) : base_type(g, max_concurrency, q), - my_body( new internal::function_body_leaf< input_type, output_type, Body>(body) ) { + my_body( new internal::function_body_leaf< input_type, output_type, Body>(body) ), + my_init_body( new internal::function_body_leaf< input_type, output_type, Body>(body) ) { } //! Copy constructor function_input( const function_input& src, input_queue_type *q = NULL ) : base_type(src, q), - my_body( src.my_body->clone() ) { + my_body( src.my_init_body->clone() ), + my_init_body(src.my_init_body->clone() ) { } ~function_input() { delete my_body; + delete my_init_body; } template< typename Body > Body copy_function_object() { - internal::function_body &body_ref = *this->my_body; + function_body_type &body_ref = *this->my_body; return dynamic_cast< internal::function_body_leaf & >(body_ref).get_body(); } @@ -444,47 +456,58 @@ namespace internal { protected: - void reset_function_input(__TBB_PFG_RESET_ARG(reset_flags f)) { - base_type::reset_function_input_base(__TBB_PFG_RESET_ARG(f)); -#if TBB_PREVIEW_FLOW_GRAPH_FEATURES - if(f & rf_reset_bodies) my_body->reset_body(); -#endif + void reset_function_input(reset_flags f) { + base_type::reset_function_input_base(f); + if(f & rf_reset_bodies) { + function_body_type *tmp = my_init_body->clone(); + delete my_body; + my_body = tmp; + } } - function_body *my_body; + function_body_type *my_body; + function_body_type *my_init_body; virtual broadcast_cache &successors() = 0; }; // function_input -#if TBB_PREVIEW_FLOW_GRAPH_FEATURES - // helper templates to reset the successor edges of the output ports of an multifunction_node - template - struct reset_element { - template - static void reset_this(P &p, reset_flags f) { - (void)tbb::flow::get(p).successors().reset(f); - reset_element::reset_this(p, f); - } - template - static bool this_empty(P &p) { + // helper templates to clear the successor edges of the output ports of an multifunction_node + template struct clear_element { + template static void clear_this(P &p) { + (void)tbb::flow::get(p).successors().clear(); + clear_element::clear_this(p); + } + template static bool this_empty(P &p) { if(tbb::flow::get(p).successors().empty()) - return reset_element::this_empty(p); + return clear_element::this_empty(p); return false; } }; - template<> - struct reset_element<1> { - template - static void reset_this(P &p, reset_flags f) { - (void)tbb::flow::get<0>(p).successors().reset(f); + template<> struct clear_element<1> { + template static void clear_this(P &p) { + (void)tbb::flow::get<0>(p).successors().clear(); } - template - static bool this_empty(P &p) { + template static bool this_empty(P &p) { return tbb::flow::get<0>(p).successors().empty(); } }; + +#if TBB_PREVIEW_FLOW_GRAPH_FEATURES + // helper templates to extract the output ports of an multifunction_node from graph + template struct extract_element { + template static void extract_this(P &p) { + (void)tbb::flow::get(p).successors().built_successors().sender_extract(tbb::flow::get(p)); + extract_element::extract_this(p); + } + }; + + template<> struct extract_element<1> { + template static void extract_this(P &p) { + (void)tbb::flow::get<0>(p).successors().built_successors().sender_extract(tbb::flow::get<0>(p)); + } + }; #endif //! Implements methods for a function node that takes a type Input as input @@ -495,35 +518,38 @@ namespace internal { static const int N = tbb::flow::tuple_size::value; typedef Input input_type; typedef OutputPortSet output_ports_type; + typedef multifunction_body multifunction_body_type; typedef multifunction_input my_class; typedef function_input_base base_type; typedef function_input_queue input_queue_type; - // constructor template - multifunction_input( - graph &g, - size_t max_concurrency, + multifunction_input( + graph &g, + size_t max_concurrency, Body& body, - function_input_queue *q = NULL ) : + input_queue_type *q = NULL ) : base_type(g, max_concurrency, q), - my_body( new internal::multifunction_body_leaf(body) ) { + my_body( new internal::multifunction_body_leaf(body) ), + my_init_body( new internal::multifunction_body_leaf(body) ) { } //! Copy constructor multifunction_input( const multifunction_input& src, input_queue_type *q = NULL ) : base_type(src, q), - my_body( src.my_body->clone() ) { + my_body( src.my_init_body->clone() ), + my_init_body(src.my_init_body->clone() ) { } ~multifunction_input() { delete my_body; + delete my_init_body; } template< typename Body > Body copy_function_object() { - internal::multifunction_body &body_ref = *this->my_body; + multifunction_body_type &body_ref = *this->my_body; return dynamic_cast< internal::multifunction_body_leaf & >(body_ref).get_body(); } @@ -540,17 +566,25 @@ namespace internal { output_ports_type &output_ports(){ return my_output_ports; } protected: - - /*override*/void reset(__TBB_PFG_RESET_ARG(reset_flags f)) { - base_type::reset_function_input_base(__TBB_PFG_RESET_ARG(f)); #if TBB_PREVIEW_FLOW_GRAPH_FEATURES - reset_element::reset_this(my_output_ports, f); - if(f & rf_reset_bodies) my_body->reset_body(); - __TBB_ASSERT(!(f & rf_extract) || reset_element::this_empty(my_output_ports), "multifunction_node reset failed"); + /*override*/void extract() { + extract_element::extract_this(my_output_ports); + } #endif + + /*override*/void reset(reset_flags f) { + base_type::reset_function_input_base(f); + if(f & rf_clear_edges)clear_element::clear_this(my_output_ports); + if(f & rf_reset_bodies) { + multifunction_body_type *tmp = my_init_body->clone(); + delete my_body; + my_body = tmp; + } + __TBB_ASSERT(!(f & rf_clear_edges) || clear_element::this_empty(my_output_ports), "multifunction_node reset failed"); } - multifunction_body *my_body; + multifunction_body_type *my_body; + multifunction_body_type *my_init_body; output_ports_type my_output_ports; }; // multifunction_input @@ -589,41 +623,51 @@ namespace internal { //! The output type of this receiver typedef Output output_type; + typedef function_body function_body_type; template< typename Body > continue_input( graph &g, Body& body ) : my_graph_ptr(&g), - my_body( new internal::function_body_leaf< input_type, output_type, Body>(body) ) { } + my_body( new internal::function_body_leaf< input_type, output_type, Body>(body) ), + my_init_body( new internal::function_body_leaf< input_type, output_type, Body>(body) ) { } template< typename Body > continue_input( graph &g, int number_of_predecessors, Body& body ) : continue_receiver( number_of_predecessors ), my_graph_ptr(&g), - my_body( new internal::function_body_leaf< input_type, output_type, Body>(body) ) { } + my_body( new internal::function_body_leaf< input_type, output_type, Body>(body) ), + my_init_body( new internal::function_body_leaf< input_type, output_type, Body>(body) ) + { } continue_input( const continue_input& src ) : continue_receiver(src), - my_graph_ptr(src.my_graph_ptr), my_body( src.my_body->clone() ) {} + my_graph_ptr(src.my_graph_ptr), + my_body( src.my_init_body->clone() ), + my_init_body( src.my_init_body->clone() ) {} ~continue_input() { delete my_body; + delete my_init_body; } template< typename Body > Body copy_function_object() { - internal::function_body &body_ref = *my_body; + function_body_type &body_ref = *my_body; return dynamic_cast< internal::function_body_leaf & >(body_ref).get_body(); } - /*override*/void reset_receiver( __TBB_PFG_RESET_ARG(reset_flags f)) { - continue_receiver::reset_receiver(__TBB_PFG_RESET_ARG(f)); -#if TBB_PREVIEW_FLOW_GRAPH_FEATURES - if(f & rf_reset_bodies) my_body->reset_body(); -#endif + /*override*/void reset_receiver( reset_flags f) { + continue_receiver::reset_receiver(f); + if(f & rf_reset_bodies) { + function_body_type *tmp = my_init_body->clone(); + delete my_body; + my_body = tmp; + } } protected: graph* my_graph_ptr; - function_body *my_body; + function_body_type *my_body; + function_body_type *my_init_body; virtual broadcast_cache &successors() = 0; @@ -645,28 +689,93 @@ namespace internal { //! Spawns a task that applies the body /* override */ task *execute( ) { - task* tp = my_graph_ptr->root_task(); - return (tp) ? - new ( task::allocate_additional_child_of( *tp ) ) + return (my_graph_ptr->is_active()) ? + new ( task::allocate_additional_child_of( *(my_graph_ptr->root_task()) ) ) apply_body_task_bypass< continue_input< Output >, continue_msg >( *this, continue_msg() ) : NULL; } }; // continue_input + +#if __TBB_PREVIEW_ASYNC_NODE + + //! Implements methods for a async node that takes a type Input as input and + // submit it to Asynchronous activity + template < typename Input, typename A, typename AsyncGatewayType > + class async_input : public function_input_base > { + public: + typedef Input input_type; + typedef AsyncGatewayType async_gateway_type; + typedef async_body< input_type, async_gateway_type > async_body_type; + typedef async_input< Input, A, async_gateway_type > my_class; + typedef function_input_base base_type; + + // constructor + template + async_input( graph &g, Body& body ) : + base_type( g, unlimited ), + my_body( new internal::async_body_leaf< input_type, Body, async_gateway_type >(body) ), + my_init_body( new internal::async_body_leaf< input_type, Body, async_gateway_type >(body) ) + { + } + + //! Copy constructor + async_input( const async_input& src ) : + base_type( src ), + my_body( src.my_init_body->clone() ), + my_init_body(src.my_init_body->clone() ) { + } + + ~async_input() { + delete my_body; + delete my_init_body; + } + + template< typename Body > + Body copy_function_object() { + async_body_type &body_ref = *this->my_body; + return dynamic_cast< internal::async_body_leaf & >(body_ref).get_body(); + } + + task * apply_body_impl_bypass( const input_type &i) { + // TODO: This FGT instrumentation only captures the submission of the work + // but not the async thread activity. + // We will have to think about the best way to capture that. + tbb::internal::fgt_begin_body( my_body ); + (*my_body)( i, async_gateway() ); + tbb::internal::fgt_end_body( my_body ); + return NULL; + } + + virtual async_gateway_type& async_gateway() = 0; + + protected: + void reset_async_input(reset_flags f) { + base_type::reset_function_input_base(f); + if(f & rf_reset_bodies) { + async_body_type *tmp = my_init_body->clone(); + delete my_body; + my_body = tmp; + } + } + + async_body_type *my_body; + async_body_type *my_init_body; + }; +#endif // __TBB_PREVIEW_ASYNC_NODE //! Implements methods for both executable and function nodes that puts Output to its successors template< typename Output > class function_output : public sender { public: -#if TBB_PREVIEW_FLOW_GRAPH_FEATURES - template friend struct reset_element; -#endif + template friend struct clear_element; typedef Output output_type; typedef receiver successor_type; typedef broadcast_cache broadcast_cache_type; #if TBB_PREVIEW_FLOW_GRAPH_FEATURES - typedef std::vector successor_vector_type; + typedef typename sender::built_successors_type built_successors_type; + typedef typename sender::successor_list_type successor_list_type; #endif function_output() { my_successors.set_owner(this); } @@ -687,6 +796,9 @@ namespace internal { } #if TBB_PREVIEW_FLOW_GRAPH_FEATURES + built_successors_type &built_successors() { return successors().built_successors(); } + + /*override*/ void internal_add_built_successor( receiver &r) { successors().internal_add_built_successor( r ); } @@ -699,7 +811,7 @@ namespace internal { return successors().successor_count(); } - /*override*/ void copy_successors( successor_vector_type &v) { + /*override*/ void copy_successors( successor_list_type &v) { successors().copy_successors(v); } #endif /* TBB_PREVIEW_FLOW_GRAPH_FEATURES */ @@ -710,12 +822,13 @@ namespace internal { // // get(output_ports).try_put(output_value); // + // if task pointer is returned will always spawn and return true, else // return value will be bool returned from successors.try_put. task *try_put_task(const output_type &i) { return my_successors.try_put_task(i); } + broadcast_cache_type &successors() { return my_successors; } protected: broadcast_cache_type my_successors; - broadcast_cache_type &successors() { return my_successors; } }; // function_output @@ -737,6 +850,23 @@ namespace internal { } }; // multifunction_output +//composite_node +#if TBB_PREVIEW_FLOW_GRAPH_TRACE + template + void add_nodes_impl(CompositeType*, bool) {} + + template< typename CompositeType, typename NodeType1, typename... NodeTypes > + void add_nodes_impl(CompositeType *c_node, bool visible, const NodeType1& n1, const NodeTypes&... n) { + void *addr = const_cast(&n1); + + if(visible) + tbb::internal::itt_relation_add( tbb::internal::ITT_DOMAIN_FLOW, c_node, tbb::internal::FLOW_NODE, tbb::internal::__itt_relation_is_parent_of, addr, tbb::internal::FLOW_NODE ); + else + tbb::internal::itt_relation_add( tbb::internal::ITT_DOMAIN_FLOW, addr, tbb::internal::FLOW_NODE, tbb::internal::__itt_relation_is_child_of, c_node, tbb::internal::FLOW_NODE ); + add_nodes_impl(c_node, visible, n...); + } +#endif + } // internal #endif // __TBB__flow_graph_node_impl_H diff --git a/dependencies64/tbb/include/tbb/internal/_flow_graph_tagged_buffer_impl.h b/dependencies64/tbb/include/tbb/internal/_flow_graph_tagged_buffer_impl.h index 8c13eb592..7e17dc6c5 100644 --- a/dependencies64/tbb/include/tbb/internal/_flow_graph_tagged_buffer_impl.h +++ b/dependencies64/tbb/include/tbb/internal/_flow_graph_tagged_buffer_impl.h @@ -1,5 +1,5 @@ /* - Copyright 2005-2014 Intel Corporation. All Rights Reserved. + Copyright 2005-2015 Intel Corporation. All Rights Reserved. This file is part of Threading Building Blocks. Threading Building Blocks is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License @@ -18,53 +18,51 @@ reasons why the executable file might be covered by the GNU General Public License. */ -// tagged buffer that can expand, and can support as many deletions as additions -// list-based, with elements of list held in array (for destruction management), -// multiplicative hashing (like ets). No synchronization built-in. +// a hash table buffer that can expand, and can support as many deletions as +// additions, list-based, with elements of list held in array (for destruction +// management), multiplicative hashing (like ets). No synchronization built-in. // -#ifndef __TBB__flow_graph_tagged_buffer_impl_H -#define __TBB__flow_graph_tagged_buffer_impl_H +#ifndef __TBB__flow_graph_hash_buffer_impl_H +#define __TBB__flow_graph_hash_buffer_impl_H #ifndef __TBB_flow_graph_H #error Do not #include this internal file directly; use public TBB headers instead. #endif -// included in namespace tbb::flow::interface7::internal +// included in namespace tbb::flow::interface8::internal -template -struct otherData { - T t; - U next; - otherData() : t(NoTagMark), next(NULL) {} -}; - -template +// elements in the table are a simple list; we need pointer to next element to +// traverse the chain +template struct buffer_element_type { // the second parameter below is void * because we can't forward-declare the type // itself, so we just reinterpret_cast below. - typedef typename aligned_pair >::type type; + typedef typename aligned_pair::type type; }; template < - typename TagType, - typename ValueType, - size_t NoTagMark = 0, - typename Allocator=tbb::cache_aligned_allocator< typename buffer_element_type::type > + typename Key, // type of key within ValueType + typename ValueType, + typename ValueToKey, // abstract method that returns "const Key" or "const Key&" given ValueType + typename HashCompare, // has hash and equal + typename Allocator=tbb::cache_aligned_allocator< typename aligned_pair::type > > -class tagged_buffer { +class hash_buffer : public HashCompare { public: static const size_t INITIAL_SIZE = 8; // initial size of the hash pointer table - static const TagType NO_TAG = TagType(NoTagMark); typedef ValueType value_type; - typedef typename buffer_element_type::type element_type; + typedef typename buffer_element_type< value_type >::type element_type; typedef value_type *pointer_type; typedef element_type *list_array_type; // array we manage manually typedef list_array_type *pointer_array_type; typedef typename Allocator::template rebind::other pointer_array_allocator_type; typedef typename Allocator::template rebind::other elements_array_allocator; + typedef typename tbb::internal::strip::type Knoref; + private: + ValueToKey *my_key; size_t my_size; size_t nelements; pointer_array_type pointer_array; // pointer_array[my_size] @@ -73,17 +71,12 @@ private: size_t mask() { return my_size - 1; } - static size_t hash(TagType t) { - return uintptr_t(t)*tbb::internal::select_size_t_constant<0x9E3779B9,0x9E3779B97F4A7C15ULL>::value; - } - void set_up_free_list( element_type **p_free_list, list_array_type la, size_t sz) { for(size_t i=0; i < sz - 1; ++i ) { // construct free list - la[i].second.next = &(la[i+1]); - la[i].second.t = NO_TAG; + la[i].second = &(la[i+1]); } - la[sz-1].second.next = NULL; - *p_free_list = &(la[0]); + la[sz-1].second = NULL; + *p_free_list = (element_type *)&(la[0]); } // cleanup for exceptions @@ -117,10 +110,10 @@ private: set_up_free_list(&new_free_list, new_elements_array, my_size ); for(size_t i=0; i < my_size; ++i) { - for( element_type* op = pointer_array[i]; op; op = (element_type *)(op->second.next)) { + for( element_type* op = pointer_array[i]; op; op = (element_type *)(op->second)) { value_type *ov = reinterpret_cast(&(op->first)); // could have std::move semantics - internal_tagged_insert(new_pointer_array, new_size, new_free_list, op->second.t, *ov); + internal_insert_with_key(new_pointer_array, new_size, new_free_list, *ov); } } my_cleanup.my_pa = NULL; @@ -137,15 +130,15 @@ private: // v should have perfect forwarding if std::move implemented. // we use this method to move elements in grow_array, so can't use class fields - void internal_tagged_insert( element_type **p_pointer_array, size_t p_sz, list_array_type &p_free_list, - const TagType t, const value_type &v) { + void internal_insert_with_key( element_type **p_pointer_array, size_t p_sz, list_array_type &p_free_list, + const value_type &v) { size_t l_mask = p_sz-1; - size_t h = hash(t) & l_mask; + __TBB_ASSERT(my_key, "Error: value-to-key functor not provided"); + size_t h = this->hash((*my_key)(v)) & l_mask; __TBB_ASSERT(p_free_list, "Error: free list not set up."); - element_type* my_elem = p_free_list; p_free_list = (element_type *)(p_free_list->second.next); - my_elem->second.t = t; + element_type* my_elem = p_free_list; p_free_list = (element_type *)(p_free_list->second); (void) new(&(my_elem->first)) value_type(v); - my_elem->second.next = p_pointer_array[h]; + my_elem->second = p_pointer_array[h]; p_pointer_array[h] = my_elem; } @@ -162,12 +155,11 @@ private: for(size_t i = 0; i < sz; ++i ) { element_type *p_next; for( element_type *p = pa[i]; p; p = p_next) { - p_next = (element_type *)p->second.next; - value_type *vp = reinterpret_cast(&(p->first)); - vp->~value_type(); + p_next = (element_type *)p->second; + internal::punned_cast(&(p->first))->~value_type(); } } - pointer_array_allocator_type().deallocate(pa, sz); + pointer_array_allocator_type().deallocate(pa, sz); pa = NULL; } // Separate test (if allocation of pa throws, el may be allocated. @@ -181,12 +173,13 @@ private: } public: - tagged_buffer() : my_size(INITIAL_SIZE), nelements(0) { + hash_buffer() : my_key(NULL), my_size(INITIAL_SIZE), nelements(0) { internal_initialize_buffer(); } - ~tagged_buffer() { + ~hash_buffer() { internal_free_buffer(pointer_array, elements_array, my_size, nelements); + if(my_key) delete my_key; } void reset() { @@ -194,34 +187,43 @@ public: internal_initialize_buffer(); } - bool tagged_insert(const TagType t, const value_type &v) { - pointer_type p; - if(tagged_find_ref(t, p)) { + // Take ownership of func object allocated with new. + // This method is only used internally, so can't be misused by user. + void set_key_func(ValueToKey *vtk) { my_key = vtk; } + // pointer is used to clone() + ValueToKey* get_key_func() { return my_key; } + + bool insert_with_key(const value_type &v) { + pointer_type p = NULL; + __TBB_ASSERT(my_key, "Error: value-to-key functor not provided"); + if(find_ref_with_key((*my_key)(v), p)) { p->~value_type(); (void) new(p) value_type(v); // copy-construct into the space return false; } ++nelements; if(nelements*2 > my_size) grow_array(); - internal_tagged_insert(pointer_array, my_size, free_list, t, v); + internal_insert_with_key(pointer_array, my_size, free_list, v); return true; } - // returns reference to array element.v - bool tagged_find_ref(const TagType t, pointer_type &v) { - size_t i = hash(t) & mask(); - for(element_type* p = pointer_array[i]; p; p = (element_type *)(p->second.next)) { - if(p->second.t == t) { - v = reinterpret_cast(&(p->first)); + // returns true and sets v to array element if found, else returns false. + bool find_ref_with_key(const Knoref& k, pointer_type &v) { + size_t i = this->hash(k) & mask(); + for(element_type* p = pointer_array[i]; p; p = (element_type *)(p->second)) { + pointer_type pv = reinterpret_cast(&(p->first)); + __TBB_ASSERT(my_key, "Error: value-to-key functor not provided"); + if(this->equal((*my_key)(*pv), k)) { + v = pv; return true; } } return false; } - bool tagged_find( const TagType t, value_type &v) { + bool find_with_key( const Knoref& k, value_type &v) { value_type *p; - if(tagged_find_ref(t, p)) { + if(find_ref_with_key(k, p)) { v = *p; return true; } @@ -229,23 +231,23 @@ public: return false; } - void tagged_delete(const TagType t) { - size_t h = hash(t) & mask(); + void delete_with_key(const Knoref& k) { + size_t h = this->hash(k) & mask(); element_type* prev = NULL; - for(element_type* p = pointer_array[h]; p; prev = p, p = (element_type *)(p->second.next)) { - if(p->second.t == t) { - value_type *vp = reinterpret_cast(&(p->first)); + for(element_type* p = pointer_array[h]; p; prev = p, p = (element_type *)(p->second)) { + value_type *vp = reinterpret_cast(&(p->first)); + __TBB_ASSERT(my_key, "Error: value-to-key functor not provided"); + if(this->equal((*my_key)(*vp), k)) { vp->~value_type(); - p->second.t = NO_TAG; - if(prev) prev->second.next = p->second.next; - else pointer_array[h] = (element_type *)(p->second.next); - p->second.next = free_list; + if(prev) prev->second = p->second; + else pointer_array[h] = (element_type *)(p->second); + p->second = free_list; free_list = p; --nelements; return; } } - __TBB_ASSERT(false, "tag not found for delete"); + __TBB_ASSERT(false, "key not found for delete"); } }; -#endif // __TBB__flow_graph_tagged_buffer_impl_H +#endif // __TBB__flow_graph_hash_buffer_impl_H diff --git a/dependencies64/tbb/include/tbb/internal/_flow_graph_trace_impl.h b/dependencies64/tbb/include/tbb/internal/_flow_graph_trace_impl.h index 43efc7c8e..17476bf53 100644 --- a/dependencies64/tbb/include/tbb/internal/_flow_graph_trace_impl.h +++ b/dependencies64/tbb/include/tbb/internal/_flow_graph_trace_impl.h @@ -1,5 +1,5 @@ /* - Copyright 2005-2014 Intel Corporation. All Rights Reserved. + Copyright 2005-2015 Intel Corporation. All Rights Reserved. This file is part of Threading Building Blocks. Threading Building Blocks is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License @@ -36,49 +36,63 @@ static inline void fgt_internal_create_output_port( void *node, void *p, string_ itt_make_task_group( ITT_DOMAIN_FLOW, p, FLOW_OUTPUT_PORT, node, FLOW_NODE, name_index ); } -template < typename TypesTuple, typename PortsTuple, int N > +template +void register_input_port(void *node, tbb::flow::interface8::receiver* port, string_index name_index) { + //TODO: Make fgt_internal_create_input_port a function template? + fgt_internal_create_input_port( node, port, name_index); +} + +template < typename PortsTuple, int N > struct fgt_internal_input_helper { static void register_port( void *node, PortsTuple &ports ) { - fgt_internal_create_input_port( node, (void*)static_cast< tbb::flow::interface7::receiver< typename tbb::flow::tuple_element::type > * >(&(tbb::flow::get(ports))), - static_cast(FLOW_INPUT_PORT_0 + N - 1) ); - fgt_internal_input_helper::register_port( node, ports ); + register_input_port( node, &(tbb::flow::get(ports)), static_cast(FLOW_INPUT_PORT_0 + N - 1) ); + fgt_internal_input_helper::register_port( node, ports ); } }; -template < typename TypesTuple, typename PortsTuple > -struct fgt_internal_input_helper { +template < typename PortsTuple > +struct fgt_internal_input_helper { static void register_port( void *node, PortsTuple &ports ) { - fgt_internal_create_input_port( node, (void*)static_cast< tbb::flow::interface7::receiver< typename tbb::flow::tuple_element<0,TypesTuple>::type > * >(&(tbb::flow::get<0>(ports))), - FLOW_INPUT_PORT_0 ); + register_input_port( node, &(tbb::flow::get<0>(ports)), FLOW_INPUT_PORT_0 ); } }; -template < typename TypesTuple, typename PortsTuple, int N > +template +void register_output_port(void *node, tbb::flow::interface8::sender* port, string_index name_index) { + //TODO: Make fgt_internal_create_output_port a function template? + fgt_internal_create_output_port( node, port, name_index); +} + +template < typename PortsTuple, int N > struct fgt_internal_output_helper { static void register_port( void *node, PortsTuple &ports ) { - fgt_internal_create_output_port( node, (void*)static_cast< tbb::flow::interface7::sender< typename tbb::flow::tuple_element::type > * >(&(tbb::flow::get(ports))), - static_cast(FLOW_OUTPUT_PORT_0 + N - 1) ); - fgt_internal_output_helper::register_port( node, ports ); + register_output_port( node, &(tbb::flow::get(ports)), static_cast(FLOW_OUTPUT_PORT_0 + N - 1) ); + fgt_internal_output_helper::register_port( node, ports ); } }; -template < typename TypesTuple, typename PortsTuple > -struct fgt_internal_output_helper { +template < typename PortsTuple > +struct fgt_internal_output_helper { static void register_port( void *node, PortsTuple &ports ) { - fgt_internal_create_output_port( node, (void*)static_cast< tbb::flow::interface7::sender< typename tbb::flow::tuple_element<0,TypesTuple>::type > * >(&(tbb::flow::get<0>(ports))), - FLOW_OUTPUT_PORT_0 ); + register_output_port( node, &(tbb::flow::get<0>(ports)), FLOW_OUTPUT_PORT_0 ); } }; template< typename NodeType > void fgt_multioutput_node_desc( const NodeType *node, const char *desc ) { - void *addr = (void *)( static_cast< tbb::flow::interface7::receiver< typename NodeType::input_type > * >(const_cast< NodeType *>(node)) ); + void *addr = (void *)( static_cast< tbb::flow::interface8::receiver< typename NodeType::input_type > * >(const_cast< NodeType *>(node)) ); + itt_metadata_str_add( ITT_DOMAIN_FLOW, addr, FLOW_NODE, FLOW_OBJECT_NAME, desc ); +} + +template< typename NodeType > +void fgt_multiinput_multioutput_node_desc( const NodeType *node, const char *desc ) { + void *addr = const_cast(node); itt_metadata_str_add( ITT_DOMAIN_FLOW, addr, FLOW_NODE, FLOW_OBJECT_NAME, desc ); } template< typename NodeType > static inline void fgt_node_desc( const NodeType *node, const char *desc ) { - void *addr = (void *)( static_cast< tbb::flow::interface7::sender< typename NodeType::output_type > * >(const_cast< NodeType *>(node)) ); + void *addr = (void *)( static_cast< tbb::flow::interface8::sender< typename NodeType::output_type > * >(const_cast< NodeType *>(node)) ); itt_metadata_str_add( ITT_DOMAIN_FLOW, addr, FLOW_NODE, FLOW_OBJECT_NAME, desc ); } @@ -90,27 +104,27 @@ static inline void fgt_body( void *node, void *body ) { itt_relation_add( ITT_DOMAIN_FLOW, body, FLOW_BODY, __itt_relation_is_child_of, node, FLOW_NODE ); } -template< typename OutputTuple, int N, typename PortsTuple > +template< int N, typename PortsTuple > static inline void fgt_multioutput_node( string_index t, void *g, void *input_port, PortsTuple &ports ) { itt_make_task_group( ITT_DOMAIN_FLOW, input_port, FLOW_NODE, g, FLOW_GRAPH, t ); fgt_internal_create_input_port( input_port, input_port, FLOW_INPUT_PORT_0 ); - fgt_internal_output_helper::register_port( input_port, ports ); + fgt_internal_output_helper::register_port( input_port, ports ); } -template< typename OutputTuple, int N, typename PortsTuple > +template< int N, typename PortsTuple > static inline void fgt_multioutput_node_with_body( string_index t, void *g, void *input_port, PortsTuple &ports, void *body ) { itt_make_task_group( ITT_DOMAIN_FLOW, input_port, FLOW_NODE, g, FLOW_GRAPH, t ); fgt_internal_create_input_port( input_port, input_port, FLOW_INPUT_PORT_0 ); - fgt_internal_output_helper::register_port( input_port, ports ); + fgt_internal_output_helper::register_port( input_port, ports ); fgt_body( input_port, body ); } -template< typename InputTuple, int N, typename PortsTuple > +template< int N, typename PortsTuple > static inline void fgt_multiinput_node( string_index t, void *g, PortsTuple &ports, void *output_port) { itt_make_task_group( ITT_DOMAIN_FLOW, output_port, FLOW_NODE, g, FLOW_GRAPH, t ); fgt_internal_create_output_port( output_port, output_port, FLOW_OUTPUT_PORT_0 ); - fgt_internal_input_helper::register_port( output_port, ports ); + fgt_internal_input_helper::register_port( output_port, ports ); } static inline void fgt_node( string_index t, void *g, void *output_port ) { @@ -175,13 +189,13 @@ static inline void fgt_graph_desc( void * /*g*/, const char * /*desc*/ ) { } static inline void fgt_body( void * /*node*/, void * /*body*/ ) { } -template< typename OutputTuple, int N, typename PortsTuple > +template< int N, typename PortsTuple > static inline void fgt_multioutput_node( string_index /*t*/, void * /*g*/, void * /*input_port*/, PortsTuple & /*ports*/ ) { } -template< typename OutputTuple, int N, typename PortsTuple > +template< int N, typename PortsTuple > static inline void fgt_multioutput_node_with_body( string_index /*t*/, void * /*g*/, void * /*input_port*/, PortsTuple & /*ports*/, void * /*body*/ ) { } -template< typename InputTuple, int N, typename PortsTuple > +template< int N, typename PortsTuple > static inline void fgt_multiinput_node( string_index /*t*/, void * /*g*/, PortsTuple & /*ports*/, void * /*output_port*/ ) { } static inline void fgt_node( string_index /*t*/, void * /*g*/, void * /*output_port*/ ) { } diff --git a/dependencies64/tbb/include/tbb/internal/_flow_graph_types_impl.h b/dependencies64/tbb/include/tbb/internal/_flow_graph_types_impl.h index 28a525a4d..627026544 100644 --- a/dependencies64/tbb/include/tbb/internal/_flow_graph_types_impl.h +++ b/dependencies64/tbb/include/tbb/internal/_flow_graph_types_impl.h @@ -1,5 +1,5 @@ /* - Copyright 2005-2014 Intel Corporation. All Rights Reserved. + Copyright 2005-2015 Intel Corporation. All Rights Reserved. This file is part of Threading Building Blocks. Threading Building Blocks is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License @@ -25,14 +25,38 @@ #error Do not #include this internal file directly; use public TBB headers instead. #endif -// included in namespace tbb::flow::interface7 +// included in namespace tbb::flow::interface8 namespace internal { -// wrap each element of a tuple in a template, and make a tuple of the result. + // the change to key_matching (adding a K and KHash template parameter, making it a class) + // means we have to pass this data to the key_matching_port. All the ports have only one + // template parameter, so we have to wrap the following types in a trait: + // + // . K == key_type + // . KHash == hash and compare for Key + // . TtoK == function_body that given an object of T, returns its K + // . T == type accepted by port, and stored in the hash table + // + // The port will have an additional parameter on node construction, which is a function_body + // that accepts a const T& and returns a K which is the field in T which is its K. + template + struct KeyTrait { + typedef Kp K; + typedef Tp T; + typedef internal::type_to_key_function_body TtoK; + typedef KHashp KHash; + }; + +// wrap each element of a tuple in a template, and make a tuple of the result. template class PT, typename TypeTuple> struct wrap_tuple_elements; + // A wrapper that generates the traits needed for each port of a key-matching join, + // and the type of the tuple of input ports. + template class PT, typename KeyTraits, typename TypeTuple> + struct wrap_key_tuple_elements; + template class PT, typename TypeTuple> struct wrap_tuple_elements<1, PT, TypeTuple> { typedef typename tbb::flow::tuple< @@ -40,6 +64,14 @@ namespace internal { type; }; + template class PT, typename KeyTraits, typename TypeTuple> + struct wrap_key_tuple_elements<1, PT, KeyTraits, TypeTuple > { + typedef typename KeyTraits::key_type K; + typedef typename KeyTraits::hash_compare_type KHash; + typedef KeyTrait::type> KeyTrait0; + typedef typename tbb::flow::tuple< PT > type; + }; + template class PT, typename TypeTuple> struct wrap_tuple_elements<2, PT, TypeTuple> { typedef typename tbb::flow::tuple< @@ -48,6 +80,15 @@ namespace internal { type; }; + template class PT, typename KeyTraits, typename TypeTuple> + struct wrap_key_tuple_elements<2, PT, KeyTraits, TypeTuple> { + typedef typename KeyTraits::key_type K; + typedef typename KeyTraits::hash_compare_type KHash; + typedef KeyTrait::type> KeyTrait0; + typedef KeyTrait::type> KeyTrait1; + typedef typename tbb::flow::tuple< PT, PT > type; + }; + template class PT, typename TypeTuple> struct wrap_tuple_elements<3, PT, TypeTuple> { typedef typename tbb::flow::tuple< @@ -57,6 +98,16 @@ namespace internal { type; }; + template class PT, typename KeyTraits, typename TypeTuple> + struct wrap_key_tuple_elements<3, PT, KeyTraits, TypeTuple> { + typedef typename KeyTraits::key_type K; + typedef typename KeyTraits::hash_compare_type KHash; + typedef KeyTrait::type> KeyTrait0; + typedef KeyTrait::type> KeyTrait1; + typedef KeyTrait::type> KeyTrait2; + typedef typename tbb::flow::tuple< PT, PT, PT > type; + }; + template class PT, typename TypeTuple> struct wrap_tuple_elements<4, PT, TypeTuple> { typedef typename tbb::flow::tuple< @@ -67,6 +118,18 @@ namespace internal { type; }; + template class PT, typename KeyTraits, typename TypeTuple> + struct wrap_key_tuple_elements<4, PT, KeyTraits, TypeTuple> { + typedef typename KeyTraits::key_type K; + typedef typename KeyTraits::hash_compare_type KHash; + typedef KeyTrait::type> KeyTrait0; + typedef KeyTrait::type> KeyTrait1; + typedef KeyTrait::type> KeyTrait2; + typedef KeyTrait::type> KeyTrait3; + typedef typename tbb::flow::tuple< PT, PT, PT, + PT > type; + }; + template class PT, typename TypeTuple> struct wrap_tuple_elements<5, PT, TypeTuple> { typedef typename tbb::flow::tuple< @@ -78,6 +141,19 @@ namespace internal { type; }; + template class PT, typename KeyTraits, typename TypeTuple> + struct wrap_key_tuple_elements<5, PT, KeyTraits, TypeTuple> { + typedef typename KeyTraits::key_type K; + typedef typename KeyTraits::hash_compare_type KHash; + typedef KeyTrait::type> KeyTrait0; + typedef KeyTrait::type> KeyTrait1; + typedef KeyTrait::type> KeyTrait2; + typedef KeyTrait::type> KeyTrait3; + typedef KeyTrait::type> KeyTrait4; + typedef typename tbb::flow::tuple< PT, PT, PT, + PT, PT > type; + }; + #if __TBB_VARIADIC_MAX >= 6 template class PT, typename TypeTuple> struct wrap_tuple_elements<6, PT, TypeTuple> { @@ -90,6 +166,20 @@ namespace internal { PT::type> > type; }; + + template class PT, typename KeyTraits, typename TypeTuple> + struct wrap_key_tuple_elements<6, PT, KeyTraits, TypeTuple> { + typedef typename KeyTraits::key_type K; + typedef typename KeyTraits::hash_compare_type KHash; + typedef KeyTrait::type> KeyTrait0; + typedef KeyTrait::type> KeyTrait1; + typedef KeyTrait::type> KeyTrait2; + typedef KeyTrait::type> KeyTrait3; + typedef KeyTrait::type> KeyTrait4; + typedef KeyTrait::type> KeyTrait5; + typedef typename tbb::flow::tuple< PT, PT, PT, PT, + PT, PT > type; + }; #endif #if __TBB_VARIADIC_MAX >= 7 @@ -105,6 +195,21 @@ namespace internal { PT::type> > type; }; + + template class PT, typename KeyTraits, typename TypeTuple> + struct wrap_key_tuple_elements<7, PT, KeyTraits, TypeTuple> { + typedef typename KeyTraits::key_type K; + typedef typename KeyTraits::hash_compare_type KHash; + typedef KeyTrait::type> KeyTrait0; + typedef KeyTrait::type> KeyTrait1; + typedef KeyTrait::type> KeyTrait2; + typedef KeyTrait::type> KeyTrait3; + typedef KeyTrait::type> KeyTrait4; + typedef KeyTrait::type> KeyTrait5; + typedef KeyTrait::type> KeyTrait6; + typedef typename tbb::flow::tuple< PT, PT, PT, PT, + PT, PT, PT > type; + }; #endif #if __TBB_VARIADIC_MAX >= 8 @@ -121,6 +226,22 @@ namespace internal { PT::type> > type; }; + + template class PT, typename KeyTraits, typename TypeTuple> + struct wrap_key_tuple_elements<8, PT, KeyTraits, TypeTuple> { + typedef typename KeyTraits::key_type K; + typedef typename KeyTraits::hash_compare_type KHash; + typedef KeyTrait::type> KeyTrait0; + typedef KeyTrait::type> KeyTrait1; + typedef KeyTrait::type> KeyTrait2; + typedef KeyTrait::type> KeyTrait3; + typedef KeyTrait::type> KeyTrait4; + typedef KeyTrait::type> KeyTrait5; + typedef KeyTrait::type> KeyTrait6; + typedef KeyTrait::type> KeyTrait7; + typedef typename tbb::flow::tuple< PT, PT, PT, PT, + PT, PT, PT, PT > type; + }; #endif #if __TBB_VARIADIC_MAX >= 9 @@ -138,6 +259,23 @@ namespace internal { PT::type> > type; }; + + template class PT, typename KeyTraits, typename TypeTuple> + struct wrap_key_tuple_elements<9, PT, KeyTraits, TypeTuple> { + typedef typename KeyTraits::key_type K; + typedef typename KeyTraits::hash_compare_type KHash; + typedef KeyTrait::type> KeyTrait0; + typedef KeyTrait::type> KeyTrait1; + typedef KeyTrait::type> KeyTrait2; + typedef KeyTrait::type> KeyTrait3; + typedef KeyTrait::type> KeyTrait4; + typedef KeyTrait::type> KeyTrait5; + typedef KeyTrait::type> KeyTrait6; + typedef KeyTrait::type> KeyTrait7; + typedef KeyTrait::type> KeyTrait8; + typedef typename tbb::flow::tuple< PT, PT, PT, PT, + PT, PT, PT, PT, PT > type; + }; #endif #if __TBB_VARIADIC_MAX >= 10 @@ -156,6 +294,25 @@ namespace internal { PT::type> > type; }; + + template class PT, typename KeyTraits, typename TypeTuple> + struct wrap_key_tuple_elements<10, PT, KeyTraits, TypeTuple> { + typedef typename KeyTraits::key_type K; + typedef typename KeyTraits::hash_compare_type KHash; + typedef KeyTrait::type> KeyTrait0; + typedef KeyTrait::type> KeyTrait1; + typedef KeyTrait::type> KeyTrait2; + typedef KeyTrait::type> KeyTrait3; + typedef KeyTrait::type> KeyTrait4; + typedef KeyTrait::type> KeyTrait5; + typedef KeyTrait::type> KeyTrait6; + typedef KeyTrait::type> KeyTrait7; + typedef KeyTrait::type> KeyTrait8; + typedef KeyTrait::type> KeyTrait9; + typedef typename tbb::flow::tuple< PT, PT, PT, PT, + PT, PT, PT, PT, PT, + PT > type; + }; #endif //! type mimicking std::pair but with trailing fill to ensure each element of an array @@ -339,20 +496,16 @@ template< class Tuple, template class Selector > struct pick_tuple_max<0, }; // is the specified type included in a tuple? - -template struct is_same_type { static const bool value = false; }; -template struct is_same_type { static const bool value = true; }; - template struct is_element_of { typedef typename tbb::flow::tuple_element::type T_i; - static const bool value = is_same_type::value || is_element_of::value; + static const bool value = tbb::internal::is_same_type::value || is_element_of::value; }; template struct is_element_of { typedef typename tbb::flow::tuple_element<0, Tuple>::type T_i; - static const bool value = is_same_type::value; + static const bool value = tbb::internal::is_same_type::value; }; // allow the construction of types that are listed tuple. If a disallowed type @@ -383,11 +536,12 @@ struct do_if { using tbb::internal::punned_cast; struct tagged_null_type {}; -template class tagged_msg { typedef tbb::flow::tuple= 6 , T5 #endif @@ -403,7 +557,7 @@ class tagged_msg { #if __TBB_VARIADIC_MAX >= 10 , T9 #endif - > Tuple; + > Tuple; private: class variant { @@ -463,11 +617,11 @@ private: variant my_msg; public: - tagged_msg(): my_tag(TagType(~0)), my_msg(){} + tagged_msg(): my_tag(TagType(~0)), my_msg(){} template tagged_msg(T const &index, R const &value) : my_tag(index), my_msg(value) {} - + #if __TBB_CONST_REF_TO_ARRAY_TEMPLATE_PARAM_BROKEN template tagged_msg(T const &index, R (&value)[N]) : my_tag(index), my_msg(value) {} @@ -486,11 +640,11 @@ public: }; //class tagged_msg // template to simplify cast and test for tagged_msg in template contexts -template -const T& cast_to(V const &v) { return v.template cast_to(); } +template +const V& cast_to(T const &t) { return t.template cast_to(); } -template -bool is_a(V const &v) { return v.template is_a(); } +template +bool is_a(T const &t) { return t.template is_a(); } } // namespace internal diff --git a/dependencies64/tbb/include/tbb/internal/_mutex_padding.h b/dependencies64/tbb/include/tbb/internal/_mutex_padding.h index ae07599c0..53d164fb4 100644 --- a/dependencies64/tbb/include/tbb/internal/_mutex_padding.h +++ b/dependencies64/tbb/include/tbb/internal/_mutex_padding.h @@ -1,5 +1,5 @@ /* - Copyright 2005-2014 Intel Corporation. All Rights Reserved. + Copyright 2005-2015 Intel Corporation. All Rights Reserved. This file is part of Threading Building Blocks. Threading Building Blocks is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License diff --git a/dependencies64/tbb/include/tbb/internal/_range_iterator.h b/dependencies64/tbb/include/tbb/internal/_range_iterator.h index 0622c4ffb..37cd6162f 100644 --- a/dependencies64/tbb/include/tbb/internal/_range_iterator.h +++ b/dependencies64/tbb/include/tbb/internal/_range_iterator.h @@ -1,5 +1,5 @@ /* - Copyright 2005-2014 Intel Corporation. All Rights Reserved. + Copyright 2005-2015 Intel Corporation. All Rights Reserved. This file is part of Threading Building Blocks. Threading Building Blocks is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License diff --git a/dependencies64/tbb/include/tbb/internal/_tbb_hash_compare_impl.h b/dependencies64/tbb/include/tbb/internal/_tbb_hash_compare_impl.h new file mode 100644 index 000000000..f9b9cb7dd --- /dev/null +++ b/dependencies64/tbb/include/tbb/internal/_tbb_hash_compare_impl.h @@ -0,0 +1,108 @@ +/* + Copyright 2005-2015 Intel Corporation. All Rights Reserved. + + This file is part of Threading Building Blocks. Threading Building Blocks is free software; + you can redistribute it and/or modify it under the terms of the GNU General Public License + version 2 as published by the Free Software Foundation. Threading Building Blocks is + distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the + implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + See the GNU General Public License for more details. You should have received a copy of + the GNU General Public License along with Threading Building Blocks; if not, write to the + Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + As a special exception, you may use this file as part of a free software library without + restriction. Specifically, if other files instantiate templates or use macros or inline + functions from this file, or you compile this file and link it with other files to produce + an executable, this file does not by itself cause the resulting executable to be covered + by the GNU General Public License. This exception does not however invalidate any other + reasons why the executable file might be covered by the GNU General Public License. +*/ + +// must be included outside namespaces. +#ifndef __TBB_tbb_hash_compare_impl_H +#define __TBB_tbb_hash_compare_impl_H + +#include + +namespace tbb { +namespace interface5 { +namespace internal { + +// Template class for hash compare +template +class hash_compare +{ +public: + typedef Hasher hasher; + typedef Key_equality key_equal; + + hash_compare() {} + + hash_compare(Hasher a_hasher) : my_hash_object(a_hasher) {} + + hash_compare(Hasher a_hasher, Key_equality a_keyeq) : my_hash_object(a_hasher), my_key_compare_object(a_keyeq) {} + + size_t operator()(const Key& key) const { + return ((size_t)my_hash_object(key)); + } + + bool operator()(const Key& key1, const Key& key2) const { + return (!my_key_compare_object(key1, key2)); + } + + Hasher my_hash_object; // The hash object + Key_equality my_key_compare_object; // The equality comparator object +}; + +//! Hash multiplier +static const size_t hash_multiplier = tbb::internal::select_size_t_constant<2654435769U, 11400714819323198485ULL>::value; + +} // namespace internal + +//! Hasher functions +template +inline size_t tbb_hasher( const T& t ) { + return static_cast( t ) * internal::hash_multiplier; +} +template +inline size_t tbb_hasher( P* ptr ) { + size_t const h = reinterpret_cast( ptr ); + return (h >> 3) ^ h; +} +template +inline size_t tbb_hasher( const std::basic_string& s ) { + size_t h = 0; + for( const E* c = s.c_str(); *c; ++c ) + h = static_cast(*c) ^ (h * internal::hash_multiplier); + return h; +} +template +inline size_t tbb_hasher( const std::pair& p ) { + return tbb_hasher(p.first) ^ tbb_hasher(p.second); +} + +} // namespace interface5 +using interface5::tbb_hasher; + +// Template class for hash compare +template +class tbb_hash +{ +public: + tbb_hash() {} + + size_t operator()(const Key& key) const + { + return tbb_hasher(key); + } +}; + +//! hash_compare that is default argument for concurrent_hash_map +template +struct tbb_hash_compare { + static size_t hash( const Key& a ) { return tbb_hasher(a); } + static bool equal( const Key& a, const Key& b ) { return a == b; } +}; + +} // namespace tbb +#endif /* __TBB_tbb_hash_compare_impl_H */ diff --git a/dependencies64/tbb/include/tbb/internal/_tbb_strings.h b/dependencies64/tbb/include/tbb/internal/_tbb_strings.h index ccffe1d36..101a5216a 100644 --- a/dependencies64/tbb/include/tbb/internal/_tbb_strings.h +++ b/dependencies64/tbb/include/tbb/internal/_tbb_strings.h @@ -1,5 +1,5 @@ /* - Copyright 2005-2014 Intel Corporation. All Rights Reserved. + Copyright 2005-2015 Intel Corporation. All Rights Reserved. This file is part of Threading Building Blocks. Threading Building Blocks is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License @@ -27,7 +27,7 @@ TBB_STRING_RESOURCE(FLOW_JOIN_NODE_RESERVING, "join_node (reserving)") TBB_STRING_RESOURCE(FLOW_JOIN_NODE_TAG_MATCHING, "join_node (tag_matching)") TBB_STRING_RESOURCE(FLOW_LIMITER_NODE, "limiter_node") TBB_STRING_RESOURCE(FLOW_MULTIFUNCTION_NODE, "multifunction_node") -TBB_STRING_RESOURCE(FLOW_OR_NODE, "or_node") //no longer in use, kept for backward compatibilty +TBB_STRING_RESOURCE(FLOW_OR_NODE, "or_node") //no longer in use, kept for backward compatibility TBB_STRING_RESOURCE(FLOW_OVERWRITE_NODE, "overwrite_node") TBB_STRING_RESOURCE(FLOW_PRIORITY_QUEUE_NODE, "priority_queue_node") TBB_STRING_RESOURCE(FLOW_QUEUE_NODE, "queue_node") @@ -63,3 +63,5 @@ TBB_STRING_RESOURCE(FLOW_OUTPUT_PORT_9, "output_port_9") TBB_STRING_RESOURCE(FLOW_OBJECT_NAME, "object_name") TBB_STRING_RESOURCE(FLOW_NULL, "null") TBB_STRING_RESOURCE(FLOW_INDEXER_NODE, "indexer_node") +TBB_STRING_RESOURCE(FLOW_COMPOSITE_NODE, "composite_node") +TBB_STRING_RESOURCE(FLOW_ASYNC_NODE, "async_node") diff --git a/dependencies64/tbb/include/tbb/internal/_tbb_windef.h b/dependencies64/tbb/include/tbb/internal/_tbb_windef.h index 551dc2b0b..2eddc5280 100644 --- a/dependencies64/tbb/include/tbb/internal/_tbb_windef.h +++ b/dependencies64/tbb/include/tbb/internal/_tbb_windef.h @@ -1,5 +1,5 @@ /* - Copyright 2005-2014 Intel Corporation. All Rights Reserved. + Copyright 2005-2015 Intel Corporation. All Rights Reserved. This file is part of Threading Building Blocks. Threading Building Blocks is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License diff --git a/dependencies64/tbb/include/tbb/internal/_template_helpers.h b/dependencies64/tbb/include/tbb/internal/_template_helpers.h new file mode 100644 index 000000000..dc5cba9ee --- /dev/null +++ b/dependencies64/tbb/include/tbb/internal/_template_helpers.h @@ -0,0 +1,143 @@ +/* + Copyright 2005-2015 Intel Corporation. All Rights Reserved. + + This file is part of Threading Building Blocks. Threading Building Blocks is free software; + you can redistribute it and/or modify it under the terms of the GNU General Public License + version 2 as published by the Free Software Foundation. Threading Building Blocks is + distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the + implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + See the GNU General Public License for more details. You should have received a copy of + the GNU General Public License along with Threading Building Blocks; if not, write to the + Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + As a special exception, you may use this file as part of a free software library without + restriction. Specifically, if other files instantiate templates or use macros or inline + functions from this file, or you compile this file and link it with other files to produce + an executable, this file does not by itself cause the resulting executable to be covered + by the GNU General Public License. This exception does not however invalidate any other + reasons why the executable file might be covered by the GNU General Public License. +*/ + +#ifndef __TBB_template_helpers_H +#define __TBB_template_helpers_H + +#include + +namespace tbb { namespace internal { + +//! Enables one or the other code branches +template struct enable_if {}; +template struct enable_if { typedef T type; }; + +//! Strips its template type argument from cv- and ref-qualifiers +template struct strip { typedef T type; }; +template struct strip { typedef T type; }; +template struct strip { typedef T type; }; +template struct strip { typedef T type; }; +template struct strip { typedef T type; }; +template struct strip { typedef T type; }; +template struct strip { typedef T type; }; +template struct strip { typedef T type; }; +#if __TBB_CPP11_RVALUE_REF_PRESENT +template struct strip { typedef T type; }; +template struct strip { typedef T type; }; +template struct strip { typedef T type; }; +template struct strip { typedef T type; }; +#endif +//! Specialization for arrays converts to a corresponding pointer +template struct strip { typedef T* type; }; +template struct strip { typedef const T* type; }; +template struct strip { typedef volatile T* type; }; +template struct strip { typedef const volatile T* type; }; + +//! Detects whether two given types are the same +template struct is_same_type { static const bool value = false; }; +template struct is_same_type { static const bool value = true; }; + +template struct is_ref { static const bool value = false; }; +template struct is_ref { static const bool value = true; }; + +#if __TBB_CPP11_RVALUE_REF_PRESENT && __TBB_CPP11_VARIADIC_TEMPLATES_PRESENT + +//! Allows to store a function parameter pack as a variable and later pass it to another function +template< typename... Types > +struct stored_pack; + +template<> +struct stored_pack<> +{ + typedef stored_pack<> pack_type; + stored_pack() {} + + // Friend front-end functions + template< typename F, typename Pack > friend void call( F&& f, Pack&& p ); + template< typename Ret, typename F, typename Pack > friend Ret call_and_return( F&& f, Pack&& p ); + +protected: + // Ideally, ref-qualified non-static methods would be used, + // but that would greatly reduce the set of compilers where it works. + template< typename Ret, typename F, typename... Preceding > + static Ret call( F&& f, const pack_type& /*pack*/, Preceding&&... params ) { + return std::forward(f)( std::forward(params)... ); + } + template< typename Ret, typename F, typename... Preceding > + static Ret call( F&& f, pack_type&& /*pack*/, Preceding&&... params ) { + return std::forward(f)( std::forward(params)... ); + } +}; + +template< typename T, typename... Types > +struct stored_pack : stored_pack +{ + typedef stored_pack pack_type; + typedef stored_pack pack_remainder; + // Since lifetime of original values is out of control, copies should be made. + // Thus references should be stripped away from the deduced type. + typename strip::type leftmost_value; + + // Here rvalue references act in the same way as forwarding references, + // as long as class template parameters were deduced via forwarding references. + stored_pack( T&& t, Types&&... types ) + : pack_remainder(std::forward(types)...), leftmost_value(std::forward(t)) {} + + // Friend front-end functions + template< typename F, typename Pack > friend void call( F&& f, Pack&& p ); + template< typename Ret, typename F, typename Pack > friend Ret call_and_return( F&& f, Pack&& p ); + +protected: + template< typename Ret, typename F, typename... Preceding > + static Ret call( F&& f, const pack_type& pack, Preceding&&... params ) { + return pack_remainder::template call( + std::forward(f), static_cast(pack), + std::forward(params)... , pack.leftmost_value + ); + } + template< typename Ret, typename F, typename... Preceding > + static Ret call( F&& f, pack_type&& pack, Preceding&&... params ) { + return pack_remainder::template call( + std::forward(f), static_cast(pack), + std::forward(params)... , std::move(pack.leftmost_value) + ); + } +}; + +//! Calls the given function with arguments taken from a stored_pack +template< typename F, typename Pack > +void call( F&& f, Pack&& p ) { + strip::type::template call( std::forward(f), std::forward(p) ); +} + +template< typename Ret, typename F, typename Pack > +Ret call_and_return( F&& f, Pack&& p ) { + return strip::type::template call( std::forward(f), std::forward(p) ); +} + +template< typename... Types > +stored_pack save_pack( Types&&... types ) { + return stored_pack( std::forward(types)... ); +} + +#endif /* __TBB_CPP11_RVALUE_REF_PRESENT && __TBB_CPP11_VARIADIC_TEMPLATES_PRESENT */ +} } // namespace internal, namespace tbb + +#endif /* __TBB_template_helpers_H */ diff --git a/dependencies64/tbb/include/tbb/internal/_x86_eliding_mutex_impl.h b/dependencies64/tbb/include/tbb/internal/_x86_eliding_mutex_impl.h index d73877aa8..4b549396e 100644 --- a/dependencies64/tbb/include/tbb/internal/_x86_eliding_mutex_impl.h +++ b/dependencies64/tbb/include/tbb/internal/_x86_eliding_mutex_impl.h @@ -1,5 +1,5 @@ /* - Copyright 2005-2014 Intel Corporation. All Rights Reserved. + Copyright 2005-2015 Intel Corporation. All Rights Reserved. This file is part of Threading Building Blocks. Threading Building Blocks is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License diff --git a/dependencies64/tbb/include/tbb/internal/_x86_rtm_rw_mutex_impl.h b/dependencies64/tbb/include/tbb/internal/_x86_rtm_rw_mutex_impl.h index 9fb8c82f3..6b4fbff75 100644 --- a/dependencies64/tbb/include/tbb/internal/_x86_rtm_rw_mutex_impl.h +++ b/dependencies64/tbb/include/tbb/internal/_x86_rtm_rw_mutex_impl.h @@ -1,5 +1,5 @@ /* - Copyright 2005-2014 Intel Corporation. All Rights Reserved. + Copyright 2005-2015 Intel Corporation. All Rights Reserved. This file is part of Threading Building Blocks. Threading Building Blocks is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License diff --git a/dependencies64/tbb/include/tbb/machine/gcc_armv7.h b/dependencies64/tbb/include/tbb/machine/gcc_armv7.h index 83f5c55e6..6fa8536f9 100644 --- a/dependencies64/tbb/include/tbb/machine/gcc_armv7.h +++ b/dependencies64/tbb/include/tbb/machine/gcc_armv7.h @@ -1,5 +1,5 @@ /* - Copyright 2005-2014 Intel Corporation. All Rights Reserved. + Copyright 2005-2015 Intel Corporation. All Rights Reserved. This file is part of Threading Building Blocks. Threading Building Blocks is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License diff --git a/dependencies64/tbb/include/tbb/machine/gcc_generic.h b/dependencies64/tbb/include/tbb/machine/gcc_generic.h index be80ed47f..257af9657 100644 --- a/dependencies64/tbb/include/tbb/machine/gcc_generic.h +++ b/dependencies64/tbb/include/tbb/machine/gcc_generic.h @@ -1,5 +1,5 @@ /* - Copyright 2005-2014 Intel Corporation. All Rights Reserved. + Copyright 2005-2015 Intel Corporation. All Rights Reserved. This file is part of Threading Building Blocks. Threading Building Blocks is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License diff --git a/dependencies64/tbb/include/tbb/machine/gcc_ia32_common.h b/dependencies64/tbb/include/tbb/machine/gcc_ia32_common.h index 1c4dad0f5..e11ca11b4 100644 --- a/dependencies64/tbb/include/tbb/machine/gcc_ia32_common.h +++ b/dependencies64/tbb/include/tbb/machine/gcc_ia32_common.h @@ -1,5 +1,5 @@ /* - Copyright 2005-2014 Intel Corporation. All Rights Reserved. + Copyright 2005-2015 Intel Corporation. All Rights Reserved. This file is part of Threading Building Blocks. Threading Building Blocks is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License @@ -53,6 +53,18 @@ static inline void __TBB_machine_pause( int32_t delay ) { #define __TBB_Pause(V) __TBB_machine_pause(V) #endif /* !__TBB_Pause */ +namespace tbb { namespace internal { typedef uint64_t machine_tsc_t; } } +static inline tbb::internal::machine_tsc_t __TBB_machine_time_stamp() { +#if __INTEL_COMPILER + return _rdtsc(); +#else + tbb::internal::uint32_t hi, lo; + __asm__ __volatile__("rdtsc" : "=d"(hi), "=a"(lo)); + return (tbb::internal::machine_tsc_t( hi ) << 32) | lo; +#endif +} +#define __TBB_time_stamp() __TBB_machine_time_stamp() + // API to retrieve/update FPU control setting #ifndef __TBB_CPU_CTL_ENV_PRESENT #define __TBB_CPU_CTL_ENV_PRESENT 1 diff --git a/dependencies64/tbb/include/tbb/machine/gcc_itsx.h b/dependencies64/tbb/include/tbb/machine/gcc_itsx.h index 87971659a..af1b53017 100644 --- a/dependencies64/tbb/include/tbb/machine/gcc_itsx.h +++ b/dependencies64/tbb/include/tbb/machine/gcc_itsx.h @@ -1,5 +1,5 @@ /* - Copyright 2005-2014 Intel Corporation. All Rights Reserved. + Copyright 2005-2015 Intel Corporation. All Rights Reserved. This file is part of Threading Building Blocks. Threading Building Blocks is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License diff --git a/dependencies64/tbb/include/tbb/machine/ibm_aix51.h b/dependencies64/tbb/include/tbb/machine/ibm_aix51.h index 57dfeb336..65be8dc86 100644 --- a/dependencies64/tbb/include/tbb/machine/ibm_aix51.h +++ b/dependencies64/tbb/include/tbb/machine/ibm_aix51.h @@ -1,5 +1,5 @@ /* - Copyright 2005-2014 Intel Corporation. All Rights Reserved. + Copyright 2005-2015 Intel Corporation. All Rights Reserved. This file is part of Threading Building Blocks. Threading Building Blocks is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License diff --git a/dependencies64/tbb/include/tbb/machine/icc_generic.h b/dependencies64/tbb/include/tbb/machine/icc_generic.h index c31a5a3d5..bd2091886 100644 --- a/dependencies64/tbb/include/tbb/machine/icc_generic.h +++ b/dependencies64/tbb/include/tbb/machine/icc_generic.h @@ -1,5 +1,5 @@ /* - Copyright 2005-2014 Intel Corporation. All Rights Reserved. + Copyright 2005-2015 Intel Corporation. All Rights Reserved. This file is part of Threading Building Blocks. Threading Building Blocks is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License @@ -46,6 +46,7 @@ #define __TBB_ENDIANNESS __TBB_ENDIAN_LITTLE //__TBB_compiler_fence() defined just in case, as it seems not to be used on its own anywhere else +#ifndef __TBB_compiler_fence #if _MSC_VER //TODO: any way to use same intrinsics on windows and linux? #pragma intrinsic(_ReadWriteBarrier) @@ -53,6 +54,7 @@ #else #define __TBB_compiler_fence() __asm__ __volatile__("": : :"memory") #endif +#endif #ifndef __TBB_full_memory_fence #if _MSC_VER @@ -64,7 +66,9 @@ #endif #endif +#ifndef __TBB_control_consistency_helper #define __TBB_control_consistency_helper() __TBB_compiler_fence() +#endif namespace tbb { namespace internal { //TODO: is there any way to reuse definition of memory_order enum from ICC instead of copy paste. diff --git a/dependencies64/tbb/include/tbb/machine/linux_common.h b/dependencies64/tbb/include/tbb/machine/linux_common.h index 53eeeafc3..7d64e3a3f 100644 --- a/dependencies64/tbb/include/tbb/machine/linux_common.h +++ b/dependencies64/tbb/include/tbb/machine/linux_common.h @@ -1,5 +1,5 @@ /* - Copyright 2005-2014 Intel Corporation. All Rights Reserved. + Copyright 2005-2015 Intel Corporation. All Rights Reserved. This file is part of Threading Building Blocks. Threading Building Blocks is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License diff --git a/dependencies64/tbb/include/tbb/machine/linux_ia32.h b/dependencies64/tbb/include/tbb/machine/linux_ia32.h index 27def2ff5..fecbe02f5 100644 --- a/dependencies64/tbb/include/tbb/machine/linux_ia32.h +++ b/dependencies64/tbb/include/tbb/machine/linux_ia32.h @@ -1,5 +1,5 @@ /* - Copyright 2005-2014 Intel Corporation. All Rights Reserved. + Copyright 2005-2015 Intel Corporation. All Rights Reserved. This file is part of Threading Building Blocks. Threading Building Blocks is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License diff --git a/dependencies64/tbb/include/tbb/machine/linux_ia64.h b/dependencies64/tbb/include/tbb/machine/linux_ia64.h index a9f386acc..b7d2f1c3e 100644 --- a/dependencies64/tbb/include/tbb/machine/linux_ia64.h +++ b/dependencies64/tbb/include/tbb/machine/linux_ia64.h @@ -1,5 +1,5 @@ /* - Copyright 2005-2014 Intel Corporation. All Rights Reserved. + Copyright 2005-2015 Intel Corporation. All Rights Reserved. This file is part of Threading Building Blocks. Threading Building Blocks is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License diff --git a/dependencies64/tbb/include/tbb/machine/linux_intel64.h b/dependencies64/tbb/include/tbb/machine/linux_intel64.h index 6fe018b83..f63b91621 100644 --- a/dependencies64/tbb/include/tbb/machine/linux_intel64.h +++ b/dependencies64/tbb/include/tbb/machine/linux_intel64.h @@ -1,5 +1,5 @@ /* - Copyright 2005-2014 Intel Corporation. All Rights Reserved. + Copyright 2005-2015 Intel Corporation. All Rights Reserved. This file is part of Threading Building Blocks. Threading Building Blocks is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License diff --git a/dependencies64/tbb/include/tbb/machine/mac_ppc.h b/dependencies64/tbb/include/tbb/machine/mac_ppc.h index 2f12c9817..f1d8e6799 100644 --- a/dependencies64/tbb/include/tbb/machine/mac_ppc.h +++ b/dependencies64/tbb/include/tbb/machine/mac_ppc.h @@ -1,5 +1,5 @@ /* - Copyright 2005-2014 Intel Corporation. All Rights Reserved. + Copyright 2005-2015 Intel Corporation. All Rights Reserved. This file is part of Threading Building Blocks. Threading Building Blocks is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License diff --git a/dependencies64/tbb/include/tbb/machine/macos_common.h b/dependencies64/tbb/include/tbb/machine/macos_common.h index dffcea5d7..05cfd7419 100644 --- a/dependencies64/tbb/include/tbb/machine/macos_common.h +++ b/dependencies64/tbb/include/tbb/machine/macos_common.h @@ -1,5 +1,5 @@ /* - Copyright 2005-2014 Intel Corporation. All Rights Reserved. + Copyright 2005-2015 Intel Corporation. All Rights Reserved. This file is part of Threading Building Blocks. Threading Building Blocks is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License diff --git a/dependencies64/tbb/include/tbb/machine/mic_common.h b/dependencies64/tbb/include/tbb/machine/mic_common.h index 1f522da1f..1d4f71d94 100644 --- a/dependencies64/tbb/include/tbb/machine/mic_common.h +++ b/dependencies64/tbb/include/tbb/machine/mic_common.h @@ -1,5 +1,5 @@ /* - Copyright 2005-2014 Intel Corporation. All Rights Reserved. + Copyright 2005-2015 Intel Corporation. All Rights Reserved. This file is part of Threading Building Blocks. Threading Building Blocks is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License @@ -45,10 +45,6 @@ #include #define __TBB_Yield() sched_yield() -// low-level timing intrinsic and its type -#define __TBB_machine_time_stamp() _rdtsc() -typedef uint64_t machine_tsc_t; - /** Specifics **/ #define __TBB_STEALING_ABORT_ON_CONTENTION 1 #define __TBB_YIELD2P 1 diff --git a/dependencies64/tbb/include/tbb/machine/msvc_armv7.h b/dependencies64/tbb/include/tbb/machine/msvc_armv7.h index b96511c75..de9b02e32 100644 --- a/dependencies64/tbb/include/tbb/machine/msvc_armv7.h +++ b/dependencies64/tbb/include/tbb/machine/msvc_armv7.h @@ -1,5 +1,5 @@ /* - Copyright 2005-2014 Intel Corporation. All Rights Reserved. + Copyright 2005-2015 Intel Corporation. All Rights Reserved. This file is part of Threading Building Blocks. Threading Building Blocks is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License diff --git a/dependencies64/tbb/include/tbb/machine/msvc_ia32_common.h b/dependencies64/tbb/include/tbb/machine/msvc_ia32_common.h index 184c3dac3..f8dd3ab9e 100644 --- a/dependencies64/tbb/include/tbb/machine/msvc_ia32_common.h +++ b/dependencies64/tbb/include/tbb/machine/msvc_ia32_common.h @@ -1,5 +1,5 @@ /* - Copyright 2005-2014 Intel Corporation. All Rights Reserved. + Copyright 2005-2015 Intel Corporation. All Rights Reserved. This file is part of Threading Building Blocks. Threading Building Blocks is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License @@ -18,43 +18,98 @@ reasons why the executable file might be covered by the GNU General Public License. */ -#ifndef __TBB_machine_msvc_ia32_common_H +#if !defined(__TBB_machine_H) || defined(__TBB_machine_msvc_ia32_common_H) +#error Do not #include this internal file directly; use public TBB headers instead. +#endif + #define __TBB_machine_msvc_ia32_common_H #include -//TODO: consider moving this macro to tbb_config.h and used there MSVC asm is used +//TODO: consider moving this macro to tbb_config.h and using where MSVC asm is used #if !_M_X64 || __INTEL_COMPILER #define __TBB_X86_MSVC_INLINE_ASM_AVAILABLE 1 - - #if _M_X64 - #define __TBB_r(reg_name) r##reg_name - #else - #define __TBB_r(reg_name) e##reg_name - #endif #else //MSVC in x64 mode does not accept inline assembler #define __TBB_X86_MSVC_INLINE_ASM_AVAILABLE 0 + #define __TBB_NO_X86_MSVC_INLINE_ASM_MSG "The compiler being used is not supported (outdated?)" +#endif + +#if _M_X64 + #define __TBB_r(reg_name) r##reg_name + #define __TBB_W(name) name##64 + namespace tbb { namespace internal { namespace msvc_intrinsics { + typedef __int64 word; + }}} +#else + #define __TBB_r(reg_name) e##reg_name + #define __TBB_W(name) name + namespace tbb { namespace internal { namespace msvc_intrinsics { + typedef long word; + }}} +#endif + +#if _MSC_VER>=1600 && (!__INTEL_COMPILER || __INTEL_COMPILER>=1310) + // S is the operand size in bytes, B is the suffix for intrinsics for that size + #define __TBB_MACHINE_DEFINE_ATOMICS(S,B,T,U) \ + __pragma(intrinsic( _InterlockedCompareExchange##B )) \ + static inline T __TBB_machine_cmpswp##S ( volatile void * ptr, U value, U comparand ) { \ + return _InterlockedCompareExchange##B ( (T*)ptr, value, comparand ); \ + } \ + __pragma(intrinsic( _InterlockedExchangeAdd##B )) \ + static inline T __TBB_machine_fetchadd##S ( volatile void * ptr, U addend ) { \ + return _InterlockedExchangeAdd##B ( (T*)ptr, addend ); \ + } \ + __pragma(intrinsic( _InterlockedExchange##B )) \ + static inline T __TBB_machine_fetchstore##S ( volatile void * ptr, U value ) { \ + return _InterlockedExchange##B ( (T*)ptr, value ); \ + } + + // Atomic intrinsics for 1, 2, and 4 bytes are available for x86 & x64 + __TBB_MACHINE_DEFINE_ATOMICS(1,8,char,__int8) + __TBB_MACHINE_DEFINE_ATOMICS(2,16,short,__int16) + __TBB_MACHINE_DEFINE_ATOMICS(4,,long,__int32) + + #if __TBB_WORDSIZE==8 + __TBB_MACHINE_DEFINE_ATOMICS(8,64,__int64,__int64) + #endif + + #undef __TBB_MACHINE_DEFINE_ATOMICS + #define __TBB_ATOMIC_PRIMITIVES_DEFINED +#endif /*_MSC_VER>=1600*/ + +#if _MSC_VER>=1300 || __INTEL_COMPILER>=1100 + #pragma intrinsic(_ReadWriteBarrier) + #pragma intrinsic(_mm_mfence) + #define __TBB_compiler_fence() _ReadWriteBarrier() + #define __TBB_full_memory_fence() _mm_mfence() +#elif __TBB_X86_MSVC_INLINE_ASM_AVAILABLE + #define __TBB_compiler_fence() __asm { __asm nop } + #define __TBB_full_memory_fence() __asm { __asm mfence } +#else + #error Unsupported compiler; define __TBB_{control,acquire,release}_consistency_helper to support it #endif -#define __TBB_NO_X86_MSVC_INLINE_ASM_MSG "The compiler being used is not supported (outdated?)" +#define __TBB_control_consistency_helper() __TBB_compiler_fence() +#define __TBB_acquire_consistency_helper() __TBB_compiler_fence() +#define __TBB_release_consistency_helper() __TBB_compiler_fence() -#if (_MSC_VER >= 1300) || (__INTEL_COMPILER) //Use compiler intrinsic when available - #define __TBB_PAUSE_USE_INTRINSIC 1 +#if (_MSC_VER>=1300) || (__INTEL_COMPILER) #pragma intrinsic(_mm_pause) - namespace tbb { namespace internal { namespace intrinsics { namespace msvc { - static inline void __TBB_machine_pause (uintptr_t delay ) { + namespace tbb { namespace internal { namespace msvc_intrinsics { + static inline void pause (uintptr_t delay ) { for (;delay>0; --delay ) _mm_pause(); } - }}}} + }}} + #define __TBB_Pause(V) tbb::internal::msvc_intrinsics::pause(V) + #define __TBB_SINGLE_PAUSE _mm_pause() #else #if !__TBB_X86_MSVC_INLINE_ASM_AVAILABLE #error __TBB_NO_X86_MSVC_INLINE_ASM_MSG #endif - - namespace tbb { namespace internal { namespace inline_asm { namespace msvc { - static inline void __TBB_machine_pause (uintptr_t delay ) { + namespace tbb { namespace internal { namespace msvc_inline_asm + static inline void pause (uintptr_t delay ) { _asm { mov __TBB_r(ax), delay @@ -65,52 +120,29 @@ } return; } - }}}} -#endif - -static inline void __TBB_machine_pause (uintptr_t delay ){ - #if __TBB_PAUSE_USE_INTRINSIC - tbb::internal::intrinsics::msvc::__TBB_machine_pause(delay); - #else - tbb::internal::inline_asm::msvc::__TBB_machine_pause(delay); - #endif -} - -//TODO: move this function to windows_api.h or to place where it is used -#if (_MSC_VER<1400) && (!_WIN64) && (__TBB_X86_MSVC_INLINE_ASM_AVAILABLE) - static inline void* __TBB_machine_get_current_teb () { - void* pteb; - __asm mov eax, fs:[0x18] - __asm mov pteb, eax - return pteb; - } + }}} + #define __TBB_Pause(V) tbb::internal::msvc_inline_asm::pause(V) + #define __TBB_SINGLE_PAUSE __asm pause #endif -#if ( _MSC_VER>=1400 && !defined(__INTEL_COMPILER) ) || (__INTEL_COMPILER>=1200) +#if (_MSC_VER>=1400 && !__INTEL_COMPILER) || (__INTEL_COMPILER>=1200) // MSVC did not have this intrinsic prior to VC8. // ICL 11.1 fails to compile a TBB example if __TBB_Log2 uses the intrinsic. - #define __TBB_LOG2_USE_BSR_INTRINSIC 1 - #if _M_X64 - #define __TBB_BSR_INTRINSIC _BitScanReverse64 - #else - #define __TBB_BSR_INTRINSIC _BitScanReverse - #endif - #pragma intrinsic(__TBB_BSR_INTRINSIC) - - namespace tbb { namespace internal { namespace intrinsics { namespace msvc { - inline uintptr_t __TBB_machine_lg( uintptr_t i ){ + #pragma intrinsic(__TBB_W(_BitScanReverse)) + namespace tbb { namespace internal { namespace msvc_intrinsics { + static inline uintptr_t lg_bsr( uintptr_t i ){ unsigned long j; - __TBB_BSR_INTRINSIC( &j, i ); + __TBB_W(_BitScanReverse)( &j, i ); return j; } - }}}} + }}} + #define __TBB_Log2(V) tbb::internal::msvc_intrinsics::lg_bsr(V) #else #if !__TBB_X86_MSVC_INLINE_ASM_AVAILABLE #error __TBB_NO_X86_MSVC_INLINE_ASM_MSG #endif - - namespace tbb { namespace internal { namespace inline_asm { namespace msvc { - inline uintptr_t __TBB_machine_lg( uintptr_t i ){ + namespace tbb { namespace internal { namespace msvc_inline_asm { + static inline uintptr_t lg_bsr( uintptr_t i ){ uintptr_t j; __asm { @@ -119,16 +151,55 @@ static inline void __TBB_machine_pause (uintptr_t delay ){ } return j; } - }}}} + }}} + #define __TBB_Log2(V) tbb::internal::msvc_inline_asm::lg_bsr(V) #endif -static inline intptr_t __TBB_machine_lg( uintptr_t i ) { -#if __TBB_LOG2_USE_BSR_INTRINSIC - return tbb::internal::intrinsics::msvc::__TBB_machine_lg(i); +#if _MSC_VER>=1400 + #pragma intrinsic(__TBB_W(_InterlockedOr)) + #pragma intrinsic(__TBB_W(_InterlockedAnd)) + namespace tbb { namespace internal { namespace msvc_intrinsics { + static inline void lock_or( volatile void *operand, intptr_t addend ){ + __TBB_W(_InterlockedOr)((volatile word*)operand, addend); + } + static inline void lock_and( volatile void *operand, intptr_t addend ){ + __TBB_W(_InterlockedAnd)((volatile word*)operand, addend); + } + }}} + #define __TBB_AtomicOR(P,V) tbb::internal::msvc_intrinsics::lock_or(P,V) + #define __TBB_AtomicAND(P,V) tbb::internal::msvc_intrinsics::lock_and(P,V) #else - return tbb::internal::inline_asm::msvc::__TBB_machine_lg(i); + #if !__TBB_X86_MSVC_INLINE_ASM_AVAILABLE + #error __TBB_NO_X86_MSVC_INLINE_ASM_MSG + #endif + namespace tbb { namespace internal { namespace msvc_inline_asm { + static inline void lock_or( volatile void *operand, __int32 addend ) { + __asm + { + mov eax, addend + mov edx, [operand] + lock or [edx], eax + } + } + static inline void lock_and( volatile void *operand, __int32 addend ) { + __asm + { + mov eax, addend + mov edx, [operand] + lock and [edx], eax + } + } + }}} + #define __TBB_AtomicOR(P,V) tbb::internal::msvc_inline_asm::lock_or(P,V) + #define __TBB_AtomicAND(P,V) tbb::internal::msvc_inline_asm::lock_and(P,V) #endif + +#pragma intrinsic(__rdtsc) +namespace tbb { namespace internal { typedef uint64_t machine_tsc_t; } } +static inline tbb::internal::machine_tsc_t __TBB_machine_time_stamp() { + return __rdtsc(); } +#define __TBB_time_stamp() __TBB_machine_time_stamp() // API to retrieve/update FPU control setting #define __TBB_CPU_CTL_ENV_PRESENT 1 @@ -182,21 +253,16 @@ extern "C" __declspec(dllimport) int __stdcall SwitchToThread( void ); #define __TBB_Yield() std::this_thread::yield() #endif -#define __TBB_Pause(V) __TBB_machine_pause(V) -#define __TBB_Log2(V) __TBB_machine_lg(V) - #undef __TBB_r +#undef __TBB_W +#undef __TBB_word extern "C" { __int8 __TBB_EXPORTED_FUNC __TBB_machine_try_lock_elided (volatile void* ptr); void __TBB_EXPORTED_FUNC __TBB_machine_unlock_elided (volatile void* ptr); // 'pause' instruction aborts HLE/RTM transactions -#if __TBB_PAUSE_USE_INTRINSIC - inline static void __TBB_machine_try_lock_elided_cancel() { _mm_pause(); } -#else - inline static void __TBB_machine_try_lock_elided_cancel() { _asm pause; } -#endif + inline static void __TBB_machine_try_lock_elided_cancel() { __TBB_SINGLE_PAUSE; } #if __TBB_TSX_INTRINSICS_PRESENT #define __TBB_machine_is_in_transaction _xtest @@ -212,5 +278,3 @@ extern "C" { void __TBB_EXPORTED_FUNC __TBB_machine_transaction_conflict_abort(); #endif /* __TBB_TSX_INTRINSICS_PRESENT */ } - -#endif /* __TBB_machine_msvc_ia32_common_H */ diff --git a/dependencies64/tbb/include/tbb/machine/sunos_sparc.h b/dependencies64/tbb/include/tbb/machine/sunos_sparc.h index 1d4fbf744..a6d8cbdec 100644 --- a/dependencies64/tbb/include/tbb/machine/sunos_sparc.h +++ b/dependencies64/tbb/include/tbb/machine/sunos_sparc.h @@ -1,5 +1,5 @@ /* - Copyright 2005-2014 Intel Corporation. All Rights Reserved. + Copyright 2005-2015 Intel Corporation. All Rights Reserved. This file is part of Threading Building Blocks. Threading Building Blocks is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License diff --git a/dependencies64/tbb/include/tbb/machine/windows_api.h b/dependencies64/tbb/include/tbb/machine/windows_api.h index c0ccc24c5..32386e5ba 100644 --- a/dependencies64/tbb/include/tbb/machine/windows_api.h +++ b/dependencies64/tbb/include/tbb/machine/windows_api.h @@ -1,5 +1,5 @@ /* - Copyright 2005-2014 Intel Corporation. All Rights Reserved. + Copyright 2005-2015 Intel Corporation. All Rights Reserved. This file is part of Threading Building Blocks. Threading Building Blocks is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License diff --git a/dependencies64/tbb/include/tbb/machine/windows_ia32.h b/dependencies64/tbb/include/tbb/machine/windows_ia32.h index 3a38634c9..f0d647b72 100644 --- a/dependencies64/tbb/include/tbb/machine/windows_ia32.h +++ b/dependencies64/tbb/include/tbb/machine/windows_ia32.h @@ -1,5 +1,5 @@ /* - Copyright 2005-2014 Intel Corporation. All Rights Reserved. + Copyright 2005-2015 Intel Corporation. All Rights Reserved. This file is part of Threading Building Blocks. Threading Building Blocks is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License @@ -24,33 +24,17 @@ #define __TBB_machine_windows_ia32_H -#include "msvc_ia32_common.h" - -#define __TBB_WORDSIZE 4 -#define __TBB_ENDIANNESS __TBB_ENDIAN_LITTLE - -#if __INTEL_COMPILER && (__INTEL_COMPILER < 1100) - #define __TBB_compiler_fence() __asm { __asm nop } - #define __TBB_full_memory_fence() __asm { __asm mfence } -#elif _MSC_VER >= 1300 || __INTEL_COMPILER - #pragma intrinsic(_ReadWriteBarrier) - #pragma intrinsic(_mm_mfence) - #define __TBB_compiler_fence() _ReadWriteBarrier() - #define __TBB_full_memory_fence() _mm_mfence() -#else - #error Unsupported compiler - need to define __TBB_{control,acquire,release}_consistency_helper to support it -#endif - -#define __TBB_control_consistency_helper() __TBB_compiler_fence() -#define __TBB_acquire_consistency_helper() __TBB_compiler_fence() -#define __TBB_release_consistency_helper() __TBB_compiler_fence() - #if defined(_MSC_VER) && !defined(__INTEL_COMPILER) // Workaround for overzealous compiler warnings in /Wp64 mode #pragma warning (push) #pragma warning (disable: 4244 4267) #endif +#include "msvc_ia32_common.h" + +#define __TBB_WORDSIZE 4 +#define __TBB_ENDIANNESS __TBB_ENDIAN_LITTLE + extern "C" { __int64 __TBB_EXPORTED_FUNC __TBB_machine_cmpswp8 (volatile void *ptr, __int64 value, __int64 comparand ); __int64 __TBB_EXPORTED_FUNC __TBB_machine_fetchadd8 (volatile void *ptr, __int64 addend ); @@ -59,7 +43,8 @@ extern "C" { __int64 __TBB_EXPORTED_FUNC __TBB_machine_load8 (const volatile void *ptr); } -//TODO: use _InterlockedXXX intrinsics as they available since VC 2005 +#ifndef __TBB_ATOMIC_PRIMITIVES_DEFINED + #define __TBB_MACHINE_DEFINE_ATOMICS(S,T,U,A,C) \ static inline T __TBB_machine_cmpswp##S ( volatile void * ptr, U value, U comparand ) { \ T result; \ @@ -108,26 +93,7 @@ __TBB_MACHINE_DEFINE_ATOMICS(4, ptrdiff_t, ptrdiff_t, eax, ecx) #undef __TBB_MACHINE_DEFINE_ATOMICS -static inline void __TBB_machine_OR( volatile void *operand, __int32 addend ) { - __asm - { - mov eax, addend - mov edx, [operand] - lock or [edx], eax - } -} - -static inline void __TBB_machine_AND( volatile void *operand, __int32 addend ) { - __asm - { - mov eax, addend - mov edx, [operand] - lock and [edx], eax - } -} - -#define __TBB_AtomicOR(P,V) __TBB_machine_OR(P,V) -#define __TBB_AtomicAND(P,V) __TBB_machine_AND(P,V) +#endif /*__TBB_ATOMIC_PRIMITIVES_DEFINED*/ //TODO: Check if it possible and profitable for IA-32 architecture on (Linux and Windows) //to use of 64-bit load/store via floating point registers together with full fence @@ -141,4 +107,3 @@ static inline void __TBB_machine_AND( volatile void *operand, __int32 addend ) { #if defined(_MSC_VER) && !defined(__INTEL_COMPILER) #pragma warning (pop) #endif // warnings 4244, 4267 are back - diff --git a/dependencies64/tbb/include/tbb/machine/windows_intel64.h b/dependencies64/tbb/include/tbb/machine/windows_intel64.h index 03795efd9..8c04fe4c9 100644 --- a/dependencies64/tbb/include/tbb/machine/windows_intel64.h +++ b/dependencies64/tbb/include/tbb/machine/windows_intel64.h @@ -1,5 +1,5 @@ /* - Copyright 2005-2014 Intel Corporation. All Rights Reserved. + Copyright 2005-2015 Intel Corporation. All Rights Reserved. This file is part of Threading Building Blocks. Threading Building Blocks is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License @@ -27,34 +27,13 @@ #define __TBB_WORDSIZE 8 #define __TBB_ENDIANNESS __TBB_ENDIAN_LITTLE -#include #include "msvc_ia32_common.h" -//TODO: Use _InterlockedXXX16 intrinsics for 2 byte operations -#if !__INTEL_COMPILER - #pragma intrinsic(_InterlockedOr64) - #pragma intrinsic(_InterlockedAnd64) - #pragma intrinsic(_InterlockedCompareExchange) - #pragma intrinsic(_InterlockedCompareExchange64) - #pragma intrinsic(_InterlockedExchangeAdd) - #pragma intrinsic(_InterlockedExchangeAdd64) - #pragma intrinsic(_InterlockedExchange) - #pragma intrinsic(_InterlockedExchange64) -#endif /* !(__INTEL_COMPILER) */ - -#if __INTEL_COMPILER && (__INTEL_COMPILER < 1100) - #define __TBB_compiler_fence() __asm { __asm nop } - #define __TBB_full_memory_fence() __asm { __asm mfence } -#elif _MSC_VER >= 1300 || __INTEL_COMPILER - #pragma intrinsic(_ReadWriteBarrier) - #pragma intrinsic(_mm_mfence) - #define __TBB_compiler_fence() _ReadWriteBarrier() - #define __TBB_full_memory_fence() _mm_mfence() -#endif +#ifndef __TBB_ATOMIC_PRIMITIVES_DEFINED -#define __TBB_control_consistency_helper() __TBB_compiler_fence() -#define __TBB_acquire_consistency_helper() __TBB_compiler_fence() -#define __TBB_release_consistency_helper() __TBB_compiler_fence() +#include +#pragma intrinsic(_InterlockedCompareExchange,_InterlockedExchangeAdd,_InterlockedExchange) +#pragma intrinsic(_InterlockedCompareExchange64,_InterlockedExchangeAdd64,_InterlockedExchange64) // ATTENTION: if you ever change argument types in machine-specific primitives, // please take care of atomic_word<> specializations in tbb/atomic.h @@ -87,19 +66,9 @@ inline __int64 __TBB_machine_fetchstore8 (volatile void *ptr, __int64 value ) { return _InterlockedExchange64( (__int64*)ptr, value ); } +#endif /*__TBB_ATOMIC_PRIMITIVES_DEFINED*/ + #define __TBB_USE_FETCHSTORE_AS_FULL_FENCED_STORE 1 #define __TBB_USE_GENERIC_HALF_FENCED_LOAD_STORE 1 #define __TBB_USE_GENERIC_RELAXED_LOAD_STORE 1 #define __TBB_USE_GENERIC_SEQUENTIAL_CONSISTENCY_LOAD_STORE 1 - -inline void __TBB_machine_OR( volatile void *operand, intptr_t addend ) { - _InterlockedOr64((__int64*)operand, addend); -} - -inline void __TBB_machine_AND( volatile void *operand, intptr_t addend ) { - _InterlockedAnd64((__int64*)operand, addend); -} - -#define __TBB_AtomicOR(P,V) __TBB_machine_OR(P,V) -#define __TBB_AtomicAND(P,V) __TBB_machine_AND(P,V) - diff --git a/dependencies64/tbb/include/tbb/machine/xbox360_ppc.h b/dependencies64/tbb/include/tbb/machine/xbox360_ppc.h index 148e5b1d0..489362783 100644 --- a/dependencies64/tbb/include/tbb/machine/xbox360_ppc.h +++ b/dependencies64/tbb/include/tbb/machine/xbox360_ppc.h @@ -1,5 +1,5 @@ /* - Copyright 2005-2014 Intel Corporation. All Rights Reserved. + Copyright 2005-2015 Intel Corporation. All Rights Reserved. This file is part of Threading Building Blocks. Threading Building Blocks is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License @@ -94,7 +94,7 @@ static inline int __TBB_XBOX360_DetectNumberOfWorkers() ((__TBB_XBOX360_HARDWARE_THREAD_MASK >> 2) & 1) + ((__TBB_XBOX360_HARDWARE_THREAD_MASK >> 3) & 1) + ((__TBB_XBOX360_HARDWARE_THREAD_MASK >> 4) & 1) + - ((__TBB_XBOX360_HARDWARE_THREAD_MASK >> 5) & 1) + 1; // +1 accomodates for the master thread + ((__TBB_XBOX360_HARDWARE_THREAD_MASK >> 5) & 1) + 1; // +1 accommodates for the master thread } static inline int __TBB_XBOX360_GetHardwareThreadIndex(int workerThreadIndex) diff --git a/dependencies64/tbb/include/tbb/memory_pool.h b/dependencies64/tbb/include/tbb/memory_pool.h index 47b8e1b2c..1ddec4f46 100644 --- a/dependencies64/tbb/include/tbb/memory_pool.h +++ b/dependencies64/tbb/include/tbb/memory_pool.h @@ -1,5 +1,5 @@ /* - Copyright 2005-2014 Intel Corporation. All Rights Reserved. + Copyright 2005-2015 Intel Corporation. All Rights Reserved. This file is part of Threading Building Blocks. Threading Building Blocks is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License @@ -28,6 +28,9 @@ #include "scalable_allocator.h" #include // std::bad_alloc +#include // std::runtime_error, std::invalid_argument +// required in C++03 to construct std::runtime_error and std::invalid_argument +#include #if __TBB_ALLOCATOR_CONSTRUCT_VARIADIC #include // std::forward #endif @@ -114,7 +117,10 @@ public: //! Allocate space for n objects. pointer allocate( size_type n, const void* /*hint*/ = 0) { - return static_cast( my_pool->malloc( n*sizeof(value_type) ) ); + pointer p = static_cast( my_pool->malloc( n*sizeof(value_type) ) ); + if (!p) + tbb::internal::throw_exception(std::bad_alloc()); + return p; } //! Free previously allocated block of memory. void deallocate( pointer p, size_type ) { @@ -216,7 +222,8 @@ memory_pool::memory_pool(const Alloc &src) : my_alloc(src) { rml::MemPoolPolicy args(allocate_request, deallocate_request, sizeof(typename Alloc::value_type)); rml::MemPoolError res = rml::pool_create_v1(intptr_t(this), &args, &my_pool); - if( res!=rml::POOL_OK ) __TBB_THROW(std::bad_alloc()); + if (res!=rml::POOL_OK) + tbb::internal::throw_exception(std::runtime_error("Can't create pool")); } template void *memory_pool::allocate_request(intptr_t pool_id, size_t & bytes) { @@ -246,10 +253,13 @@ int memory_pool::deallocate_request(intptr_t pool_id, void* raw_ptr, size #pragma warning (pop) #endif inline fixed_pool::fixed_pool(void *buf, size_t size) : my_buffer(buf), my_size(size) { - if( !buf || !size ) __TBB_THROW(std::bad_alloc()); + if (!buf || !size) + // TODO: improve support for mode with exceptions disabled + tbb::internal::throw_exception(std::invalid_argument("Zero in parameter is invalid")); rml::MemPoolPolicy args(allocate_request, 0, size, /*fixedPool=*/true); rml::MemPoolError res = rml::pool_create_v1(intptr_t(this), &args, &my_pool); - if( res!=rml::POOL_OK ) __TBB_THROW(std::bad_alloc()); + if (res!=rml::POOL_OK) + tbb::internal::throw_exception(std::runtime_error("Can't create pool")); } inline void *fixed_pool::allocate_request(intptr_t pool_id, size_t & bytes) { fixed_pool &self = *reinterpret_cast(pool_id); diff --git a/dependencies64/tbb/include/tbb/mutex.h b/dependencies64/tbb/include/tbb/mutex.h index 32340f8b1..df328fdea 100644 --- a/dependencies64/tbb/include/tbb/mutex.h +++ b/dependencies64/tbb/include/tbb/mutex.h @@ -1,5 +1,5 @@ /* - Copyright 2005-2014 Intel Corporation. All Rights Reserved. + Copyright 2005-2015 Intel Corporation. All Rights Reserved. This file is part of Threading Building Blocks. Threading Building Blocks is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License diff --git a/dependencies64/tbb/include/tbb/null_mutex.h b/dependencies64/tbb/include/tbb/null_mutex.h index 240e9bdcc..78a16b79b 100644 --- a/dependencies64/tbb/include/tbb/null_mutex.h +++ b/dependencies64/tbb/include/tbb/null_mutex.h @@ -1,5 +1,5 @@ /* - Copyright 2005-2014 Intel Corporation. All Rights Reserved. + Copyright 2005-2015 Intel Corporation. All Rights Reserved. This file is part of Threading Building Blocks. Threading Building Blocks is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License diff --git a/dependencies64/tbb/include/tbb/null_rw_mutex.h b/dependencies64/tbb/include/tbb/null_rw_mutex.h index 813f79f39..390a85b29 100644 --- a/dependencies64/tbb/include/tbb/null_rw_mutex.h +++ b/dependencies64/tbb/include/tbb/null_rw_mutex.h @@ -1,5 +1,5 @@ /* - Copyright 2005-2014 Intel Corporation. All Rights Reserved. + Copyright 2005-2015 Intel Corporation. All Rights Reserved. This file is part of Threading Building Blocks. Threading Building Blocks is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License diff --git a/dependencies64/tbb/include/tbb/parallel_do.h b/dependencies64/tbb/include/tbb/parallel_do.h index 8173a9715..1bae6b425 100644 --- a/dependencies64/tbb/include/tbb/parallel_do.h +++ b/dependencies64/tbb/include/tbb/parallel_do.h @@ -1,5 +1,5 @@ /* - Copyright 2005-2014 Intel Corporation. All Rights Reserved. + Copyright 2005-2015 Intel Corporation. All Rights Reserved. This file is part of Threading Building Blocks. Threading Building Blocks is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License @@ -22,6 +22,7 @@ #define __TBB_parallel_do_H #include "internal/_range_iterator.h" +#include "internal/_template_helpers.h" #include "task.h" #include "aligned_space.h" #include @@ -32,26 +33,6 @@ namespace tbb { namespace internal { template class parallel_do_feeder_impl; template class do_group_task; - - //! Strips its template type argument from 'cv' and '&' qualifiers - template - struct strip { typedef T type; }; - template - struct strip { typedef T type; }; - template - struct strip { typedef T type; }; - template - struct strip { typedef T type; }; - template - struct strip { typedef T type; }; - // Most of the compilers remove cv-qualifiers from non-reference function argument types. - // But unfortunately there are those that don't. - template - struct strip { typedef T type; }; - template - struct strip { typedef T type; }; - template - struct strip { typedef T type; }; } // namespace internal //! @endcond diff --git a/dependencies64/tbb/include/tbb/parallel_for.h b/dependencies64/tbb/include/tbb/parallel_for.h index 4dc499cf0..dd6eb9959 100644 --- a/dependencies64/tbb/include/tbb/parallel_for.h +++ b/dependencies64/tbb/include/tbb/parallel_for.h @@ -1,5 +1,5 @@ /* - Copyright 2005-2014 Intel Corporation. All Rights Reserved. + Copyright 2005-2015 Intel Corporation. All Rights Reserved. This file is part of Threading Building Blocks. Threading Building Blocks is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License diff --git a/dependencies64/tbb/include/tbb/parallel_for_each.h b/dependencies64/tbb/include/tbb/parallel_for_each.h index c7dc39f4d..e0527dde6 100644 --- a/dependencies64/tbb/include/tbb/parallel_for_each.h +++ b/dependencies64/tbb/include/tbb/parallel_for_each.h @@ -1,5 +1,5 @@ /* - Copyright 2005-2014 Intel Corporation. All Rights Reserved. + Copyright 2005-2015 Intel Corporation. All Rights Reserved. This file is part of Threading Building Blocks. Threading Building Blocks is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License diff --git a/dependencies64/tbb/include/tbb/parallel_invoke.h b/dependencies64/tbb/include/tbb/parallel_invoke.h index bc055850a..14c07643f 100644 --- a/dependencies64/tbb/include/tbb/parallel_invoke.h +++ b/dependencies64/tbb/include/tbb/parallel_invoke.h @@ -1,5 +1,5 @@ /* - Copyright 2005-2014 Intel Corporation. All Rights Reserved. + Copyright 2005-2015 Intel Corporation. All Rights Reserved. This file is part of Threading Building Blocks. Threading Building Blocks is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License diff --git a/dependencies64/tbb/include/tbb/parallel_reduce.h b/dependencies64/tbb/include/tbb/parallel_reduce.h index 17fba2019..b0e93574e 100644 --- a/dependencies64/tbb/include/tbb/parallel_reduce.h +++ b/dependencies64/tbb/include/tbb/parallel_reduce.h @@ -1,5 +1,5 @@ /* - Copyright 2005-2014 Intel Corporation. All Rights Reserved. + Copyright 2005-2015 Intel Corporation. All Rights Reserved. This file is part of Threading Building Blocks. Threading Building Blocks is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License diff --git a/dependencies64/tbb/include/tbb/parallel_scan.h b/dependencies64/tbb/include/tbb/parallel_scan.h index e9d8c692e..716338bab 100644 --- a/dependencies64/tbb/include/tbb/parallel_scan.h +++ b/dependencies64/tbb/include/tbb/parallel_scan.h @@ -1,5 +1,5 @@ /* - Copyright 2005-2014 Intel Corporation. All Rights Reserved. + Copyright 2005-2015 Intel Corporation. All Rights Reserved. This file is part of Threading Building Blocks. Threading Building Blocks is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License diff --git a/dependencies64/tbb/include/tbb/parallel_sort.h b/dependencies64/tbb/include/tbb/parallel_sort.h index 1d33c1f70..34f373a75 100644 --- a/dependencies64/tbb/include/tbb/parallel_sort.h +++ b/dependencies64/tbb/include/tbb/parallel_sort.h @@ -1,5 +1,5 @@ /* - Copyright 2005-2014 Intel Corporation. All Rights Reserved. + Copyright 2005-2015 Intel Corporation. All Rights Reserved. This file is part of Threading Building Blocks. Threading Building Blocks is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License diff --git a/dependencies64/tbb/include/tbb/parallel_while.h b/dependencies64/tbb/include/tbb/parallel_while.h index a1db83413..bf49953d2 100644 --- a/dependencies64/tbb/include/tbb/parallel_while.h +++ b/dependencies64/tbb/include/tbb/parallel_while.h @@ -1,5 +1,5 @@ /* - Copyright 2005-2014 Intel Corporation. All Rights Reserved. + Copyright 2005-2015 Intel Corporation. All Rights Reserved. This file is part of Threading Building Blocks. Threading Building Blocks is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License diff --git a/dependencies64/tbb/include/tbb/partitioner.h b/dependencies64/tbb/include/tbb/partitioner.h index c1a24d269..656d7368e 100644 --- a/dependencies64/tbb/include/tbb/partitioner.h +++ b/dependencies64/tbb/include/tbb/partitioner.h @@ -1,5 +1,5 @@ /* - Copyright 2005-2014 Intel Corporation. All Rights Reserved. + Copyright 2005-2015 Intel Corporation. All Rights Reserved. This file is part of Threading Building Blocks. Threading Building Blocks is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License @@ -43,7 +43,7 @@ #endif #if __TBB_DEFINE_MIC #define __TBB_NONUNIFORM_TASK_CREATION 1 -#ifdef __TBB_machine_time_stamp +#ifdef __TBB_time_stamp #define __TBB_USE_MACHINE_TIME_STAMPS 1 #define __TBB_task_duration() __TBB_STATIC_THRESHOLD #endif // __TBB_machine_time_stamp @@ -52,6 +52,7 @@ #include "task.h" #include "aligned_space.h" #include "atomic.h" +#include "internal/_template_helpers.h" #if defined(_MSC_VER) && !defined(__INTEL_COMPILER) // Workaround for overzealous compiler warnings @@ -334,10 +335,6 @@ struct adaptive_partition_type_base : partition_type_base { depth_t max_depth() { return my_max_depth; } }; -//! Helper that enables one or the other code branches (see example in is_splittable_in_proportion) -template struct enable_if { typedef T type; }; -template struct enable_if { }; - //! Class determines whether template parameter has static boolean constant //! 'is_splittable_in_proportion' initialized with value of 'true' or not. /** If template parameter has such field that has been initialized with non-zero @@ -366,7 +363,7 @@ class affinity_partition_type : public adaptive_partition_type_base 0, NULL); return false; } diff --git a/dependencies64/tbb/include/tbb/pipeline.h b/dependencies64/tbb/include/tbb/pipeline.h index 3a1d3d899..2d7c38558 100644 --- a/dependencies64/tbb/include/tbb/pipeline.h +++ b/dependencies64/tbb/include/tbb/pipeline.h @@ -1,5 +1,5 @@ /* - Copyright 2005-2014 Intel Corporation. All Rights Reserved. + Copyright 2005-2015 Intel Corporation. All Rights Reserved. This file is part of Threading Building Blocks. Threading Building Blocks is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License @@ -595,6 +595,7 @@ class filter_t { template friend filter_t operator& (const filter_t& , const filter_t& ); public: + // TODO: add move-constructors, move-assignment, etc. where C++11 is available. filter_t() : root(NULL) {} filter_t( const filter_t& rhs ) : root(rhs.root) { if( root ) root->add_ref(); diff --git a/dependencies64/tbb/include/tbb/queuing_mutex.h b/dependencies64/tbb/include/tbb/queuing_mutex.h index 7986b0b45..44bd306bc 100644 --- a/dependencies64/tbb/include/tbb/queuing_mutex.h +++ b/dependencies64/tbb/include/tbb/queuing_mutex.h @@ -1,5 +1,5 @@ /* - Copyright 2005-2014 Intel Corporation. All Rights Reserved. + Copyright 2005-2015 Intel Corporation. All Rights Reserved. This file is part of Threading Building Blocks. Threading Building Blocks is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License diff --git a/dependencies64/tbb/include/tbb/queuing_rw_mutex.h b/dependencies64/tbb/include/tbb/queuing_rw_mutex.h index 76df16290..de1fc0fda 100644 --- a/dependencies64/tbb/include/tbb/queuing_rw_mutex.h +++ b/dependencies64/tbb/include/tbb/queuing_rw_mutex.h @@ -1,5 +1,5 @@ /* - Copyright 2005-2014 Intel Corporation. All Rights Reserved. + Copyright 2005-2015 Intel Corporation. All Rights Reserved. This file is part of Threading Building Blocks. Threading Building Blocks is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License diff --git a/dependencies64/tbb/include/tbb/reader_writer_lock.h b/dependencies64/tbb/include/tbb/reader_writer_lock.h index 60d24f3dc..86b1af4aa 100644 --- a/dependencies64/tbb/include/tbb/reader_writer_lock.h +++ b/dependencies64/tbb/include/tbb/reader_writer_lock.h @@ -1,5 +1,5 @@ /* - Copyright 2005-2014 Intel Corporation. All Rights Reserved. + Copyright 2005-2015 Intel Corporation. All Rights Reserved. This file is part of Threading Building Blocks. Threading Building Blocks is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License diff --git a/dependencies64/tbb/include/tbb/recursive_mutex.h b/dependencies64/tbb/include/tbb/recursive_mutex.h index 1e41d90a5..f430a3838 100644 --- a/dependencies64/tbb/include/tbb/recursive_mutex.h +++ b/dependencies64/tbb/include/tbb/recursive_mutex.h @@ -1,5 +1,5 @@ /* - Copyright 2005-2014 Intel Corporation. All Rights Reserved. + Copyright 2005-2015 Intel Corporation. All Rights Reserved. This file is part of Threading Building Blocks. Threading Building Blocks is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License diff --git a/dependencies64/tbb/include/tbb/runtime_loader.h b/dependencies64/tbb/include/tbb/runtime_loader.h index f5cd412ec..5dc8bab76 100644 --- a/dependencies64/tbb/include/tbb/runtime_loader.h +++ b/dependencies64/tbb/include/tbb/runtime_loader.h @@ -1,5 +1,5 @@ /* - Copyright 2005-2014 Intel Corporation. All Rights Reserved. + Copyright 2005-2015 Intel Corporation. All Rights Reserved. This file is part of Threading Building Blocks. Threading Building Blocks is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License diff --git a/dependencies64/tbb/include/tbb/scalable_allocator.h b/dependencies64/tbb/include/tbb/scalable_allocator.h index 3683aa27f..42472cee1 100644 --- a/dependencies64/tbb/include/tbb/scalable_allocator.h +++ b/dependencies64/tbb/include/tbb/scalable_allocator.h @@ -1,5 +1,5 @@ /* - Copyright 2005-2014 Intel Corporation. All Rights Reserved. + Copyright 2005-2015 Intel Corporation. All Rights Reserved. This file is part of Threading Building Blocks. Threading Building Blocks is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License @@ -129,6 +129,7 @@ namespace rml { class MemoryPool; typedef void *(*rawAllocType)(intptr_t pool_id, size_t &bytes); +// returns non-zero in case of error typedef int (*rawFreeType)(intptr_t pool_id, void* raw_ptr, size_t raw_bytes); /* @@ -191,6 +192,7 @@ void *pool_aligned_malloc(MemoryPool* mPool, size_t size, size_t alignment); void *pool_aligned_realloc(MemoryPool* mPool, void *ptr, size_t size, size_t alignment); bool pool_reset(MemoryPool* memPool); bool pool_free(MemoryPool *memPool, void *object); +MemoryPool *pool_identify(void *object); } #include /* To use new with the placement argument */ @@ -216,6 +218,23 @@ namespace tbb { #pragma warning (disable: 4100) #endif +//! @cond INTERNAL +namespace internal { + +#if TBB_USE_EXCEPTIONS +// forward declaration is for inlining prevention +template __TBB_NOINLINE( void throw_exception(const E &e) ); +#endif + +// keep throw in a separate function to prevent code bloat +template +void throw_exception(const E &e) { + __TBB_THROW(e); +} + +} // namespace internal +//! @endcond + //! Meets "allocator" requirements of ISO C++ Standard, Section 20.1.5 /** The members are ordered the same way they are in section 20.4.1 of the ISO C++ standard. @@ -243,7 +262,10 @@ public: //! Allocate space for n objects. pointer allocate( size_type n, const void* /*hint*/ =0 ) { - return static_cast( scalable_malloc( n * sizeof(value_type) ) ); + pointer p = static_cast( scalable_malloc( n * sizeof(value_type) ) ); + if (!p) + internal::throw_exception(std::bad_alloc()); + return p; } //! Free previously allocated block of memory diff --git a/dependencies64/tbb/include/tbb/spin_mutex.h b/dependencies64/tbb/include/tbb/spin_mutex.h index a7ed31be4..70ddbd8af 100644 --- a/dependencies64/tbb/include/tbb/spin_mutex.h +++ b/dependencies64/tbb/include/tbb/spin_mutex.h @@ -1,5 +1,5 @@ /* - Copyright 2005-2014 Intel Corporation. All Rights Reserved. + Copyright 2005-2015 Intel Corporation. All Rights Reserved. This file is part of Threading Building Blocks. Threading Building Blocks is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License diff --git a/dependencies64/tbb/include/tbb/spin_rw_mutex.h b/dependencies64/tbb/include/tbb/spin_rw_mutex.h index 61151c179..593a4abe0 100644 --- a/dependencies64/tbb/include/tbb/spin_rw_mutex.h +++ b/dependencies64/tbb/include/tbb/spin_rw_mutex.h @@ -1,5 +1,5 @@ /* - Copyright 2005-2014 Intel Corporation. All Rights Reserved. + Copyright 2005-2015 Intel Corporation. All Rights Reserved. This file is part of Threading Building Blocks. Threading Building Blocks is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License diff --git a/dependencies64/tbb/include/tbb/task.h b/dependencies64/tbb/include/tbb/task.h index 5dabcd97a..a416f3e27 100644 --- a/dependencies64/tbb/include/tbb/task.h +++ b/dependencies64/tbb/include/tbb/task.h @@ -1,5 +1,5 @@ /* - Copyright 2005-2014 Intel Corporation. All Rights Reserved. + Copyright 2005-2015 Intel Corporation. All Rights Reserved. This file is part of Threading Building Blocks. Threading Building Blocks is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License @@ -23,6 +23,7 @@ #include "tbb_stddef.h" #include "tbb_machine.h" +#include "tbb_profiling.h" #include typedef struct ___itt_caller *__itt_caller; @@ -689,12 +690,23 @@ public: #endif /* TBB_USE_THREADING_TOOLS||TBB_USE_ASSERT */ } - //! Atomically increment reference count and returns its old value. + //! Atomically increment reference count. /** Has acquire semantics */ void increment_ref_count() { __TBB_FetchAndIncrementWacquire( &prefix().ref_count ); } + //! Atomically adds to reference count and returns its new value. + /** Has release-acquire semantics */ + int add_ref_count( int count ) { + internal::call_itt_notify( internal::releasing, &prefix().ref_count ); + internal::reference_count k = count+__TBB_FetchAndAddW( &prefix().ref_count, count ); + __TBB_ASSERT( k>=0, "task's reference count underflowed" ); + if( k==0 ) + internal::call_itt_notify( internal::acquired, &prefix().ref_count ); + return int(k); + } + //! Atomically decrement reference count and returns its new value. /** Has release semantics. */ int decrement_ref_count() { @@ -766,7 +778,7 @@ public: //! sets parent task pointer to specified value void set_parent(task* p) { #if __TBB_TASK_GROUP_CONTEXT - __TBB_ASSERT(prefix().context == p->prefix().context, "The tasks must be in the same context"); + __TBB_ASSERT(!p || prefix().context == p->prefix().context, "The tasks must be in the same context"); #endif prefix().parent = p; } @@ -925,7 +937,18 @@ public: *next_ptr = &task; next_ptr = &task.prefix().next; } - +#if __TBB_TODO + // TODO: add this method and implement&document the local execution ordering. See more in generic_scheduler::local_spawn + //! Push task onto front of list (FIFO local execution, like individual spawning in the same order). + void push_front( task& task ) { + if( empty() ) { + push_back(task); + } else { + task.prefix().next = first; + first = &task; + } + } +#endif //! Pop the front task from the list. task& pop_front() { __TBB_ASSERT( !empty(), "attempt to pop item from empty task_list" ); diff --git a/dependencies64/tbb/include/tbb/task_arena.h b/dependencies64/tbb/include/tbb/task_arena.h index 893763e56..2f26d94ec 100644 --- a/dependencies64/tbb/include/tbb/task_arena.h +++ b/dependencies64/tbb/include/tbb/task_arena.h @@ -1,5 +1,5 @@ /* - Copyright 2005-2014 Intel Corporation. All Rights Reserved. + Copyright 2005-2015 Intel Corporation. All Rights Reserved. This file is part of Threading Building Blocks. Threading Building Blocks is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License diff --git a/dependencies64/tbb/include/tbb/task_group.h b/dependencies64/tbb/include/tbb/task_group.h index 4cbe7d55b..b3fd2fa1e 100644 --- a/dependencies64/tbb/include/tbb/task_group.h +++ b/dependencies64/tbb/include/tbb/task_group.h @@ -1,5 +1,5 @@ /* - Copyright 2005-2014 Intel Corporation. All Rights Reserved. + Copyright 2005-2015 Intel Corporation. All Rights Reserved. This file is part of Threading Building Blocks. Threading Building Blocks is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License diff --git a/dependencies64/tbb/include/tbb/task_scheduler_init.h b/dependencies64/tbb/include/tbb/task_scheduler_init.h index b49bddb89..e98abbfa9 100644 --- a/dependencies64/tbb/include/tbb/task_scheduler_init.h +++ b/dependencies64/tbb/include/tbb/task_scheduler_init.h @@ -1,5 +1,5 @@ /* - Copyright 2005-2014 Intel Corporation. All Rights Reserved. + Copyright 2005-2015 Intel Corporation. All Rights Reserved. This file is part of Threading Building Blocks. Threading Building Blocks is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License diff --git a/dependencies64/tbb/include/tbb/task_scheduler_observer.h b/dependencies64/tbb/include/tbb/task_scheduler_observer.h index 6c8ac4da0..4865dd378 100644 --- a/dependencies64/tbb/include/tbb/task_scheduler_observer.h +++ b/dependencies64/tbb/include/tbb/task_scheduler_observer.h @@ -1,5 +1,5 @@ /* - Copyright 2005-2014 Intel Corporation. All Rights Reserved. + Copyright 2005-2015 Intel Corporation. All Rights Reserved. This file is part of Threading Building Blocks. Threading Building Blocks is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License diff --git a/dependencies64/tbb/include/tbb/tbb.h b/dependencies64/tbb/include/tbb/tbb.h index 8a8a8dfa8..f5ce04009 100644 --- a/dependencies64/tbb/include/tbb/tbb.h +++ b/dependencies64/tbb/include/tbb/tbb.h @@ -1,5 +1,5 @@ /* - Copyright 2005-2014 Intel Corporation. All Rights Reserved. + Copyright 2005-2015 Intel Corporation. All Rights Reserved. This file is part of Threading Building Blocks. Threading Building Blocks is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License @@ -51,6 +51,9 @@ #include "critical_section.h" #include "enumerable_thread_specific.h" #include "flow_graph.h" +#if TBB_PREVIEW_GLOBAL_CONTROL +#include "global_control.h" +#endif #include "mutex.h" #include "null_mutex.h" #include "null_rw_mutex.h" diff --git a/dependencies64/tbb/include/tbb/tbb_allocator.h b/dependencies64/tbb/include/tbb/tbb_allocator.h index d9480f2ad..33d09de7d 100644 --- a/dependencies64/tbb/include/tbb/tbb_allocator.h +++ b/dependencies64/tbb/include/tbb/tbb_allocator.h @@ -1,5 +1,5 @@ /* - Copyright 2005-2014 Intel Corporation. All Rights Reserved. + Copyright 2005-2015 Intel Corporation. All Rights Reserved. This file is part of Threading Building Blocks. Threading Building Blocks is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License diff --git a/dependencies64/tbb/include/tbb/tbb_config.h b/dependencies64/tbb/include/tbb/tbb_config.h index fad3400ce..112c768b6 100644 --- a/dependencies64/tbb/include/tbb/tbb_config.h +++ b/dependencies64/tbb/include/tbb/tbb_config.h @@ -1,5 +1,5 @@ /* - Copyright 2005-2014 Intel Corporation. All Rights Reserved. + Copyright 2005-2015 Intel Corporation. All Rights Reserved. This file is part of Threading Building Blocks. Threading Building Blocks is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License @@ -29,6 +29,11 @@ - known compiler/platform issues **/ +/* This macro marks incomplete code or comments describing ideas which are considered for the future. + * See also for plain comment with TODO and FIXME marks for small improvement opportunities. + */ +#define __TBB_TODO 0 + /*Check which standard library we use on OS X.*/ /*__TBB_SYMBOL is defined only while processing exported symbols list where C++ is not allowed.*/ #if !defined(__TBB_SYMBOL) && __APPLE__ @@ -150,12 +155,13 @@ #define __TBB_CPP11_STD_BEGIN_END_PRESENT (_MSC_VER >= 1700 || __GXX_EXPERIMENTAL_CXX0X__ && __INTEL_COMPILER >= 1310 && (__TBB_GCC_VERSION >= 40600 || _LIBCPP_VERSION)) #define __TBB_CPP11_AUTO_PRESENT (_MSC_VER >= 1600 || __GXX_EXPERIMENTAL_CXX0X__ && __INTEL_COMPILER >= 1210) #define __TBB_CPP11_DECLTYPE_PRESENT (_MSC_VER >= 1600 || __GXX_EXPERIMENTAL_CXX0X__ && __INTEL_COMPILER >= 1210) + #define __TBB_CPP11_LAMBDAS_PRESENT (__INTEL_CXX11_MODE__ && __INTEL_COMPILER >= 1200) #elif __clang__ //TODO: these options need to be rechecked /** on OS X* the only way to get C++11 is to use clang. For library features (e.g. exception_ptr) libc++ is also * required. So there is no need to check GCC version for clang**/ - #define __TBB_CPP11_VARIADIC_TEMPLATES_PRESENT (__has_feature(__cxx_variadic_templates__)) - #define __TBB_CPP11_RVALUE_REF_PRESENT (__has_feature(__cxx_rvalue_references__) && (__TBB_GCC_VERSION >= 40300 || _LIBCPP_VERSION)) + #define __TBB_CPP11_VARIADIC_TEMPLATES_PRESENT (__has_feature(__cxx_variadic_templates__)) + #define __TBB_CPP11_RVALUE_REF_PRESENT (__has_feature(__cxx_rvalue_references__) && (__TBB_GCC_VERSION >= 40300 || _LIBCPP_VERSION)) /** TODO: extend exception_ptr related conditions to cover libstdc++ **/ #define __TBB_EXCEPTION_PTR_PRESENT (__cplusplus >= 201103L && _LIBCPP_VERSION) #define __TBB_STATIC_ASSERT_PRESENT __has_feature(__cxx_static_assert__) @@ -174,6 +180,7 @@ #define __TBB_CPP11_STD_BEGIN_END_PRESENT (__has_feature(__cxx_range_for__) && _LIBCPP_VERSION) #define __TBB_CPP11_AUTO_PRESENT __has_feature(__cxx_auto_type__) #define __TBB_CPP11_DECLTYPE_PRESENT __has_feature(__cxx_decltype__) + #define __TBB_CPP11_LAMBDAS_PRESENT __has_feature(cxx_lambdas) #elif __GNUC__ #define __TBB_CPP11_VARIADIC_TEMPLATES_PRESENT __GXX_EXPERIMENTAL_CXX0X__ #define __TBB_CPP11_RVALUE_REF_PRESENT __GXX_EXPERIMENTAL_CXX0X__ @@ -191,6 +198,7 @@ #define __TBB_CPP11_STD_BEGIN_END_PRESENT (__GXX_EXPERIMENTAL_CXX0X__ && __TBB_GCC_VERSION >= 40600) #define __TBB_CPP11_AUTO_PRESENT (__GXX_EXPERIMENTAL_CXX0X__ && __TBB_GCC_VERSION >= 40400) #define __TBB_CPP11_DECLTYPE_PRESENT (__GXX_EXPERIMENTAL_CXX0X__ && __TBB_GCC_VERSION >= 40400) + #define __TBB_CPP11_LAMBDAS_PRESENT (__GXX_EXPERIMENTAL_CXX0X__ && __TBB_GCC_VERSION >= 40500) #elif _MSC_VER #define __TBB_CPP11_VARIADIC_TEMPLATES_PRESENT (_MSC_VER >= 1800) #define __TBB_CPP11_RVALUE_REF_PRESENT (_MSC_VER >= 1600) @@ -200,10 +208,11 @@ #define __TBB_INITIALIZER_LISTS_PRESENT (_MSC_VER >= 1800) #define __TBB_CONSTEXPR_PRESENT 0 #define __TBB_DEFAULTED_AND_DELETED_FUNC_PRESENT (_MSC_VER >= 1800) - #define __TBB_NOEXCEPT_PRESENT 0 /*for _MSC_VER == 1800*/ + #define __TBB_NOEXCEPT_PRESENT (_MSC_VER >= 1900) #define __TBB_CPP11_STD_BEGIN_END_PRESENT (_MSC_VER >= 1700) #define __TBB_CPP11_AUTO_PRESENT (_MSC_VER >= 1600) #define __TBB_CPP11_DECLTYPE_PRESENT (_MSC_VER >= 1600) + #define __TBB_CPP11_LAMBDAS_PRESENT (_MSC_VER >= 1600) #else #define __TBB_CPP11_VARIADIC_TEMPLATES_PRESENT 0 #define __TBB_CPP11_RVALUE_REF_PRESENT 0 @@ -217,17 +226,19 @@ #define __TBB_CPP11_STD_BEGIN_END_PRESENT 0 #define __TBB_CPP11_AUTO_PRESENT 0 #define __TBB_CPP11_DECLTYPE_PRESENT 0 + #define __TBB_CPP11_LAMBDAS_PRESENT 0 #endif // C++11 standard library features +#define __TBB_CPP11_VARIADIC_TUPLE_PRESENT (!_MSC_VER || _MSC_VER >=1800) #define __TBB_CPP11_TYPE_PROPERTIES_PRESENT (_LIBCPP_VERSION || _MSC_VER >= 1700) #define __TBB_TR1_TYPE_PROPERTIES_IN_STD_PRESENT (__GXX_EXPERIMENTAL_CXX0X__ && __TBB_GCC_VERSION >= 40300 || _MSC_VER >= 1600) // GCC has a partial support of type properties #define __TBB_CPP11_IS_COPY_CONSTRUCTIBLE_PRESENT (__GXX_EXPERIMENTAL_CXX0X__ && __TBB_GCC_VERSION >= 40700 || __TBB_CPP11_TYPE_PROPERTIES_PRESENT) // In GCC and MSVC, implementation of std::move_if_noexcept is not aligned with noexcept -#define __TBB_MOVE_IF_NOEXCEPT_PRESENT (__GXX_EXPERIMENTAL_CXX0X__ && __TBB_GCC_VERSION >= 40700 || _MSC_VER >= 1800 || __clang__ && _LIBCPP_VERSION && __TBB_NOEXCEPT_PRESENT) +#define __TBB_MOVE_IF_NOEXCEPT_PRESENT (__GXX_EXPERIMENTAL_CXX0X__ && __TBB_GCC_VERSION >= 40700 || _MSC_VER >= 1900 || __clang__ && _LIBCPP_VERSION && __TBB_NOEXCEPT_PRESENT) //TODO: Probably more accurate way is to analyze version of stdlibc++ via__GLIBCXX__ instead of __TBB_GCC_VERSION #define __TBB_ALLOCATOR_TRAITS_PRESENT (__cplusplus >= 201103L && _LIBCPP_VERSION || _MSC_VER >= 1700 || \ __GXX_EXPERIMENTAL_CXX0X__ && __TBB_GCC_VERSION >= 40700 && !(__TBB_GCC_VERSION == 40700 && __TBB_DEFINE_MIC) \ @@ -255,7 +266,8 @@ /* Actually ICC supports gcc __sync_* intrinsics starting 11.1, * but 64 bit support for 32 bit target comes in later ones*/ /* TODO: change the version back to 4.1.2 once macro __TBB_WORD_SIZE become optional */ -#if __TBB_GCC_VERSION >= 40306 || __INTEL_COMPILER >= 1200 +/* Assumed that all clang versions have these gcc compatible intrinsics. */ +#if __TBB_GCC_VERSION >= 40306 || __INTEL_COMPILER >= 1200 || __clang__ /** built-in atomics available in GCC since 4.1.2 **/ #define __TBB_GCC_BUILTIN_ATOMICS_PRESENT 1 #endif @@ -455,13 +467,15 @@ #endif #ifdef _VARIADIC_MAX -#define __TBB_VARIADIC_MAX _VARIADIC_MAX -#else -#if _MSC_VER >= 1700 -#define __TBB_VARIADIC_MAX 5 /* current VS11 setting, may change. */ + #define __TBB_VARIADIC_MAX _VARIADIC_MAX #else -#define __TBB_VARIADIC_MAX 10 -#endif + #if _MSC_VER == 1700 + #define __TBB_VARIADIC_MAX 5 // VS11 setting, issue resolved in VS12 + #elif _MSC_VER == 1600 + #define __TBB_VARIADIC_MAX 10 // VS10 setting + #else + #define __TBB_VARIADIC_MAX 15 + #endif #endif /** __TBB_WIN8UI_SUPPORT enables support of New Windows*8 Store Apps and limit a possibility to load @@ -534,7 +548,7 @@ #define __TBB_SSE_STACK_ALIGNMENT_BROKEN 0 #endif -#if __GNUC__==4 && __GNUC_MINOR__==3 && __GNUC_PATCHLEVEL__==0 +#if __TBB_GCC_VERSION==40300 && !__INTEL_COMPILER && !__clang__ /* GCC of this version may rashly ignore control dependencies */ #define __TBB_GCC_OPTIMIZER_ORDERING_BROKEN 1 #endif @@ -604,7 +618,7 @@ #define __TBB_GCC_CAS8_BUILTIN_INLINING_BROKEN 1 #endif -#if __TBB_x86_32 && (__linux__ || __APPLE__ || _WIN32 || __sun || __ANDROID__) && (__INTEL_COMPILER || (__GNUC__==3 && __GNUC_MINOR__==3 ) || __SUNPRO_CC) +#if __TBB_x86_32 && (__linux__ || __APPLE__ || _WIN32 || __sun || __ANDROID__) && (__INTEL_COMPILER || (__GNUC__==3 && __GNUC_MINOR__==3 )||(__MINGW32__ ) && (__GNUC__==4 && __GNUC_MINOR__==5 ) || __SUNPRO_CC) // Some compilers for IA-32 fail to provide 8-byte alignment of objects on the stack, // even if the object specifies 8-byte alignment. On such platforms, the IA-32 implementation // of 64 bit atomics (e.g. atomic) use different tactics depending upon @@ -629,7 +643,17 @@ // MSVC 2013 and ICC 15 seems do not generate implicit move constructor for empty derived class while should #define __TBB_CPP11_IMPLICIT_MOVE_MEMBERS_GENERATION_FOR_DERIVED_BROKEN (__TBB_CPP11_RVALUE_REF_PRESENT && \ - ( !__INTEL_COMPILER && _MSC_VER && _MSC_VER <=1800 || __INTEL_COMPILER && __INTEL_COMPILER <= 1500 )) + ( !__INTEL_COMPILER && _MSC_VER && _MSC_VER <= 1800 || __INTEL_COMPILER && __INTEL_COMPILER <= 1500 )) + +#define __TBB_CPP11_DECLVAL_BROKEN (_MSC_VER == 1600 || (__GNUC__ && __TBB_GCC_VERSION < 40500) ) + +// Intel C++ compiler has difficulties with copying std::pair with VC11 std::reference_wrapper being a const member +#define __TBB_COPY_FROM_NON_CONST_REF_BROKEN (_MSC_VER == 1700 && __INTEL_COMPILER && __INTEL_COMPILER < 1600) +//The implicit upcasting of the tuple of a reference of a derived class to a base class fails on icc 13.X +//if the system's gcc environment is 4.8 +#if (__INTEL_COMPILER >=1300 && __INTEL_COMPILER <=1310) && __TBB_GCC_VERSION>=40700 && __GXX_EXPERIMENTAL_CXX0X__ + #define __TBB_UPCAST_OF_TUPLE_OF_REF_BROKEN 1 +#endif /** End of __TBB_XXX_BROKEN macro section **/ @@ -643,4 +667,9 @@ #define __TBB_ALLOCATOR_CONSTRUCT_VARIADIC (__TBB_CPP11_VARIADIC_TEMPLATES_PRESENT && __TBB_CPP11_RVALUE_REF_PRESENT) #define __TBB_VARIADIC_PARALLEL_INVOKE (TBB_PREVIEW_VARIADIC_PARALLEL_INVOKE && __TBB_CPP11_VARIADIC_TEMPLATES_PRESENT && __TBB_CPP11_RVALUE_REF_PRESENT) +#define __TBB_FLOW_GRAPH_CPP11_FEATURES (__TBB_CPP11_VARIADIC_TEMPLATES_PRESENT \ + && __TBB_CPP11_RVALUE_REF_PRESENT && __TBB_CPP11_AUTO_PRESENT) \ + && __TBB_CPP11_VARIADIC_TUPLE_PRESENT && !__TBB_UPCAST_OF_TUPLE_OF_REF_BROKEN +#define __TBB_PREVIEW_ASYNC_NODE TBB_PREVIEW_FLOW_GRAPH_NODES +#define __TBB_PREVIEW_OPENCL_NODE __TBB_FLOW_GRAPH_CPP11_FEATURES && TBB_PREVIEW_FLOW_GRAPH_NODES #endif /* __TBB_tbb_config_H */ diff --git a/dependencies64/tbb/include/tbb/tbb_exception.h b/dependencies64/tbb/include/tbb/tbb_exception.h index cfef55ef3..75423d0f8 100644 --- a/dependencies64/tbb/include/tbb/tbb_exception.h +++ b/dependencies64/tbb/include/tbb/tbb_exception.h @@ -1,5 +1,5 @@ /* - Copyright 2005-2014 Intel Corporation. All Rights Reserved. + Copyright 2005-2015 Intel Corporation. All Rights Reserved. This file is part of Threading Building Blocks. Threading Building Blocks is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License diff --git a/dependencies64/tbb/include/tbb/tbb_machine.h b/dependencies64/tbb/include/tbb/tbb_machine.h index 479806529..e82a35af7 100644 --- a/dependencies64/tbb/include/tbb/tbb_machine.h +++ b/dependencies64/tbb/include/tbb/tbb_machine.h @@ -1,5 +1,5 @@ /* - Copyright 2005-2014 Intel Corporation. All Rights Reserved. + Copyright 2005-2015 Intel Corporation. All Rights Reserved. This file is part of Threading Building Blocks. Threading Building Blocks is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License @@ -34,7 +34,7 @@ __TBB_USE_GENERIC_DWORD_FETCH_ADD __TBB_USE_GENERIC_DWORD_FETCH_STORE __TBB_USE_GENERIC_HALF_FENCED_LOAD_STORE - __TBB_USE_GENERIC_FULL_FENCED_LOAD_STORE + __TBB_USE_GENERIC_SEQUENTIAL_CONSISTENCY_LOAD_STORE __TBB_USE_GENERIC_RELAXED_LOAD_STORE __TBB_USE_FETCHSTORE_AS_FULL_FENCED_STORE @@ -351,7 +351,7 @@ namespace internal { //< @cond INTERNAL class atomic_backoff : no_copy { //! Time delay, in units of "pause" instructions. /** Should be equal to approximately the number of "pause" instructions - that take the same time as an context switch. */ + that take the same time as an context switch. Must be a power of two.*/ static const int32_t LOOPS_BEFORE_YIELD = 16; int32_t count; public: @@ -374,10 +374,10 @@ public: } } - // pause for a few times and then return false immediately. + //! Pause for a few times and return false if saturated. bool bounded_pause() { - if( count<=LOOPS_BEFORE_YIELD ) { - __TBB_Pause(count); + __TBB_Pause(count); + if( count inline argument_integer_type modulo_power_of_two(argument_integer_type arg, divisor_integer_type divisor) { - // Divisor is assumed to be a power of two (which is valid for current uses). __TBB_ASSERT( is_power_of_two(divisor), "Divisor should be a power of two" ); return (arg & (divisor - 1)); } -//! A function to determine if "arg is a multiplication of a number and a power of 2". -// i.e. for strictly positive i and j, with j a power of 2, +//! A function to determine if arg is a power of 2 at least as big as another power of 2. +// i.e. for strictly positive i and j, with j being a power of 2, // determines whether i==j< -inline bool is_power_of_two_factor(argument_integer_type arg, divisor_integer_type divisor) { - // Divisor is assumed to be a power of two (which is valid for current uses). - __TBB_ASSERT( is_power_of_two(divisor), "Divisor should be a power of two" ); - return 0 == (arg & (arg - divisor)); +template +inline bool is_power_of_two_at_least(argument_integer_type arg, power2_integer_type power2) { + __TBB_ASSERT( is_power_of_two(power2), "Divisor should be a power of two" ); + return 0 == (arg & (arg - power2)); } //! Utility template function to prevent "unused" warnings by various compilers. @@ -472,12 +470,42 @@ struct select_size_t_constant { #if __TBB_CPP11_RVALUE_REF_PRESENT using std::move; +using std::forward; #elif defined(_LIBCPP_NAMESPACE) -// libc++ defines "pre-C++11 move" similarly to our; use it to avoid name conflicts in some cases. +// libc++ defines "pre-C++11 move and forward" similarly to ours; use it to avoid name conflicts in some cases. using std::_LIBCPP_NAMESPACE::move; +using std::_LIBCPP_NAMESPACE::forward; #else +// It is assumed that cv qualifiers, if any, are part of the deduced type. template T& move( T& x ) { return x; } +template +T& forward( T& x ) { return x; } +#endif /* __TBB_CPP11_RVALUE_REF_PRESENT */ + +// Helper macros to simplify writing templates working with both C++03 and C++11. +#if __TBB_CPP11_RVALUE_REF_PRESENT +#define __TBB_FORWARDING_REF(A) A&& +#else +// It is assumed that cv qualifiers, if any, are part of a deduced type. +// Thus this macro should not be used in public interfaces. +#define __TBB_FORWARDING_REF(A) A& +#endif +#if __TBB_CPP11_VARIADIC_TEMPLATES_PRESENT +#define __TBB_PARAMETER_PACK ... +#define __TBB_PACK_EXPANSION(A) A... +#else +#define __TBB_PARAMETER_PACK +#define __TBB_PACK_EXPANSION(A) A +#endif /* __TBB_CPP11_VARIADIC_TEMPLATES_PRESENT */ + +#if __TBB_CPP11_DECLTYPE_PRESENT +#if __TBB_CPP11_DECLVAL_BROKEN +// Ad-hoc implementation of std::declval +template __TBB_FORWARDING_REF(T) declval() /*noexcept*/; +#else +using std::declval; +#endif #endif template diff --git a/dependencies64/tbb/include/tbb/tbb_thread.h b/dependencies64/tbb/include/tbb/tbb_thread.h index 00ec24709..a28dd7968 100644 --- a/dependencies64/tbb/include/tbb/tbb_thread.h +++ b/dependencies64/tbb/include/tbb/tbb_thread.h @@ -1,5 +1,5 @@ /* - Copyright 2005-2014 Intel Corporation. All Rights Reserved. + Copyright 2005-2015 Intel Corporation. All Rights Reserved. This file is part of Threading Building Blocks. Threading Building Blocks is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License @@ -22,21 +22,29 @@ #define __TBB_tbb_thread_H #include "tbb_stddef.h" + #if _WIN32||_WIN64 #include "machine/windows_api.h" #define __TBB_NATIVE_THREAD_ROUTINE unsigned WINAPI #define __TBB_NATIVE_THREAD_ROUTINE_PTR(r) unsigned (WINAPI* r)( void* ) +namespace tbb { namespace internal { #if __TBB_WIN8UI_SUPPORT -typedef size_t thread_id_type; + typedef size_t thread_id_type; #else // __TBB_WIN8UI_SUPPORT -typedef DWORD thread_id_type; + typedef DWORD thread_id_type; #endif // __TBB_WIN8UI_SUPPORT +}} //namespace tbb::internal #else #define __TBB_NATIVE_THREAD_ROUTINE void* #define __TBB_NATIVE_THREAD_ROUTINE_PTR(r) void* (*r)( void* ) #include +namespace tbb { namespace internal { + typedef pthread_t thread_id_type; +}} //namespace tbb::internal #endif // _WIN32||_WIN64 +#include "atomic.h" +#include "internal/_tbb_hash_compare_impl.h" #include "tick_count.h" #if !TBB_USE_EXCEPTIONS && _MSC_VER @@ -45,6 +53,7 @@ typedef DWORD thread_id_type; #pragma warning (disable: 4530) #endif +#include //for swap #include #if !TBB_USE_EXCEPTIONS && _MSC_VER @@ -222,13 +231,9 @@ namespace internal { }; class tbb_thread_v3::id { -#if _WIN32||_WIN64 thread_id_type my_id; id( thread_id_type id_ ) : my_id(id_) {} -#else - pthread_t my_id; - id( pthread_t id_ ) : my_id(id_) {} -#endif // _WIN32||_WIN64 + friend class tbb_thread_v3; public: id() __TBB_NOEXCEPT(true) : my_id(0) {} @@ -249,6 +254,16 @@ namespace internal { return out; } friend tbb_thread_v3::id __TBB_EXPORTED_FUNC thread_get_id_v3(); + + friend inline size_t tbb_hasher( const tbb_thread_v3::id& id ) { + __TBB_STATIC_ASSERT(sizeof(id.my_id) <= sizeof(size_t), "Implementaion assumes that thread_id_type fits into machine word"); + return tbb::tbb_hasher(id.my_id); + } + + // A workaround for lack of tbb::atomic (which would require id to be POD in C++03). + friend id atomic_compare_and_swap(id& location, const id& value, const id& comparand){ + return as_atomic(location.my_id).compare_and_swap(value.my_id, comparand.my_id); + } }; // tbb_thread_v3::id tbb_thread_v3::id tbb_thread_v3::get_id() const __TBB_NOEXCEPT(true) { @@ -258,6 +273,7 @@ namespace internal { return id(my_handle); #endif // _WIN32||_WIN64 } + void __TBB_EXPORTED_FUNC move_v3( tbb_thread_v3& t1, tbb_thread_v3& t2 ); tbb_thread_v3::id __TBB_EXPORTED_FUNC thread_get_id_v3(); void __TBB_EXPORTED_FUNC thread_yield_v3(); @@ -305,13 +321,9 @@ inline void move( tbb_thread& t1, tbb_thread& t2 ) { } inline void swap( internal::tbb_thread_v3& t1, internal::tbb_thread_v3& t2 ) __TBB_NOEXCEPT(true) { - tbb::tbb_thread::native_handle_type h = t1.my_handle; - t1.my_handle = t2.my_handle; - t2.my_handle = h; + std::swap(t1.my_handle, t2.my_handle); #if _WIN32||_WIN64 - thread_id_type i = t1.my_thread_id; - t1.my_thread_id = t2.my_thread_id; - t2.my_thread_id = i; + std::swap(t1.my_thread_id, t2.my_thread_id); #endif /* _WIN32||_WIN64 */ } diff --git a/dependencies64/tbb/include/tbb/tbbmalloc_proxy.h b/dependencies64/tbb/include/tbb/tbbmalloc_proxy.h index dde395411..81d7a2b01 100644 --- a/dependencies64/tbb/include/tbb/tbbmalloc_proxy.h +++ b/dependencies64/tbb/include/tbb/tbbmalloc_proxy.h @@ -1,5 +1,5 @@ /* - Copyright 2005-2014 Intel Corporation. All Rights Reserved. + Copyright 2005-2015 Intel Corporation. All Rights Reserved. This file is part of Threading Building Blocks. Threading Building Blocks is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License diff --git a/dependencies64/tbb/include/tbb/tick_count.h b/dependencies64/tbb/include/tbb/tick_count.h index b5520f9b0..10f539066 100644 --- a/dependencies64/tbb/include/tbb/tick_count.h +++ b/dependencies64/tbb/include/tbb/tick_count.h @@ -1,5 +1,5 @@ /* - Copyright 2005-2014 Intel Corporation. All Rights Reserved. + Copyright 2005-2015 Intel Corporation. All Rights Reserved. This file is part of Threading Building Blocks. Threading Building Blocks is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License diff --git a/dependencies64/tbb/lib/win32/irml/irml.lib b/dependencies64/tbb/lib/win32/irml/irml.lib deleted file mode 100644 index 304a5f6cb..000000000 Binary files a/dependencies64/tbb/lib/win32/irml/irml.lib and /dev/null differ diff --git a/dependencies64/tbb/lib/win32/irml/irml_debug.lib b/dependencies64/tbb/lib/win32/irml/irml_debug.lib deleted file mode 100644 index c6519fb25..000000000 Binary files a/dependencies64/tbb/lib/win32/irml/irml_debug.lib and /dev/null differ diff --git a/dependencies64/tbb/lib/win32/tbb.def b/dependencies64/tbb/lib/win32/tbb.def index a8eb7ebba..454befcd1 100644 --- a/dependencies64/tbb/lib/win32/tbb.def +++ b/dependencies64/tbb/lib/win32/tbb.def @@ -1,43 +1,413 @@ -; Copyright 2005-2014 Intel Corporation. All Rights Reserved. + +; Copyright 2005-2015 Intel Corporation. All Rights Reserved. +; +; This file is part of Threading Building Blocks. Threading Building Blocks is free software; +; you can redistribute it and/or modify it under the terms of the GNU General Public License +; version 2 as published by the Free Software Foundation. Threading Building Blocks is +; distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the +; implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +; See the GNU General Public License for more details. You should have received a copy of +; the GNU General Public License along with Threading Building Blocks; if not, write to the +; Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +; +; As a special exception, you may use this file as part of a free software library without +; restriction. Specifically, if other files instantiate templates or use macros or inline +; functions from this file, or you compile this file and link it with other files to produce +; an executable, this file does not by itself cause the resulting executable to be covered +; by the GNU General Public License. This exception does not however invalidate any other +; reasons why the executable file might be covered by the GNU General Public License. + +; This file is organized with a section for each .cpp file. +; Each of these sections is in alphabetical order. + +EXPORTS + + + +; Copyright 2005-2015 Intel Corporation. All Rights Reserved. ; -; The source code contained or described herein and all documents related -; to the source code ("Material") are owned by Intel Corporation or its -; suppliers or licensors. Title to the Material remains with Intel -; Corporation or its suppliers and licensors. The Material is protected -; by worldwide copyright laws and treaty provisions. No part of the -; Material may be used, copied, reproduced, modified, published, uploaded, -; posted, transmitted, distributed, or disclosed in any way without -; Intel's prior express written permission. +; This file is part of Threading Building Blocks. Threading Building Blocks is free software; +; you can redistribute it and/or modify it under the terms of the GNU General Public License +; version 2 as published by the Free Software Foundation. Threading Building Blocks is +; distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the +; implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +; See the GNU General Public License for more details. You should have received a copy of +; the GNU General Public License along with Threading Building Blocks; if not, write to the +; Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA ; -; No license under any patent, copyright, trade secret or other -; intellectual property right is granted to or conferred upon you by -; disclosure or delivery of the Materials, either expressly, by -; implication, inducement, estoppel or otherwise. Any license under such -; intellectual property rights must be express and approved by Intel in -; writing. +; As a special exception, you may use this file as part of a free software library without +; restriction. Specifically, if other files instantiate templates or use macros or inline +; functions from this file, or you compile this file and link it with other files to produce +; an executable, this file does not by itself cause the resulting executable to be covered +; by the GNU General Public License. This exception does not however invalidate any other +; reasons why the executable file might be covered by the GNU General Public License. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + -; This file is organized with a section for each .cpp file. -; Each of these sections is in alphabetical order. -EXPORTS -; Copyright 2005-2014 Intel Corporation. All Rights Reserved. -; -; The source code contained or described herein and all documents related -; to the source code ("Material") are owned by Intel Corporation or its -; suppliers or licensors. Title to the Material remains with Intel -; Corporation or its suppliers and licensors. The Material is protected -; by worldwide copyright laws and treaty provisions. No part of the -; Material may be used, copied, reproduced, modified, published, uploaded, -; posted, transmitted, distributed, or disclosed in any way without -; Intel's prior express written permission. -; -; No license under any patent, copyright, trade secret or other -; intellectual property right is granted to or conferred upon you by -; disclosure or delivery of the Materials, either expressly, by -; implication, inducement, estoppel or otherwise. Any license under such -; intellectual property rights must be express and approved by Intel in -; writing. @@ -48,6 +418,31 @@ EXPORTS + + + + + + + + + + + + + + + + + + + + + + + + + @@ -55,37 +450,37 @@ EXPORTS + + + - + + - - - - - + @@ -93,25 +488,138 @@ EXPORTS + - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - @@ -127,36 +635,31 @@ EXPORTS - - - + + + + + + - - + + - - - - - - - - @@ -167,25 +670,24 @@ EXPORTS + + - - - @@ -201,10 +703,11 @@ EXPORTS + + - @@ -213,7 +716,6 @@ EXPORTS - @@ -261,9 +763,12 @@ __TBB_machine_is_in_transaction ?initialize@task_scheduler_init@tbb@@QEAAXH_K@Z ?initialize@task_scheduler_init@tbb@@QEAAXH@Z ?terminate@task_scheduler_init@tbb@@QEAAXXZ + ?observe@task_scheduler_observer_v3@internal@tbb@@QEAAX_N@Z - + + + ?internal_current_slot@task_arena_base@internal@interface7@tbb@@KAHXZ ?internal_initialize@task_arena_base@internal@interface7@tbb@@IEAAXXZ ?internal_terminate@task_arena_base@internal@interface7@tbb@@IEAAXXZ @@ -272,9 +777,13 @@ __TBB_machine_is_in_transaction ?internal_wait@task_arena_base@internal@interface7@tbb@@IEBAXXZ + + ?destroy@task@tbb@@QEAAXAEAV12@@Z + + ?allocate@allocate_root_with_context_proxy@internal@tbb@@QEBAAEAVtask@3@_K@Z ?free@allocate_root_with_context_proxy@internal@tbb@@QEBAXAEAVtask@3@@Z ?change_group@task@tbb@@QEAAXAEAVtask_group_context@2@@Z @@ -285,8 +794,10 @@ __TBB_machine_is_in_transaction ?init@task_group_context@tbb@@IEAAXXZ ?register_pending_exception@task_group_context@tbb@@QEAAXXZ ??1task_group_context@tbb@@QEAA@XZ + ?set_priority@task_group_context@tbb@@QEAAXW4priority_t@2@@Z ?priority@task_group_context@tbb@@QEBA?AW4priority_t@2@XZ + ?name@captured_exception@tbb@@UEBAPEBDXZ ?what@captured_exception@tbb@@UEBAPEBDXZ ??1captured_exception@tbb@@UEAA@XZ @@ -296,6 +807,7 @@ __TBB_machine_is_in_transaction ?clear@captured_exception@tbb@@QEAAXXZ + ?throw_bad_last_alloc_exception_v4@internal@tbb@@YAXXZ ?throw_exception_v4@internal@tbb@@YAXW4exception_id@12@@Z ?what@bad_last_alloc@tbb@@UEBAPEBDXZ @@ -320,6 +832,13 @@ TBB_runtime_interface_version ?itt_set_sync_name_v3@internal@tbb@@YAXPEAXPEB_W@Z + + + + + + + ??_7pipeline@tbb@@6B@ ??0pipeline@tbb@@QEAA@XZ ??1filter@tbb@@UEAA@XZ @@ -328,7 +847,9 @@ TBB_runtime_interface_version ?clear@pipeline@tbb@@QEAAXXZ ?inject_token@pipeline@tbb@@AEAAXAEAVtask@2@@Z ?run@pipeline@tbb@@QEAAX_K@Z + ?run@pipeline@tbb@@QEAAX_KAEAVtask_group_context@2@@Z + ?process_item@thread_bound_filter@tbb@@QEAA?AW4result_type@12@XZ ?try_process_item@thread_bound_filter@tbb@@QEAA?AW4result_type@12@XZ ?set_end_of_input@filter@tbb@@IEAAXXZ @@ -355,6 +876,7 @@ TBB_runtime_interface_version ?internal_destroy@scoped_lock_read@reader_writer_lock@interface5@tbb@@AEAAXXZ + ?internal_itt_releasing@spin_rw_mutex@tbb@@CAXPEAV12@@Z ?internal_acquire_writer@spin_rw_mutex@tbb@@CA_NPEAV12@@Z ?internal_acquire_reader@spin_rw_mutex@tbb@@CAXPEAV12@@Z @@ -366,6 +888,7 @@ TBB_runtime_interface_version ?internal_try_acquire_reader@spin_rw_mutex@tbb@@CA_NPEAV12@@Z + ?internal_construct@spin_rw_mutex_v3@tbb@@AEAAXXZ ?internal_upgrade@spin_rw_mutex_v3@tbb@@AEAA_NXZ ?internal_downgrade@spin_rw_mutex_v3@tbb@@AEAAXXZ @@ -415,6 +938,7 @@ TBB_runtime_interface_version ?internal_construct@critical_section_v4@internal@tbb@@QEAAXXZ + ?internal_grow_predicate@hash_map_segment_base@internal@tbb@@QEBA_NXZ @@ -432,6 +956,7 @@ TBB_runtime_interface_version ?internal_size@concurrent_queue_base@internal@tbb@@IEBA_JXZ + ??0concurrent_queue_iterator_base_v3@internal@tbb@@IEAA@AEBVconcurrent_queue_base_v3@12@@Z ??0concurrent_queue_iterator_base_v3@internal@tbb@@IEAA@AEBVconcurrent_queue_base_v3@12@_K@Z ??1concurrent_queue_iterator_base_v3@internal@tbb@@IEAA@XZ @@ -455,6 +980,7 @@ TBB_runtime_interface_version ?move_content@concurrent_queue_base_v8@internal@tbb@@IEAAXAEAV123@@Z + ?internal_assign@concurrent_vector_base@internal@tbb@@IEAAXAEBV123@_KP6AXPEAX1@ZP6AX2PEBX1@Z5@Z ?internal_capacity@concurrent_vector_base@internal@tbb@@IEBA_KXZ ?internal_clear@concurrent_vector_base@internal@tbb@@IEAAXP6AXPEAX_K@Z_N@Z @@ -465,6 +991,7 @@ TBB_runtime_interface_version ?internal_reserve@concurrent_vector_base@internal@tbb@@IEAAX_K00@Z + ??1concurrent_vector_base_v3@internal@tbb@@IEAA@XZ ?internal_assign@concurrent_vector_base_v3@internal@tbb@@IEAAXAEBV123@_KP6AXPEAX1@ZP6AX2PEBX1@Z5@Z ?internal_capacity@concurrent_vector_base_v3@internal@tbb@@IEBA_KXZ @@ -500,3 +1027,10 @@ TBB_runtime_interface_version ?internal_destroy_condition_variable@internal@interface5@tbb@@YAXAEATcondvar_impl_t@123@@Z +?active_value@global_control@interface9@tbb@@CA_KH@Z +?internal_create@global_control@interface9@tbb@@AEAAXXZ +?internal_destroy@global_control@interface9@tbb@@AEAAXXZ + + + + diff --git a/dependencies64/tbb/lib/win32/tbb.lib b/dependencies64/tbb/lib/win32/tbb.lib index c16727a49..c7a5404d5 100644 Binary files a/dependencies64/tbb/lib/win32/tbb.lib and b/dependencies64/tbb/lib/win32/tbb.lib differ diff --git a/dependencies64/tbb/lib/win32/tbb_debug.lib b/dependencies64/tbb/lib/win32/tbb_debug.lib index f974a7577..e7b215a3c 100644 Binary files a/dependencies64/tbb/lib/win32/tbb_debug.lib and b/dependencies64/tbb/lib/win32/tbb_debug.lib differ diff --git a/dependencies64/tbb/lib/win32/tbb_preview.lib b/dependencies64/tbb/lib/win32/tbb_preview.lib deleted file mode 100644 index bdceb7c7b..000000000 Binary files a/dependencies64/tbb/lib/win32/tbb_preview.lib and /dev/null differ diff --git a/dependencies64/tbb/lib/win32/tbb_preview_debug.lib b/dependencies64/tbb/lib/win32/tbb_preview_debug.lib deleted file mode 100644 index e6ecf5f9a..000000000 Binary files a/dependencies64/tbb/lib/win32/tbb_preview_debug.lib and /dev/null differ diff --git a/dependencies64/tbb/lib/win32/tbbmalloc.def b/dependencies64/tbb/lib/win32/tbbmalloc.def index 8f22c9131..1965e689b 100644 --- a/dependencies64/tbb/lib/win32/tbbmalloc.def +++ b/dependencies64/tbb/lib/win32/tbbmalloc.def @@ -1,20 +1,21 @@ -; Copyright 2005-2014 Intel Corporation. All Rights Reserved. + +; Copyright 2005-2015 Intel Corporation. All Rights Reserved. ; -; The source code contained or described herein and all documents related -; to the source code ("Material") are owned by Intel Corporation or its -; suppliers or licensors. Title to the Material remains with Intel -; Corporation or its suppliers and licensors. The Material is protected -; by worldwide copyright laws and treaty provisions. No part of the -; Material may be used, copied, reproduced, modified, published, uploaded, -; posted, transmitted, distributed, or disclosed in any way without -; Intel's prior express written permission. +; This file is part of Threading Building Blocks. Threading Building Blocks is free software; +; you can redistribute it and/or modify it under the terms of the GNU General Public License +; version 2 as published by the Free Software Foundation. Threading Building Blocks is +; distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the +; implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +; See the GNU General Public License for more details. You should have received a copy of +; the GNU General Public License along with Threading Building Blocks; if not, write to the +; Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA ; -; No license under any patent, copyright, trade secret or other -; intellectual property right is granted to or conferred upon you by -; disclosure or delivery of the Materials, either expressly, by -; implication, inducement, estoppel or otherwise. Any license under such -; intellectual property rights must be express and approved by Intel in -; writing. +; As a special exception, you may use this file as part of a free software library without +; restriction. Specifically, if other files instantiate templates or use macros or inline +; functions from this file, or you compile this file and link it with other files to produce +; an executable, this file does not by itself cause the resulting executable to be covered +; by the GNU General Public License. This exception does not however invalidate any other +; reasons why the executable file might be covered by the GNU General Public License. EXPORTS @@ -45,3 +46,4 @@ __TBB_malloc_safer_aligned_realloc ?pool_realloc@rml@@YAPEAXPEAVMemoryPool@1@PEAX_K@Z ?pool_aligned_realloc@rml@@YAPEAXPEAVMemoryPool@1@PEAX_K2@Z ?pool_aligned_malloc@rml@@YAPEAXPEAVMemoryPool@1@_K1@Z +?pool_identify@rml@@YAPEAVMemoryPool@1@PEAX@Z diff --git a/dependencies64/tbb/lib/win32/tbbmalloc.lib b/dependencies64/tbb/lib/win32/tbbmalloc.lib index cdab1e3ad..86e059757 100644 Binary files a/dependencies64/tbb/lib/win32/tbbmalloc.lib and b/dependencies64/tbb/lib/win32/tbbmalloc.lib differ diff --git a/dependencies64/tbb/lib/win32/tbbmalloc_debug.lib b/dependencies64/tbb/lib/win32/tbbmalloc_debug.lib index 2efec8311..7d0f02056 100644 Binary files a/dependencies64/tbb/lib/win32/tbbmalloc_debug.lib and b/dependencies64/tbb/lib/win32/tbbmalloc_debug.lib differ diff --git a/dependencies64/tbb/lib/win32/tbbmalloc_proxy.lib b/dependencies64/tbb/lib/win32/tbbmalloc_proxy.lib index 7385c8732..94e111add 100644 Binary files a/dependencies64/tbb/lib/win32/tbbmalloc_proxy.lib and b/dependencies64/tbb/lib/win32/tbbmalloc_proxy.lib differ diff --git a/dependencies64/tbb/lib/win32/tbbmalloc_proxy_debug.lib b/dependencies64/tbb/lib/win32/tbbmalloc_proxy_debug.lib index 15bcdb672..621cf32af 100644 Binary files a/dependencies64/tbb/lib/win32/tbbmalloc_proxy_debug.lib and b/dependencies64/tbb/lib/win32/tbbmalloc_proxy_debug.lib differ diff --git a/dependencies64/tbb/lib/win32/tbbproxy.lib b/dependencies64/tbb/lib/win32/tbbproxy.lib deleted file mode 100644 index 2b18a0197..000000000 Binary files a/dependencies64/tbb/lib/win32/tbbproxy.lib and /dev/null differ diff --git a/dependencies64/tbb/lib/win32/tbbproxy.pdb b/dependencies64/tbb/lib/win32/tbbproxy.pdb deleted file mode 100644 index 07a1de76d..000000000 Binary files a/dependencies64/tbb/lib/win32/tbbproxy.pdb and /dev/null differ diff --git a/dependencies64/tbb/lib/win32/tbbproxy_debug.lib b/dependencies64/tbb/lib/win32/tbbproxy_debug.lib deleted file mode 100644 index 7122c258d..000000000 Binary files a/dependencies64/tbb/lib/win32/tbbproxy_debug.lib and /dev/null differ diff --git a/dependencies64/tbb/lib/win32/tbbproxy_debug.pdb b/dependencies64/tbb/lib/win32/tbbproxy_debug.pdb deleted file mode 100644 index 022095c72..000000000 Binary files a/dependencies64/tbb/lib/win32/tbbproxy_debug.pdb and /dev/null differ