From: bangerth Date: Fri, 19 Nov 2010 01:26:33 +0000 (+0000) Subject: Remove tests directory. X-Git-Url: https://gitweb.dealii.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=3190662353792ab89045b94191acd1edf21aab11;p=dealii-svn.git Remove tests directory. git-svn-id: https://svn.dealii.org/trunk@22814 0785d39b-7218-0410-832d-ea1e28bc413d --- diff --git a/deal.II/contrib/tbb/tbb30_104oss/src/test/harness.h b/deal.II/contrib/tbb/tbb30_104oss/src/test/harness.h deleted file mode 100644 index c4805b2b5c..0000000000 --- a/deal.II/contrib/tbb/tbb30_104oss/src/test/harness.h +++ /dev/null @@ -1,461 +0,0 @@ -/* - Copyright 2005-2010 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. -*/ - -// Declarations for rock-bottom simple test harness. -// Just include this file to use it. -// Every test is presumed to have a command line of the form "test [-v] [MinThreads[:MaxThreads]]" -// The default for MinThreads is 1, for MaxThreads 4. -// The defaults can be overridden by defining macros HARNESS_DEFAULT_MIN_THREADS -// and HARNESS_DEFAULT_MAX_THREADS before including harness.h - -#ifndef tbb_tests_harness_H -#define tbb_tests_harness_H - -#include "tbb/tbb_config.h" - -namespace Harness { - enum TestResult { - Done, - Skipped - }; -} - -//! Entry point to a TBB unit test application -/** It MUST be defined by the test application. - - If HARNESS_NO_PARSE_COMMAND_LINE macro was not explicitly set before including harness.h, - then global variables Verbose, MinThread, and MaxThread will be available and - initialized when it is called. - - Returns Harness::Done when the tests passed successfully. When the test fail, it must - not return, calling exit(errcode) or abort() instead. When the test is not supported - for the given platform/compiler/etc, it should return Harness::Skipped. - - To provide non-standard variant of main() for the test, define HARNESS_CUSTOM_MAIN - before including harness.h **/ -int TestMain (); - -#define __TBB_LAMBDAS_PRESENT ( _MSC_VER >= 1600 && !__INTEL_COMPILER || __INTEL_COMPILER > 1100 && _TBB_CPP0X ) - -#if defined(_MSC_VER) && _MSC_VER < 1400 - #define __TBB_EXCEPTION_TYPE_INFO_BROKEN 1 -#else - #define __TBB_EXCEPTION_TYPE_INFO_BROKEN 0 -#endif - -#if __SUNPRO_CC - #include - #include -#else /* !__SUNPRO_CC */ - #include -#if !TBB_USE_EXCEPTIONS && _MSC_VER - // Suppress "C++ exception handler used, but unwind semantics are not enabled" warning in STL headers - #pragma warning (push) - #pragma warning (disable: 4530) -#endif - #include -#if !TBB_USE_EXCEPTIONS && _MSC_VER - #pragma warning (pop) -#endif -#endif /* !__SUNPRO_CC */ - -#include - - #define HARNESS_EXPORT - #define REPORT_FATAL_ERROR REPORT - -#if _WIN32||_WIN64 - #include "tbb/machine/windows_api.h" -#if _XBOX - #undef HARNESS_NO_PARSE_COMMAND_LINE - #define HARNESS_NO_PARSE_COMMAND_LINE 1 -#endif - #include -#else - #include -#endif -#if __linux__ - #include /* for uname */ - #include /* for use in LinuxKernelVersion() */ -#endif - -#include "harness_report.h" - -#if !HARNESS_NO_ASSERT -#include "harness_assert.h" - -typedef void (*test_error_extra_t)(void); -static test_error_extra_t ErrorExtraCall; -//! Set additional handler to process failed assertions -void SetHarnessErrorProcessing( test_error_extra_t extra_call ) { - ErrorExtraCall = extra_call; - // TODO: add tbb::set_assertion_handler(ReportError); -} -//! Reports errors issued by failed assertions -void ReportError( const char* filename, int line, const char* expression, const char * message ) { -#if __TBB_ICL_11_1_CODE_GEN_BROKEN - printf("%s:%d, assertion %s: %s\n", filename, line, expression, message ? message : "failed" ); -#else - REPORT_FATAL_ERROR("%s:%d, assertion %s: %s\n", filename, line, expression, message ? message : "failed" ); -#endif - if( ErrorExtraCall ) - (*ErrorExtraCall)(); -#if HARNESS_TERMINATE_ON_ASSERT - TerminateProcess(GetCurrentProcess(), 1); -#elif HARNESS_EXIT_ON_ASSERT - exit(1); -#else - abort(); -#endif /* HARNESS_EXIT_ON_ASSERT */ -} -//! Reports warnings issued by failed warning assertions -void ReportWarning( const char* filename, int line, const char* expression, const char * message ) { - REPORT("Warning: %s:%d, assertion %s: %s\n", filename, line, expression, message ? message : "failed" ); -} -#else -#define ASSERT(p,msg) ((void)0) -#define ASSERT_WARNING(p,msg) ((void)0) -#endif /* HARNESS_NO_ASSERT */ - -#if !HARNESS_NO_PARSE_COMMAND_LINE - -//! Controls level of commentary printed via printf-like REMARK() macro. -/** If true, makes the test print commentary. If false, test should print "done" and nothing more. */ -static bool Verbose; - -#ifndef HARNESS_DEFAULT_MIN_THREADS - #define HARNESS_DEFAULT_MIN_THREADS 1 -#endif - -//! Minimum number of threads -static int MinThread = HARNESS_DEFAULT_MIN_THREADS; - -#ifndef HARNESS_DEFAULT_MAX_THREADS - #define HARNESS_DEFAULT_MAX_THREADS 4 -#endif - -//! Maximum number of threads -static int MaxThread = HARNESS_DEFAULT_MAX_THREADS; - -//! Parse command line of the form "name [-v] [MinThreads[:MaxThreads]]" -/** Sets Verbose, MinThread, and MaxThread accordingly. - The nthread argument can be a single number or a range of the form m:n. - A single number m is interpreted as if written m:m. - The numbers must be non-negative. - Clients often treat the value 0 as "run sequentially." */ -static void ParseCommandLine( int argc, char* argv[] ) { - if( !argc ) REPORT("Command line with 0 arguments\n"); - int i = 1; - if( i -class NativeParallelForTask: NoCopy { -public: - NativeParallelForTask( Index index_, const Body& body_ ) : - index(index_), - body(body_) - {} - - //! Start task - void start() { -#if _WIN32||_WIN64 - unsigned thread_id; - thread_handle = (HANDLE)_beginthreadex( NULL, 0, thread_function, this, 0, &thread_id ); - ASSERT( thread_handle!=0, "NativeParallelFor: _beginthreadex failed" ); -#else -#if __ICC==1100 - #pragma warning (push) - #pragma warning (disable: 2193) -#endif /* __ICC==1100 */ - // Some machines may have very large hard stack limit. When the test is - // launched by make, the default stack size is set to the hard limit, and - // calls to pthread_create fail with out-of-memory error. - // Therefore we set the stack size explicitly (as for TBB worker threads). - const size_t MByte = 1<<20; -#if __i386__||__i386 - const size_t stack_size = 1*MByte; -#elif __x86_64__ - const size_t stack_size = 2*MByte; -#else - const size_t stack_size = 4*MByte; -#endif - pthread_attr_t attr_stack; - int status = pthread_attr_init(&attr_stack); - ASSERT(0==status, "NativeParallelFor: pthread_attr_init failed"); - status = pthread_attr_setstacksize( &attr_stack, stack_size ); - ASSERT(0==status, "NativeParallelFor: pthread_attr_setstacksize failed"); - status = pthread_create(&thread_id, &attr_stack, thread_function, this); - ASSERT(0==status, "NativeParallelFor: pthread_create failed"); - pthread_attr_destroy(&attr_stack); -#if __ICC==1100 - #pragma warning (pop) -#endif -#endif /* _WIN32||_WIN64 */ - } - - //! Wait for task to finish - void wait_to_finish() { -#if _WIN32||_WIN64 - DWORD status = WaitForSingleObject( thread_handle, INFINITE ); - ASSERT( status!=WAIT_FAILED, "WaitForSingleObject failed" ); - CloseHandle( thread_handle ); -#else - int status = pthread_join( thread_id, NULL ); - ASSERT( !status, "pthread_join failed" ); -#endif - } - -private: -#if _WIN32||_WIN64 - HANDLE thread_handle; -#else - pthread_t thread_id; -#endif - - //! Range over which task will invoke the body. - const Index index; - - //! Body to invoke over the range. - const Body body; - -#if _WIN32||_WIN64 - static unsigned __stdcall thread_function( void* object ) -#else - static void* thread_function(void* object) -#endif - { - NativeParallelForTask& self = *static_cast(object); - (self.body)(self.index); - return 0; - } -}; - -//! Execute body(i) in parallel for i in the interval [0,n). -/** Each iteration is performed by a separate thread. */ -template -void NativeParallelFor( Index n, const Body& body ) { - typedef NativeParallelForTask task; - - if( n>0 ) { - // Allocate array to hold the tasks - task* array = static_cast(operator new( n*sizeof(task) )); - - // Construct the tasks - for( Index i=0; i!=n; ++i ) - new( &array[i] ) task(i,body); - - // Start the tasks - for( Index i=0; i!=n; ++i ) - array[i].start(); - - // Wait for the tasks to finish and destroy each one. - for( Index i=n; i; --i ) { - array[i-1].wait_to_finish(); - array[i-1].~task(); - } - - // Deallocate the task array - operator delete(array); - } -} - -//! The function to zero-initialize arrays; useful to avoid warnings -template -void zero_fill(void* array, size_t n) { - memset(array, 0, sizeof(T)*n); -} - -#if __SUNPRO_CC && defined(min) -#undef min -#undef max -#endif - -#ifndef min -//! Utility template function returning lesser of the two values. -/** Provided here to avoid including not strict safe .\n - In case operands cause signed/unsigned or size mismatch warnings it is caller's - responsibility to do the appropriate cast before calling the function. **/ -template -T1 min ( const T1& val1, const T2& val2 ) { - return val1 < val2 ? val1 : val2; -} -#endif /* !min */ - -#ifndef max -//! Utility template function returning greater of the two values. -/** Provided here to avoid including not strict safe .\n - In case operands cause signed/unsigned or size mismatch warnings it is caller's - responsibility to do the appropriate cast before calling the function. **/ -template -T1 max ( const T1& val1, const T2& val2 ) { - return val1 < val2 ? val2 : val1; -} -#endif /* !max */ - -#if __linux__ -inline unsigned LinuxKernelVersion() -{ - unsigned digit1, digit2, digit3; - struct utsname utsnameBuf; - - if (-1 == uname(&utsnameBuf)) { - REPORT_FATAL_ERROR("Can't call uname: errno %d\n", errno); - exit(1); - } - if (3 != sscanf(utsnameBuf.release, "%u.%u.%u", &digit1, &digit2, &digit3)) { - REPORT_FATAL_ERROR("Unable to parse OS release '%s'\n", utsnameBuf.release); - exit(1); - } - return 1000000*digit1+1000*digit2+digit3; -} -#endif - -namespace Harness { - -#if !HARNESS_NO_ASSERT -//! Base class that asserts that no operations are made with the object after its destruction. -class NoAfterlife { -protected: - enum state_t { - LIVE=0x56781234, - DEAD=0xDEADBEEF - } m_state; - -public: - NoAfterlife() : m_state(LIVE) {} - NoAfterlife( const NoAfterlife& src ) : m_state(LIVE) { - ASSERT( src.IsLive(), "Constructing from the dead source" ); - } - ~NoAfterlife() { - ASSERT( IsLive(), "Repeated destructor call" ); - m_state = DEAD; - } - const NoAfterlife& operator=( const NoAfterlife& src ) { - ASSERT( IsLive(), NULL ); - ASSERT( src.IsLive(), NULL ); - return *this; - } - void AssertLive() const { - ASSERT( IsLive(), "Already dead" ); - } - bool IsLive() const { - return m_state == LIVE; - } -}; // NoAfterlife -#endif /* !HARNESS_NO_ASSERT */ - -#if _WIN32 || _WIN64 - void Sleep ( int ms ) { ::Sleep(ms); } -#else /* !WIN */ - void Sleep ( int ms ) { - timespec requested = { ms / 1000, (ms % 1000)*1000000 }; - timespec remaining = { 0, 0 }; - nanosleep(&requested, &remaining); - } -#endif /* !WIN */ - -} // namespace Harness - -#endif /* tbb_tests_harness_H */ diff --git a/deal.II/contrib/tbb/tbb30_104oss/src/test/harness_allocator.h b/deal.II/contrib/tbb/tbb30_104oss/src/test/harness_allocator.h deleted file mode 100644 index 00e5cd6d72..0000000000 --- a/deal.II/contrib/tbb/tbb30_104oss/src/test/harness_allocator.h +++ /dev/null @@ -1,293 +0,0 @@ -/* - Copyright 2005-2010 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. -*/ - -// Declarations for simple estimate of the memory being used by a program. -// Not yet implemented for Mac. -// This header is an optional part of the test harness. -// It assumes that "harness_assert.h" has already been included. - -#if __linux__ || __APPLE__ || __sun -#include -#elif _WIN32 -#include "tbb/machine/windows_api.h" -#endif /* OS specific */ -#include - -#if !TBB_USE_EXCEPTIONS && _MSC_VER - // Suppress "C++ exception handler used, but unwind semantics are not enabled" warning in STL headers - #pragma warning (push) - #pragma warning (disable: 4530) -#endif - -#include - -#if !TBB_USE_EXCEPTIONS && _MSC_VER - #pragma warning (pop) -#endif - -#include "tbb/atomic.h" - -#if __SUNPRO_CC -using std::printf; -#endif - -#if defined(_MSC_VER) && defined(_Wp64) - // Workaround for overzealous compiler warnings in /Wp64 mode - #pragma warning (push) - #pragma warning (disable: 4267) -#endif - - -template > -class static_counting_allocator : public base_alloc_t -{ -public: - typedef typename base_alloc_t::pointer pointer; - typedef typename base_alloc_t::const_pointer const_pointer; - typedef typename base_alloc_t::reference reference; - typedef typename base_alloc_t::const_reference const_reference; - typedef typename base_alloc_t::value_type value_type; - typedef typename base_alloc_t::size_type size_type; - typedef typename base_alloc_t::difference_type difference_type; - template struct rebind { - typedef static_counting_allocator::other,count_t> other; - }; - - static size_t max_items; - static count_t items_allocated; - static count_t items_freed; - static count_t allocations; - static count_t frees; - static bool verbose, throwing; - - static_counting_allocator() throw() { } - - static_counting_allocator(const static_counting_allocator& src) throw() - : base_alloc_t(src) { } - - template - static_counting_allocator(const static_counting_allocator& src) throw() - : base_alloc_t(src) { } - - bool operator==(const static_counting_allocator &a) const - { return true; } - - pointer allocate(const size_type n) - { - if(verbose) printf("\t+%d|", int(n)); - if(max_items && items_allocated + n >= max_items) { - if(verbose) printf("items limit hits!"); - if(throwing) - __TBB_THROW( std::bad_alloc() ); - return NULL; - } - allocations++; - items_allocated += n; - return base_alloc_t::allocate(n, pointer(0)); - } - - pointer allocate(const size_type n, const void * const) - { return allocate(n); } - - void deallocate(const pointer ptr, const size_type n) - { - if(verbose) printf("\t-%d|", int(n)); - frees++; - items_freed += n; - base_alloc_t::deallocate(ptr, n); - } - - static void init_counters(bool v = false) { - verbose = v; - if(verbose) printf("\n------------------------------------------- Allocations:\n"); - items_allocated = 0; - items_freed = 0; - allocations = 0; - frees = 0; - max_items = 0; - } - - static void set_limits(size_type max = 0, bool do_throw = true) { - max_items = max; - throwing = do_throw; - } -}; - -template -size_t static_counting_allocator::max_items; -template -count_t static_counting_allocator::items_allocated; -template -count_t static_counting_allocator::items_freed; -template -count_t static_counting_allocator::allocations; -template -count_t static_counting_allocator::frees; -template -bool static_counting_allocator::verbose; -template -bool static_counting_allocator::throwing; - -template > -class local_counting_allocator : public base_alloc_t -{ -public: - typedef typename base_alloc_t::pointer pointer; - typedef typename base_alloc_t::const_pointer const_pointer; - typedef typename base_alloc_t::reference reference; - typedef typename base_alloc_t::const_reference const_reference; - typedef typename base_alloc_t::value_type value_type; - typedef typename base_alloc_t::size_type size_type; - typedef typename base_alloc_t::difference_type difference_type; - template struct rebind { - typedef local_counting_allocator::other,count_t> other; - }; - - count_t items_allocated; - count_t items_freed; - count_t allocations; - count_t frees; - size_t max_items; - - local_counting_allocator() throw() { - items_allocated = 0; - items_freed = 0; - allocations = 0; - frees = 0; - max_items = 0; - } - - local_counting_allocator(const local_counting_allocator &a) throw() - : base_alloc_t(a) - , items_allocated(a.items_allocated) - , items_freed(a.items_freed) - , allocations(a.allocations) - , frees(a.frees) - , max_items(a.max_items) - { } - - template - local_counting_allocator(const static_counting_allocator &) throw() { - items_allocated = static_counting_allocator::items_allocated; - items_freed = static_counting_allocator::items_freed; - allocations = static_counting_allocator::allocations; - frees = static_counting_allocator::frees; - max_items = static_counting_allocator::max_items; - } - - template - local_counting_allocator(const local_counting_allocator &a) throw() - : items_allocated(a.items_allocated) - , items_freed(a.items_freed) - , allocations(a.allocations) - , frees(a.frees) - , max_items(a.max_items) - { } - - bool operator==(const local_counting_allocator &a) const - { return &a == this; } - - pointer allocate(const size_type n) - { - if(max_items && items_allocated + n >= max_items) - __TBB_THROW( std::bad_alloc() ); - ++allocations; - items_allocated += n; - return base_alloc_t::allocate(n, pointer(0)); - } - - pointer allocate(const size_type n, const void * const) - { return allocate(n); } - - void deallocate(const pointer ptr, const size_type n) - { - ++frees; - items_freed += n; - base_alloc_t::deallocate(ptr, n); - } - - void set_limits(size_type max = 0) { - max_items = max; - } -}; - -template class Allocator = std::allocator> -class debug_allocator : public Allocator -{ -public: - typedef Allocator base_allocator_type; - typedef typename base_allocator_type::value_type value_type; - typedef typename base_allocator_type::pointer pointer; - typedef typename base_allocator_type::const_pointer const_pointer; - typedef typename base_allocator_type::reference reference; - typedef typename base_allocator_type::const_reference const_reference; - typedef typename base_allocator_type::size_type size_type; - typedef typename base_allocator_type::difference_type difference_type; - template struct rebind { - typedef debug_allocator other; - }; - - debug_allocator() throw() { } - debug_allocator(const debug_allocator &a) throw() : base_allocator_type( a ) { } - template - debug_allocator(const debug_allocator &a) throw() : base_allocator_type( Allocator( a ) ) { } - - pointer allocate(const size_type n, const void *hint = 0 ) { - pointer ptr = base_allocator_type::allocate( n, hint ); - std::memset( ptr, 0xE3E3E3E3, n * sizeof(value_type) ); - return ptr; - } -}; - -//! Analogous to std::allocator, as defined in ISO C++ Standard, Section 20.4.1 -/** @ingroup memory_allocation */ -template class Allocator> -class debug_allocator : public Allocator { -public: - typedef Allocator base_allocator_type; - typedef typename base_allocator_type::value_type value_type; - typedef typename base_allocator_type::pointer pointer; - typedef typename base_allocator_type::const_pointer const_pointer; - template struct rebind { - typedef debug_allocator other; - }; -}; - -template class B1, typename T2, template class B2> -inline bool operator==( const debug_allocator &a, const debug_allocator &b) { - return static_cast< B1 >(a) == static_cast< B2 >(b); -} -template class B1, typename T2, template class B2> -inline bool operator!=( const debug_allocator &a, const debug_allocator &b) { - return static_cast< B1 >(a) != static_cast< B2 >(b); -} - -#if defined(_MSC_VER) && defined(_Wp64) - // Workaround for overzealous compiler warnings in /Wp64 mode - #pragma warning (pop) -#endif // warning 4267 is back diff --git a/deal.II/contrib/tbb/tbb30_104oss/src/test/harness_assert.h b/deal.II/contrib/tbb/tbb30_104oss/src/test/harness_assert.h deleted file mode 100644 index 0fecbd5b50..0000000000 --- a/deal.II/contrib/tbb/tbb30_104oss/src/test/harness_assert.h +++ /dev/null @@ -1,48 +0,0 @@ -/* - Copyright 2005-2010 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. -*/ - -// Just the assertion portion of the harness. -// This is useful for writing portions of tests that include -// the minimal number of necessary header files. -// -// The full "harness.h" must be included later. - -#ifndef harness_assert_H -#define harness_assert_H - -void ReportError( const char* filename, int line, const char* expression, const char* message); -void ReportWarning( const char* filename, int line, const char* expression, const char* message); - -#define ASSERT(p,message) ((p)?(void)0:ReportError(__FILE__,__LINE__,#p,message)) -#define ASSERT_WARNING(p,message) ((p)?(void)0:ReportWarning(__FILE__,__LINE__,#p,message)) - -//! Compile-time error if x and y have different types -template -void AssertSameType( const T& /*x*/, const T& /*y*/ ) {} - -#endif /* harness_assert_H */ diff --git a/deal.II/contrib/tbb/tbb30_104oss/src/test/harness_bad_expr.h b/deal.II/contrib/tbb/tbb30_104oss/src/test/harness_bad_expr.h deleted file mode 100644 index 2fc0b4a7a5..0000000000 --- a/deal.II/contrib/tbb/tbb30_104oss/src/test/harness_bad_expr.h +++ /dev/null @@ -1,85 +0,0 @@ -/* - Copyright 2005-2010 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. -*/ - -// Declarations for checking __TBB_ASSERT checks inside TBB. -// This header is an optional part of the test harness. -// It assumes that "harness.h" has already been included. - -#define TRY_BAD_EXPR_ENABLED (TBB_USE_ASSERT && TBB_USE_EXCEPTIONS && !__TBB_THROW_ACROSS_MODULE_BOUNDARY_BROKEN) - -#if TRY_BAD_EXPR_ENABLED - -//! Check that expression x raises assertion failure with message containing given substring. -/** Assumes that tbb::set_assertion_handler( AssertionFailureHandler ) was called earlier. */ -#define TRY_BAD_EXPR(x,substr) \ - { \ - const char* message = NULL; \ - bool okay = false; \ - try { \ - x; \ - } catch( AssertionFailure a ) { \ - okay = true; \ - message = a.message; \ - } \ - CheckAssertionFailure(__LINE__,#x,okay,message,substr); \ - } - -//! Exception object that holds a message. -struct AssertionFailure { - const char* message; - AssertionFailure( const char* filename, int line, const char* expression, const char* comment ); -}; - -AssertionFailure::AssertionFailure( const char* filename, int line, const char* expression, const char* comment ) : - message(comment) -{ - ASSERT(filename,"missing filename"); - ASSERT(0 numThreadsFinished; /* threads reached barrier in this epoch */ - tbb::atomic epoch; /* how many times this barrier used - XXX move to a separate cache line */ - - struct DummyCallback { - void operator() () const {} - }; - - SpinBarrier( const SpinBarrier& ); // no copy ctor - void operator=( const SpinBarrier& ); // no assignment -public: - SpinBarrier( unsigned nthreads = 0 ) { initialize(nthreads); }; - - void initialize( unsigned nthreads ) { - numThreads = nthreads; - numThreadsFinished = 0; - epoch = 0; - }; - - // onOpenBarrierCallback is called by last thread arrived on a barrier - template - bool wait(const Callback &onOpenBarrierCallback) - { // return true if last thread - unsigned myEpoch = epoch; - int threadsLeft = numThreads - numThreadsFinished.fetch_and_increment() - 1; - ASSERT(threadsLeft>=0, "Broken barrier"); - if (threadsLeft > 0) { - /* not the last threading reaching barrier, wait until epoch changes & return 0 */ - tbb::internal::spin_wait_while_eq(epoch, myEpoch); - return false; - } - /* No more threads left to enter, so I'm the last one reaching this epoch; - reset the barrier, increment epoch, and return non-zero */ - onOpenBarrierCallback(); - numThreadsFinished = 0; - epoch = myEpoch+1; /* wakes up threads waiting to exit this epoch */ - return true; - } - bool wait() - { - return wait(DummyCallback()); - } -}; - -} - -#endif //harness_barrier_H diff --git a/deal.II/contrib/tbb/tbb30_104oss/src/test/harness_concurrency_tracker.h b/deal.II/contrib/tbb/tbb30_104oss/src/test/harness_concurrency_tracker.h deleted file mode 100644 index 5a5fa888ef..0000000000 --- a/deal.II/contrib/tbb/tbb30_104oss/src/test/harness_concurrency_tracker.h +++ /dev/null @@ -1,85 +0,0 @@ -/* - Copyright 2005-2010 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_tests_harness_concurrency_tracker_H -#define tbb_tests_harness_concurrency_tracker_H - -#include "harness.h" -#include "tbb/atomic.h" -#include "../tbb/tls.h" - -namespace Harness { - -static tbb::atomic ctInstantParallelism; -static tbb::atomic ctPeakParallelism; -static tbb::internal::tls ctNested; - -class ConcurrencyTracker { - bool m_Outer; - - static void Started () { - unsigned p = ++ctInstantParallelism; - unsigned q = ctPeakParallelism; - while( q

0, "Mismatched call to ConcurrencyTracker::Stopped()" ); - --ctInstantParallelism; - } -public: - ConcurrencyTracker() : m_Outer(false) { - uintptr_t nested = ctNested; - ASSERT (nested == 0 || nested == 1, NULL); - if ( !ctNested ) { - Started(); - m_Outer = true; - ctNested = 1; - } - } - ~ConcurrencyTracker() { - if ( m_Outer ) { - Stopped(); - ctNested = 0; - } - } - - static unsigned PeakParallelism() { return ctPeakParallelism; } - static unsigned InstantParallelism() { return ctInstantParallelism; } - - static void Reset() { - ASSERT (ctInstantParallelism == 0, "Reset cannot be called when concurrency tracking is underway"); - ctInstantParallelism = ctPeakParallelism = 0; - } -}; // ConcurrencyTracker - -} // namespace Harness - -#endif /* tbb_tests_harness_concurrency_tracker_H */ diff --git a/deal.II/contrib/tbb/tbb30_104oss/src/test/harness_cpu.h b/deal.II/contrib/tbb/tbb30_104oss/src/test/harness_cpu.h deleted file mode 100644 index b3c91c36b3..0000000000 --- a/deal.II/contrib/tbb/tbb30_104oss/src/test/harness_cpu.h +++ /dev/null @@ -1,129 +0,0 @@ -/* - Copyright 2005-2010 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. -*/ - -// Declarations for simple estimate of CPU time being used by a program. -// This header is an optional part of the test harness. -// It assumes that "harness_assert.h" has already been included. - -#if _WIN32 -#if !_XBOX - #include -#endif -#else - #include - #include -#endif - -//! Return time (in seconds) spent by the current process in user mode. -/* Returns 0 if not implemented on platform. */ -static double GetCPUUserTime() { -#if _XBOX - return 0; -#elif _WIN32 - FILETIME my_times[4]; - bool status = GetProcessTimes(GetCurrentProcess(), my_times, my_times+1, my_times+2, my_times+3)!=0; - ASSERT( status, NULL ); - LARGE_INTEGER usrtime; - usrtime.LowPart = my_times[3].dwLowDateTime; - usrtime.HighPart = my_times[3].dwHighDateTime; - return double(usrtime.QuadPart)*1E-7; -#else - // Generic UNIX, including __APPLE__ - - // On Linux, there is no good way to get CPU usage info for the current process: - // getrusage(RUSAGE_SELF, ...) that is used now only returns info for the calling thread; - // getrusage(RUSAGE_CHILDREN, ...) only counts for finished children threads; - // tms_utime and tms_cutime got with times(struct tms*) are equivalent to the above items; - // finally, /proc/self/task//stat doesn't exist on older kernels - // and it isn't quite convenient to read it for every task_id. - - struct rusage resources; - bool status = getrusage(RUSAGE_SELF, &resources)==0; - ASSERT( status, NULL ); - return (double(resources.ru_utime.tv_sec)*1E6 + double(resources.ru_utime.tv_usec))*1E-6; -#endif -} - -#include "tbb/tick_count.h" -#include - -// The resolution of GetCPUUserTime is 10-15 ms or so; waittime should be a few times bigger. -const double WAITTIME = 0.1; // in seconds, i.e. 100 ms -const double THRESHOLD = WAITTIME/100; - -static void TestCPUUserTime( int nthreads, int nactive = 1 ) { - // The test will always pass on Linux; read the comments in GetCPUUserTime for details - // Also it will not detect spinning issues on systems with only one processing core. - - int nworkers = nthreads-nactive; - if( !nworkers ) return; - double lastusrtime = GetCPUUserTime(); - if( !lastusrtime ) return; - - static double minimal_waittime = WAITTIME, - maximal_waittime = WAITTIME * 10; - double usrtime; - double waittime; - tbb::tick_count stamp = tbb::tick_count::now(); - // wait for GetCPUUserTime update - while( (usrtime=GetCPUUserTime())-lastusrtime < THRESHOLD ) { - volatile intptr_t k = (intptr_t)&usrtime; - for ( int i = 0; i < 1000; ++i ) ++k; - if ( (waittime = (tbb::tick_count::now()-stamp).seconds()) > maximal_waittime ) { - REPORT( "Warning: %.2f sec elapsed but user mode time is still below its threshold (%g < %g)\n", - waittime, usrtime - lastusrtime, THRESHOLD ); - break; - } - } - lastusrtime = usrtime; - - // Wait for workers to go sleep - stamp = tbb::tick_count::now(); - while( ((waittime=(tbb::tick_count::now()-stamp).seconds()) < minimal_waittime) - || ((usrtime=GetCPUUserTime()-lastusrtime) < THRESHOLD) ) - { - if ( waittime > maximal_waittime ) { - REPORT( "Warning: %.2f sec elapsed but GetCPUUserTime reported only %g sec\n", waittime, usrtime ); - break; - } - } - - // Test that all workers sleep when no work. - while( nactive>1 && usrtime-nactive*waittime<0 ) { - // probably the number of active threads was mispredicted - --nactive; ++nworkers; - } - double avg_worker_usrtime = (usrtime-nactive*waittime)/nworkers; - - if( avg_worker_usrtime > waittime/2 ) - REPORT( "ERROR: %d worker threads are spinning; waittime: %g; usrtime: %g; avg worker usrtime: %g\n", - nworkers, waittime, usrtime, avg_worker_usrtime); - else - REMARK("%d worker threads; waittime: %g; usrtime: %g; avg worker usrtime: %g\n", - nworkers, waittime, usrtime, avg_worker_usrtime); -} diff --git a/deal.II/contrib/tbb/tbb30_104oss/src/test/harness_eh.h b/deal.II/contrib/tbb/tbb30_104oss/src/test/harness_eh.h deleted file mode 100644 index 48f4b2ebac..0000000000 --- a/deal.II/contrib/tbb/tbb30_104oss/src/test/harness_eh.h +++ /dev/null @@ -1,244 +0,0 @@ -/* - Copyright 2005-2010 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. -*/ - -#include -#include "tbb/atomic.h" -#include "harness.h" -#include "harness_concurrency_tracker.h" - -namespace Harness { -#if _WIN32 || _WIN64 - typedef DWORD tid_t; - tid_t CurrentTid () { return GetCurrentThreadId(); } -#else /* !WIN */ - typedef pthread_t tid_t; - tid_t CurrentTid () { return pthread_self(); } -#endif /* !WIN */ -} // namespace Harness - -int g_NumThreads = 0; -Harness::tid_t g_Master = 0; - -tbb::atomic g_CurExecuted, - g_ExecutedAtCatch, - g_ExceptionsThrown; -volatile bool g_ExceptionCaught = false, - g_UnknownException = false; - -volatile bool g_ThrowException = true, - g_Flog = false; - -bool g_ExceptionInMaster = false; -bool g_SolitaryException = false; - -//! Number of exceptions propagated into the user code (i.e. intercepted by the tests) -tbb::atomic g_Exceptions; - -inline void ResetEhGlobals ( bool throwException = true, bool flog = false ) { - Harness::ConcurrencyTracker::Reset(); - g_CurExecuted = g_ExecutedAtCatch = 0; - g_ExceptionCaught = false; - g_UnknownException = false; - g_ThrowException = throwException; - g_Flog = flog; - g_ExceptionsThrown = g_Exceptions = 0; -} - -#if TBB_USE_EXCEPTIONS -class test_exception : public std::exception { - const char* my_description; -public: - test_exception ( const char* description ) : my_description(description) {} - - const char* what() const throw() { return my_description; } -}; - -class solitary_test_exception : public test_exception { -public: - solitary_test_exception ( const char* description ) : test_exception(description) {} -}; - -#if TBB_USE_CAPTURED_EXCEPTION - typedef tbb::captured_exception PropagatedException; - #define EXCEPTION_NAME(e) e.name() -#else - typedef test_exception PropagatedException; - #define EXCEPTION_NAME(e) typeid(e).name() -#endif - -#define EXCEPTION_DESCR "Test exception" - -#if HARNESS_EH_SIMPLE_MODE - -static void ThrowTestException () { - ++g_ExceptionsThrown; - throw test_exception(EXCEPTION_DESCR); -} - -#else /* !HARNESS_EH_SIMPLE_MODE */ - -static void ThrowTestException ( intptr_t threshold ) { - if ( !g_ThrowException || (!g_Flog && (g_ExceptionInMaster ^ (Harness::CurrentTid() == g_Master))) ) - return; - while ( Existed() < threshold ) - __TBB_Yield(); - if ( !g_SolitaryException ) { - ++g_ExceptionsThrown; - throw test_exception(EXCEPTION_DESCR); - } - if ( g_ExceptionsThrown.compare_and_swap(1, 0) == 0 ) - throw solitary_test_exception(EXCEPTION_DESCR); -} -#endif /* !HARNESS_EH_SIMPLE_MODE */ - -#define CATCH() \ - } catch ( PropagatedException& e ) { \ - g_ExecutedAtCatch = g_CurExecuted; \ - ASSERT( e.what(), "Empty what() string" ); \ - ASSERT (__TBB_EXCEPTION_TYPE_INFO_BROKEN || strcmp(EXCEPTION_NAME(e), (g_SolitaryException ? typeid(solitary_test_exception) : typeid(test_exception)).name() ) == 0, "Unexpected original exception name"); \ - ASSERT (__TBB_EXCEPTION_TYPE_INFO_BROKEN || strcmp(e.what(), EXCEPTION_DESCR) == 0, "Unexpected original exception info"); \ - g_ExceptionCaught = exceptionCaught = true; \ - ++g_Exceptions; \ - } catch ( tbb::tbb_exception& e ) { \ - REPORT("Unexpected %s\n", e.name()); \ - ASSERT (g_UnknownException && !g_UnknownException, "Unexpected tbb::tbb_exception" ); \ - } catch ( std::exception& e ) { \ - REPORT("Unexpected %s\n", typeid(e).name()); \ - ASSERT (g_UnknownException && !g_UnknownException, "Unexpected std::exception" ); \ - } catch ( ... ) { \ - g_ExceptionCaught = exceptionCaught = true; \ - g_UnknownException = unknownException = true; \ - } \ - if ( !g_SolitaryException ) \ - REMARK_ONCE ("Multiple exceptions mode: %d throws", (intptr_t)g_ExceptionsThrown); - -#define ASSERT_EXCEPTION() \ - ASSERT (g_ExceptionsThrown ? g_ExceptionCaught : true, "throw without catch"); \ - ASSERT (!g_ExceptionsThrown ? !g_ExceptionCaught : true, "catch without throw"); \ - ASSERT (g_ExceptionCaught, "no exception occurred"); \ - ASSERT (__TBB_EXCEPTION_TYPE_INFO_BROKEN || !g_UnknownException, "unknown exception was caught") - -#define CATCH_AND_ASSERT() \ - CATCH() \ - ASSERT_EXCEPTION() - -#else /* !TBB_USE_EXCEPTIONS */ - -inline void ThrowTestException ( intptr_t ) {} - -#endif /* !TBB_USE_EXCEPTIONS */ - -#define TRY() \ - bool exceptionCaught = false, unknownException = false; \ - __TBB_TRY { - -// "exceptionCaught || unknownException" is used only to "touch" otherwise unused local variables -#define CATCH_AND_FAIL() } __TBB_CATCH(...) { \ - ASSERT (false, "Canceling tasks must not cause any exceptions"); \ - (void)(exceptionCaught && unknownException); \ - } - -const int c_Timeout = 1000000; - -void WaitUntilConcurrencyPeaks ( int expected_peak ) { - if ( g_Flog ) - return; - int n = 0; -retry: - while ( ++n < c_Timeout && (int)Harness::ConcurrencyTracker::PeakParallelism() < expected_peak ) - __TBB_Yield(); - ASSERT_WARNING( n < c_Timeout, "Missed wakeup or machine is overloaded?" ); - // Workaround in case a missed wakeup takes place - if ( n == c_Timeout ) { - tbb::task &r = *new( tbb::task::allocate_root() ) tbb::empty_task(); - r.spawn(r); - n = 0; - goto retry; - } -} - -inline void WaitUntilConcurrencyPeaks () { WaitUntilConcurrencyPeaks(g_NumThreads); } - -inline bool IsMaster() { - return Harness::CurrentTid() == g_Master; -} - -inline bool IsThrowingThread() { - return g_ExceptionInMaster ^ IsMaster() ? true : false; -} - -class CancellatorTask : public tbb::task { - static volatile bool s_Ready; - tbb::task_group_context &m_groupToCancel; - intptr_t m_cancellationThreshold; - - tbb::task* execute () { - Harness::ConcurrencyTracker ct; - s_Ready = true; - while ( g_CurExecuted < m_cancellationThreshold ) - __TBB_Yield(); - m_groupToCancel.cancel_group_execution(); - g_ExecutedAtCatch = g_CurExecuted; - return NULL; - } -public: - CancellatorTask ( tbb::task_group_context& ctx, intptr_t threshold ) - : m_groupToCancel(ctx), m_cancellationThreshold(threshold) - { - s_Ready = false; - } - - static void Reset () { s_Ready = false; } - - static bool WaitUntilReady () { - const intptr_t limit = 10000000; - intptr_t n = 0; - do { - __TBB_Yield(); - } while( !s_Ready && ++n < limit ); - ASSERT( s_Ready || n == limit, NULL ); - return s_Ready; - } -}; - -volatile bool CancellatorTask::s_Ready = false; - -template -void RunCancellationTest ( intptr_t threshold = 1 ) -{ - tbb::task_group_context ctx; - tbb::empty_task &r = *new( tbb::task::allocate_root(ctx) ) tbb::empty_task; - r.set_ref_count(3); - r.spawn( *new( r.allocate_child() ) CancellatorTaskT(ctx, threshold) ); - __TBB_Yield(); - r.spawn( *new( r.allocate_child() ) LauncherTaskT(ctx) ); - TRY(); - r.wait_for_all(); - CATCH_AND_FAIL(); - r.destroy(r); -} diff --git a/deal.II/contrib/tbb/tbb30_104oss/src/test/harness_inject_scheduler.h b/deal.II/contrib/tbb/tbb30_104oss/src/test/harness_inject_scheduler.h deleted file mode 100644 index 3c7ac61f1e..0000000000 --- a/deal.II/contrib/tbb/tbb30_104oss/src/test/harness_inject_scheduler.h +++ /dev/null @@ -1,62 +0,0 @@ -/* - Copyright 2005-2010 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. -*/ - -// Used in tests that work with TBB scheduler but do not link to the TBB library. -// In other words it embeds the TBB library core into the test executable. - -#ifndef harness_inject_scheduler_H -#define harness_inject_scheduler_H - -// Suppress usage of #pragma comment -#define __TBB_NO_IMPLICIT_LINKAGE 1 - -#define __TBB_TASK_CPP_DIRECTLY_INCLUDED 1 -#include "../tbb/tbb_main.cpp" - -// Tasking subsystem files -#include "../tbb/governor.cpp" -#if __TBB_ARENA_PER_MASTER -#include "../tbb/market.cpp" -#endif /* __TBB_ARENA_PER_MASTER */ -#include "../tbb/arena.cpp" -#include "../tbb/scheduler.cpp" -#include "../tbb/observer_proxy.cpp" -#include "../tbb/task.cpp" -#include "../tbb/task_group_context.cpp" - -// Other dependencies -#include "../tbb/cache_aligned_allocator.cpp" -#include "../tbb/dynamic_link.cpp" -#include "../tbb/tbb_thread.cpp" -#include "../tbb/mutex.cpp" -#include "../tbb/spin_rw_mutex.cpp" -#include "../tbb/spin_mutex.cpp" -#include "../tbb/private_server.cpp" -#include "../rml/client/rml_tbb.cpp" - -#endif /* harness_inject_scheduler_H */ diff --git a/deal.II/contrib/tbb/tbb30_104oss/src/test/harness_iterator.h b/deal.II/contrib/tbb/tbb30_104oss/src/test/harness_iterator.h deleted file mode 100644 index c3dbd02964..0000000000 --- a/deal.II/contrib/tbb/tbb30_104oss/src/test/harness_iterator.h +++ /dev/null @@ -1,130 +0,0 @@ -/* - Copyright 2005-2010 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 harness_iterator_H -#define harness_iterator_H - -#include -#include - -namespace Harness { - -template -class InputIterator { - T * my_ptr; -public: -#if HARNESS_EXTENDED_STD_COMPLIANCE - typedef std::input_iterator_tag iterator_category; - typedef T value_type; - typedef typename std::allocator::difference_type difference_type; - typedef typename std::allocator::pointer pointer; - typedef typename std::allocator::reference reference; -#endif /* HARNESS_EXTENDED_STD_COMPLIANCE */ - - explicit InputIterator( T * ptr): my_ptr(ptr){} - - T& operator* () { return *my_ptr; } - - InputIterator& operator++ () { ++my_ptr; return *this; } - - bool operator== ( const InputIterator& r ) { return my_ptr == r.my_ptr; } -}; - -template -class ForwardIterator { - T * my_ptr; -public: -#if HARNESS_EXTENDED_STD_COMPLIANCE - typedef std::forward_iterator_tag iterator_category; - typedef T value_type; - typedef typename std::allocator::difference_type difference_type; - typedef typename std::allocator::pointer pointer; - typedef typename std::allocator::reference reference; -#endif /* HARNESS_EXTENDED_STD_COMPLIANCE */ - - explicit ForwardIterator ( T * ptr ) : my_ptr(ptr){} - - ForwardIterator ( const ForwardIterator& r ) : my_ptr(r.my_ptr){} - - T& operator* () { return *my_ptr; } - - ForwardIterator& operator++ () { ++my_ptr; return *this; } - - bool operator== ( const ForwardIterator& r ) { return my_ptr == r.my_ptr; } -}; - -template -class RandomIterator { - T * my_ptr; -#if !HARNESS_EXTENDED_STD_COMPLIANCE - typedef typename std::allocator::difference_type difference_type; -#endif - -public: -#if HARNESS_EXTENDED_STD_COMPLIANCE - typedef std::random_access_iterator_tag iterator_category; - typedef T value_type; - typedef typename std::allocator::pointer pointer; - typedef typename std::allocator::reference reference; - typedef typename std::allocator::difference_type difference_type; -#endif /* HARNESS_EXTENDED_STD_COMPLIANCE */ - - explicit RandomIterator ( T * ptr ) : my_ptr(ptr){} - RandomIterator ( const RandomIterator& r ) : my_ptr(r.my_ptr){} - T& operator* () { return *my_ptr; } - RandomIterator& operator++ () { ++my_ptr; return *this; } - bool operator== ( const RandomIterator& r ) { return my_ptr == r.my_ptr; } - difference_type operator- (const RandomIterator &r) {return my_ptr - r.my_ptr;} - RandomIterator operator+ (difference_type n) {return RandomIterator(my_ptr + n);} -}; - -} // namespace Harness - -#if !HARNESS_EXTENDED_STD_COMPLIANCE -namespace std { - template - struct iterator_traits< Harness::InputIterator > { - typedef std::input_iterator_tag iterator_category; - typedef T value_type; - }; - - template - struct iterator_traits< Harness::ForwardIterator > { - typedef std::forward_iterator_tag iterator_category; - typedef T value_type; - }; - - template - struct iterator_traits< Harness::RandomIterator > { - typedef std::random_access_iterator_tag iterator_category; - typedef T value_type; - }; -} // namespace std -#endif /* !HARNESS_EXTENDED_STD_COMPLIANCE */ - -#endif //harness_iterator_H diff --git a/deal.II/contrib/tbb/tbb30_104oss/src/test/harness_m128.h b/deal.II/contrib/tbb/tbb30_104oss/src/test/harness_m128.h deleted file mode 100644 index 88cd15c974..0000000000 --- a/deal.II/contrib/tbb/tbb30_104oss/src/test/harness_m128.h +++ /dev/null @@ -1,81 +0,0 @@ -/* - Copyright 2005-2010 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. -*/ - -// Header that sets HAVE_m128 if we have type __m128 - -#if (__SSE__||_M_IX86) && !defined(__sun) -#include -#define HAVE_m128 1 - -//! Class for testing safety of using __m128 -/** Uses circuitous logic forces compiler to put __m128 objects on stack while - executing various methods, and thus tempt it to use aligned loads and stores - on the stack. */ -// Do not create file-scope objects of the class, because MinGW (as of May 2010) -// did not always provide proper stack alignment in destructors of such objects. -class ClassWithSSE { - static const int n = 16; - __m128 field[n]; - void init( int start ); -public: - ClassWithSSE() {init(-n);} - ClassWithSSE( int i ) {init(i);} - void operator=( const ClassWithSSE& src ) { - __m128 stack[n]; - for( int i=0; i -#include - -#elif __APPLE__ -#include -#include -#include -#if MAC_OS_X_VERSION_MIN_REQUIRED >= 1060 -#include -#else -#include -#endif -#if SHARED_TEXT_REGION_SIZE || SHARED_DATA_REGION_SIZE -const size_t shared_size = SHARED_TEXT_REGION_SIZE+SHARED_DATA_REGION_SIZE; -#else -const size_t shared_size = 0; -#endif - -#elif _WIN32 && !_XBOX -#include -#include -#if _MSC_VER -#pragma comment(lib, "psapi") -#endif - -#endif /* OS selection */ - -//! Return estimate of number of bytes of memory that this program is currently using. -/* Returns 0 if not implemented on platform. */ -size_t GetMemoryUsage() { -#if _XBOX - return 0; -#elif _WIN32 - PROCESS_MEMORY_COUNTERS mem; - bool status = GetProcessMemoryInfo(GetCurrentProcess(), &mem, sizeof(mem))!=0; - ASSERT(status, NULL); - return mem.PagefileUsage; -#elif __linux__ - FILE* statsfile = fopen("/proc/self/statm","r"); - size_t pagesize = getpagesize(); - ASSERT(statsfile, NULL); - long total_mem; - int n = fscanf(statsfile,"%lu",&total_mem); - if( n!=1 ) { - REPORT("Warning: memory usage statistics wasn't obtained\n"); - return 0; - } - fclose(statsfile); - return total_mem*pagesize; -#elif __APPLE__ - kern_return_t status; - task_basic_info info; - mach_msg_type_number_t msg_type = TASK_BASIC_INFO_COUNT; - status = task_info(mach_task_self(), TASK_BASIC_INFO, reinterpret_cast(&info), &msg_type); - ASSERT(status==KERN_SUCCESS, NULL); - return info.virtual_size - shared_size; -#else - return 0; -#endif -} - -//! Use approximately a specified amount of stack space. -/** Recursion is used here instead of alloca because some implementations of alloca do not use the stack. */ -void UseStackSpace( size_t amount, char* top=0 ) { - char x[1000]; - memset( x, -1, sizeof(x) ); - if( !top ) - top = x; - ASSERT( x<=top, "test assumes that stacks grow downwards" ); - if( size_t(top-x) -#else -#include -#endif - -#include - - -#ifdef HARNESS_INCOMPLETE_SOURCES -#error Source files are not complete. Check the build environment -#endif - -#if _MSC_VER - #define snprintf _snprintf -#if _MSC_VER<=1400 - #define vsnprintf _vsnprintf -#endif -#endif - -namespace Harness { - namespace internal { - -#ifndef TbbHarnessReporter - struct TbbHarnessReporter { - void Report ( const char* msg ) { - printf( "%s", msg ); - fflush(stdout); -#ifdef _WINDOWS_ - OutputDebugStringA(msg); -#endif - } - }; // struct TbbHarnessReporter -#endif /* !TbbHarnessReporter */ - - class Tracer { - int m_flags; - const char *m_file; - const char *m_func; - size_t m_line; - - TbbHarnessReporter m_reporter; - - public: - enum { - prefix = 1, - need_lf = 2 - }; - - Tracer* set_trace_info ( int flags, const char *file, size_t line, const char *func ) { - m_flags = flags; - m_line = line; - m_file = file; - m_func = func; - return this; - } - - void trace ( const char* fmt, ... ) { - char msg[MAX_TRACE_SIZE]; - char msg_fmt_buf[MAX_TRACE_SIZE]; - const char *msg_fmt = fmt; - if ( m_flags & prefix ) { - snprintf (msg_fmt_buf, MAX_TRACE_SIZE, "[%s] %s", m_func, fmt); - msg_fmt = msg_fmt_buf; - } - std::va_list argptr; - va_start (argptr, fmt); - int len = vsnprintf (msg, MAX_TRACE_SIZE, msg_fmt, argptr); - va_end (argptr); - if ( m_flags & need_lf && - len < MAX_TRACE_SIZE - 1 && msg_fmt[len-1] != '\n' ) - { - msg[len] = '\n'; - msg[len + 1] = 0; - } - m_reporter.Report(msg); - } - }; // class Tracer - - static Tracer tracer; - - template - bool not_the_first_call () { - static bool first_call = false; - bool res = first_call; - first_call = true; - return res; - } - - } // namespace internal -} // namespace Harness - -#if defined(_MSC_VER) && _MSC_VER >= 1300 || defined(__GNUC__) || defined(__GNUG__) - #define HARNESS_TRACE_ORIG_INFO __FILE__, __LINE__, __FUNCTION__ -#else - #define HARNESS_TRACE_ORIG_INFO __FILE__, __LINE__, "" - #define __FUNCTION__ "" -#endif - - -//! printf style tracing macro -/** This variant of TRACE adds trailing line-feed (new line) character, if it is absent. **/ -#define TRACE Harness::internal::tracer.set_trace_info(Harness::internal::Tracer::need_lf, HARNESS_TRACE_ORIG_INFO)->trace - -//! printf style tracing macro without automatic new line character adding -#define TRACENL Harness::internal::tracer.set_trace_info(0, HARNESS_TRACE_ORIG_INFO)->trace - -//! printf style tracing macro with additional information prefix (e.g. current function name) -#define TRACEP Harness::internal::tracer.set_trace_info(Harness::internal::Tracer::prefix | \ - Harness::internal::Tracer::need_lf, HARNESS_TRACE_ORIG_INFO)->trace - -//! printf style remark macro -/** Produces output only when the test is run with the -v (verbose) option. **/ -#define REMARK !Verbose ? (void)0 : TRACENL - -//! printf style remark macro -/** Produces output only when invoked first time. - Only one instance of this macro is allowed per source code line. **/ -#define REMARK_ONCE (!Verbose || Harness::internal::not_the_first_call<__LINE__>()) ? (void)0 : TRACE - -//! printf style reporting macro -/** On heterogeneous platforms redirects its output to the host side. **/ -#define REPORT TRACENL - -#endif /* tbb_tests_harness_report_H */ diff --git a/deal.II/contrib/tbb/tbb30_104oss/src/test/test_ScalableAllocator.cpp b/deal.II/contrib/tbb/tbb30_104oss/src/test/test_ScalableAllocator.cpp deleted file mode 100644 index b0c5904b13..0000000000 --- a/deal.II/contrib/tbb/tbb30_104oss/src/test/test_ScalableAllocator.cpp +++ /dev/null @@ -1,55 +0,0 @@ -/* - Copyright 2005-2010 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. -*/ - -// Test whether scalable_allocator complies with the requirements in 20.1.5 of ISO C++ Standard (1998). - -#define HARNESS_NO_PARSE_COMMAND_LINE 1 - -#include "tbb/scalable_allocator.h" - -// the actual body of the test is there: -#include "test_allocator.h" - -#if _MSC_VER -#include "tbb/machine/windows_api.h" -#endif /* _MSC_VER */ - -int TestMain () { -#if _MSC_VER && !__TBBMALLOC_NO_IMPLICIT_LINKAGE - #ifdef _DEBUG - ASSERT(!GetModuleHandle("tbbmalloc.dll") && GetModuleHandle("tbbmalloc_debug.dll"), - "test linked with wrong (non-debug) tbbmalloc library"); - #else - ASSERT(!GetModuleHandle("tbbmalloc_debug.dll") && GetModuleHandle("tbbmalloc.dll"), - "test linked with wrong (debug) tbbmalloc library"); - #endif -#endif /* _MSC_VER && !__TBBMALLOC_NO_IMPLICIT_LINKAGE */ - int result = TestMain >(); - ASSERT( !result, NULL ); - return Harness::Done; -} diff --git a/deal.II/contrib/tbb/tbb30_104oss/src/test/test_ScalableAllocator_STL.cpp b/deal.II/contrib/tbb/tbb30_104oss/src/test/test_ScalableAllocator_STL.cpp deleted file mode 100644 index 34c6d3cedc..0000000000 --- a/deal.II/contrib/tbb/tbb30_104oss/src/test/test_ScalableAllocator_STL.cpp +++ /dev/null @@ -1,40 +0,0 @@ -/* - Copyright 2005-2010 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. -*/ - -// Test whether scalable_allocator works with some of the host's STL containers. - -#define HARNESS_NO_PARSE_COMMAND_LINE 1 -#include "tbb/scalable_allocator.h" - -// The actual body of the test is there: -#include "test_allocator_STL.h" - -int TestMain () { - TestAllocatorWithSTL >(); - return Harness::Done; -} diff --git a/deal.II/contrib/tbb/tbb30_104oss/src/test/test_aligned_space.cpp b/deal.II/contrib/tbb/tbb30_104oss/src/test/test_aligned_space.cpp deleted file mode 100644 index 95d6c8ebae..0000000000 --- a/deal.II/contrib/tbb/tbb30_104oss/src/test/test_aligned_space.cpp +++ /dev/null @@ -1,119 +0,0 @@ -/* - Copyright 2005-2010 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. -*/ - -#include "tbb/tbb_config.h" - -#if __TBB_GCC_WARNING_SUPPRESSION_ENABLED -#pragma GCC diagnostic ignored "-Wstrict-aliasing" -#endif - -//! Wrapper around T where all members are private. -/** Used to prove that aligned_space never calls member of T. */ -template -class Minimal { - Minimal(); - Minimal( Minimal& min ); - ~Minimal(); - void operator=( const Minimal& ); - T pad; - template - friend void AssignToCheckAlignment( Minimal& dst, const Minimal& src ) ; -}; - -template -void AssignToCheckAlignment( Minimal& dst, const Minimal& src ) { - dst.pad = src.pad; -} - -#include "tbb/aligned_space.h" -#include "harness_assert.h" - -static bool SpaceWasted; - -template -void TestAlignedSpaceN() { - typedef Minimal T; - struct { - //! Pad byte increases chance that subsequent member will be misaligned if there is a problem. - char pad; - tbb::aligned_space space; - } x; - AssertSameType( static_cast< T *>(0), x.space.begin() ); - AssertSameType( static_cast< T *>(0), x.space.end() ); - ASSERT( reinterpret_cast(x.space.begin())==reinterpret_cast< void *>(&x.space), NULL ); - ASSERT( x.space.end()-x.space.begin()==N, NULL ); - ASSERT( reinterpret_cast(x.space.begin())>=reinterpret_cast< void *>(&x.space), NULL ); - ASSERT( x.space.end()<=reinterpret_cast< T *>(&x.space+1), NULL ); - // Though not required, a good implementation of aligned_space does not use any more space than a T[N]. - SpaceWasted |= sizeof(x.space)!=sizeof(T)*N; - for( size_t k=1; k - -template -void TestAlignedSpace() { - SpaceWasted = false; - TestAlignedSpaceN(); - TestAlignedSpaceN(); - TestAlignedSpaceN(); - TestAlignedSpaceN(); - TestAlignedSpaceN(); - TestAlignedSpaceN(); - TestAlignedSpaceN(); - TestAlignedSpaceN(); - if( SpaceWasted ) - PrintSpaceWastingWarning( typeid(T).name() ); -} - -#define HARNESS_NO_PARSE_COMMAND_LINE 1 -#include "harness.h" - -#include "harness_m128.h" - -int TestMain () { - TestAlignedSpace(); - TestAlignedSpace(); - TestAlignedSpace(); - TestAlignedSpace(); - TestAlignedSpace(); - TestAlignedSpace(); - TestAlignedSpace(); -#if HAVE_m128 - TestAlignedSpace<__m128>(); -#endif /* HAVE_m128 */ - return Harness::Done; -} - -static void PrintSpaceWastingWarning( const char* type_name ) { - REPORT("Consider rewriting aligned_space<%s,N> to waste less space\n", type_name ); -} - diff --git a/deal.II/contrib/tbb/tbb30_104oss/src/test/test_allocator.h b/deal.II/contrib/tbb/tbb30_104oss/src/test/test_allocator.h deleted file mode 100644 index d8a10e2b72..0000000000 --- a/deal.II/contrib/tbb/tbb30_104oss/src/test/test_allocator.h +++ /dev/null @@ -1,226 +0,0 @@ -/* - Copyright 2005-2010 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. -*/ - -// Basic testing of an allocator -// Tests against requirements in 20.1.5 of ISO C++ Standard (1998). -// Does not check for thread safety or false sharing issues. -// -// Tests for compatibility with the host's STL are in -// test_Allocator_STL.h. Those tests are in a separate file -// because they bring in lots of STL headers, and the tests here -// are supposed to work in the abscense of STL. - -#include "harness.h" - -template -struct is_zero_filling { - static const bool value = false; -}; - -int NumberOfFoo; - -template -struct Foo { - T foo_array[N]; - Foo() { - zero_fill(foo_array, N); - ++NumberOfFoo; - } - Foo( const Foo& x ) { - *this = x; - ++NumberOfFoo; - } - ~Foo() { - --NumberOfFoo; - } -}; - -inline char PseudoRandomValue( size_t j, size_t k ) { - return char(j*3 ^ j>>4 ^ k); -} - -//! T is type and A is allocator for that type -template -void TestBasic( A& a ) { - T x; - const T cx = T(); - - // See Table 32 in ISO ++ Standard - typename A::pointer px = &x; - typename A::const_pointer pcx = &cx; - - typename A::reference rx = x; - ASSERT( &rx==&x, NULL ); - - typename A::const_reference rcx = cx; - ASSERT( &rcx==&cx, NULL ); - - typename A::value_type v = x; - - typename A::size_type size; - size = 0; - --size; - ASSERT( size>0, "not an unsigned integral type?" ); - - typename A::difference_type difference; - difference = 0; - --difference; - ASSERT( difference<0, "not an signed integral type?" ); - - // "rebind" tested by our caller - - ASSERT( a.address(rx)==px, NULL ); - - ASSERT( a.address(rcx)==pcx, NULL ); - - typename A::pointer array[100]; - size_t sizeof_T = sizeof(T); - for( size_t k=0; k<100; ++k ) { - array[k] = k&1 ? a.allocate(k,array[0]) : a.allocate(k); - char* s = reinterpret_cast(reinterpret_cast(array[k])); - for( size_t j=0; j(reinterpret_cast(array[k])); - for( size_t j=0; j=a.max_size(), "max_size larger than reasonable" ); - - // Test "a1==a2" - A a1, a2; - ASSERT( a1==a2, NULL ); - - // Test "a1!=a2" - ASSERT( !(a1!=a2), NULL ); - - // Test "a.construct(p,t)" - int n = NumberOfFoo; - typename A::pointer p = a.allocate(1); - a.construct( p, cx ); - ASSERT( NumberOfFoo==n+1, "constructor for Foo not called?" ); - - // Test "a.destroy(p)" - a.destroy( p ); - ASSERT( NumberOfFoo==n, "destructor for Foo not called?" ); - a.deallocate(p,1); -} - -#include "tbb/blocked_range.h" - -#if _MSC_VER && !defined(__INTEL_COMPILER) - // Workaround for erroneous "conditional expression is constant" warning in method check_allocate. - #pragma warning (disable: 4127) -#endif - -// A is an allocator for some type -template -struct Body: NoAssign { - static const size_t max_k = 100000; - A &a; - Body(A &a_) : a(a_) {} - void check_allocate( typename A::pointer array[], size_t i, size_t t ) const - { - ASSERT(array[i] == 0, NULL); - size_t size = i * (i&3); - array[i] = i&1 ? a.allocate(size, array[i>>3]) : a.allocate(size); - char* s = reinterpret_cast(reinterpret_cast(array[i])); - for( size_t j=0; j::other>::value) - ASSERT( !s[j], NULL); - s[j] = PseudoRandomValue(i, t); - } - } - - void check_deallocate( typename A::pointer array[], size_t i, size_t t ) const - { - ASSERT(array[i] != 0, NULL); - size_t size = i * (i&3); - char* s = reinterpret_cast(reinterpret_cast(array[i])); - for( size_t j=0; j(PseudoRandomValue(k,thread_id)); - if(!array[i]) check_allocate(array, i, thread_id); - else check_deallocate(array, i, thread_id); - } - for( size_t k=0; k<256; ++k ) - if(array[k]) - check_deallocate(array, k, thread_id); - } -}; - -// A is an allocator for some type, and U is another type -template -void Test() { - typename A::template rebind::other b; - TestBasic(b); - - A a(b); - TestBasic(a); - - // thread safety - int n = NumberOfFoo; - NativeParallelFor( 4, Body(a) ); - ASSERT( NumberOfFoo==n, "Allocate/deallocate count mismatched" ); - - ASSERT( a==b, NULL ); - ASSERT( !(a!=b), NULL ); -} - -template -int TestMain() { - Test >::other, Foo >(); - Test >::other, Foo >(); - return 0; -} - diff --git a/deal.II/contrib/tbb/tbb30_104oss/src/test/test_allocator_STL.h b/deal.II/contrib/tbb/tbb30_104oss/src/test/test_allocator_STL.h deleted file mode 100644 index 54820c031e..0000000000 --- a/deal.II/contrib/tbb/tbb30_104oss/src/test/test_allocator_STL.h +++ /dev/null @@ -1,114 +0,0 @@ -/* - Copyright 2005-2010 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. -*/ - -// Tests for compatibility with the host's STL. - -#include "harness.h" - -template -void TestSequence() { - Container c; - for( int i=0; i<1000; ++i ) - c.push_back(i*i); - typename Container::const_iterator p = c.begin(); - for( int i=0; i<1000; ++i ) { - ASSERT( *p==i*i, NULL ); - ++p; - } -} - -template -void TestSet() { - Set s; - typedef typename Set::value_type value_type; - for( int i=0; i<100; ++i ) - s.insert(value_type(3*i)); - for( int i=0; i<300; ++i ) { - ASSERT( s.erase(i)==size_t(i%3==0), NULL ); - } -} - -template -void TestMap() { - Map m; - typedef typename Map::value_type value_type; - for( int i=0; i<100; ++i ) - m.insert(value_type(i,i*i)); - for( int i=0; i<100; ++i ) - ASSERT( m.find(i)->second==i*i, NULL ); -} - -#if !TBB_USE_EXCEPTIONS && _MSC_VER - // Suppress "C++ exception handler used, but unwind semantics are not enabled" warning in STL headers - #pragma warning (push) - #pragma warning (disable: 4530) -#endif - -#include -#include -#include -#include -#include - -#if !TBB_USE_EXCEPTIONS && _MSC_VER - #pragma warning (pop) -#endif - -template -void TestAllocatorWithSTL() { - typedef typename Allocator::template rebind::other Ai; - typedef typename Allocator::template rebind::other Aci; - typedef typename Allocator::template rebind >::other Acii; - typedef typename Allocator::template rebind >::other Aii; - - // Sequenced containers - TestSequence >(); - TestSequence >(); - TestSequence >(); - - // Associative containers - TestSet, Ai> >(); - TestSet, Ai> >(); - TestMap, Acii> >(); - TestMap, Acii> >(); - -#if _MSC_VER - // Test compatibility with Microsoft's implementation of std::allocator for some cases that - // are undefined according to the ISO standard but permitted by Microsoft. - TestSequence >(); -#if _CPPLIB_VER>=500 - TestSequence >(); -#endif - TestSequence >(); - TestSet, Aci> >(); - TestMap, Aii> >(); - TestMap, Acii> >(); - TestMap, Aii> >(); - TestMap, Acii> >(); -#endif /* _MSC_VER */ -} diff --git a/deal.II/contrib/tbb/tbb30_104oss/src/test/test_assembly.cpp b/deal.II/contrib/tbb/tbb30_104oss/src/test/test_assembly.cpp deleted file mode 100644 index 0496a13c7a..0000000000 --- a/deal.II/contrib/tbb/tbb30_104oss/src/test/test_assembly.cpp +++ /dev/null @@ -1,140 +0,0 @@ -/* - Copyright 2005-2010 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. -*/ - -// Program for basic correctness testing of assembly-language routines. - -#include "tbb/task.h" - -#include -#include "harness.h" - -using tbb::internal::reference_count; - -//! Test __TBB_CompareAndSwapW -static void TestCompareExchange() { - ASSERT( intptr_t(-10)<10, "intptr_t not a signed integral type?" ); - REMARK("testing __TBB_CompareAndSwapW\n"); - for( intptr_t a=-10; a<10; ++a ) - for( intptr_t b=-10; b<10; ++b ) - for( intptr_t c=-10; c<10; ++c ) { -// Workaround for a bug in GCC 4.3.0; and one more is below. -#if __GNUC__==4&&__GNUC_MINOR__==3&&__GNUC_PATCHLEVEL__==0 - intptr_t x; - __TBB_store_with_release( x, a ); -#else - intptr_t x = a; -#endif - intptr_t y = __TBB_CompareAndSwapW(&x,b,c); - ASSERT( y==a, NULL ); - if( a==c ) - ASSERT( x==b, NULL ); - else - ASSERT( x==a, NULL ); - } -} - -//! Test __TBB___TBB_FetchAndIncrement and __TBB___TBB_FetchAndDecrement -static void TestAtomicCounter() { - // "canary" is a value used to detect illegal overwrites. - const reference_count canary = ~(uintptr_t)0/3; - REMARK("testing __TBB_FetchAndIncrement\n"); - struct { - reference_count prefix, i, suffix; - } x; - x.prefix = canary; - x.i = 0; - x.suffix = canary; - for( int k=0; k<10; ++k ) { - reference_count j = __TBB_FetchAndIncrementWacquire((volatile void *)&x.i); - ASSERT( x.prefix==canary, NULL ); - ASSERT( x.suffix==canary, NULL ); - ASSERT( x.i==k+1, NULL ); - ASSERT( j==k, NULL ); - } - REMARK("testing __TBB_FetchAndDecrement\n"); - x.i = 10; - for( int k=10; k>0; --k ) { - reference_count j = __TBB_FetchAndDecrementWrelease((volatile void *)&x.i); - ASSERT( j==k, NULL ); - ASSERT( x.i==k-1, NULL ); - ASSERT( x.prefix==canary, NULL ); - ASSERT( x.suffix==canary, NULL ); - } -} - -static void TestTinyLock() { - REMARK("testing __TBB_LockByte\n"); - unsigned char flags[16]; - for( int i=0; i<16; ++i ) - flags[i] = (unsigned char)i; -#if __GNUC__==4&&__GNUC_MINOR__==3&&__GNUC_PATCHLEVEL__==0 - __TBB_store_with_release( flags[8], 0 ); -#else - flags[8] = 0; -#endif - __TBB_LockByte(flags[8]); - for( int i=0; i<16; ++i ) - #ifdef __sparc - ASSERT( flags[i]==(i==8?0xff:i), NULL ); - #else - ASSERT( flags[i]==(i==8?1:i), NULL ); - #endif -} - -static void TestLog2() { - REMARK("testing __TBB_Log2\n"); - for( uintptr_t i=1; i; i<<=1 ) { - for( uintptr_t j=1; j<1<<16; ++j ) { - if( uintptr_t k = i*j ) { - uintptr_t actual = __TBB_Log2(k); - const uintptr_t ONE = 1; // warning suppression again - ASSERT( k >= ONE<>1 < ONE< // memcmp - -#if _MSC_VER && !defined(__INTEL_COMPILER) - // unary minus operator applied to unsigned type, result still unsigned - #pragma warning( push ) - #pragma warning( disable: 4310 ) -#endif - -//! Structure that holds an atomic and some guard bytes around it. -template -struct TestStruct { - typedef unsigned char byte_type; - T prefix; - tbb::atomic counter; - T suffix; - TestStruct( T i ) { - ASSERT( sizeof(*this)==3*sizeof(T), NULL ); - for (size_t j = 0; j < sizeof(T); ++j) { - reinterpret_cast(&prefix)[j] = byte_type(0x11*(j+1)); - reinterpret_cast(&suffix)[sizeof(T)-j-1] = byte_type(0x11*(j+1)); - } - counter = i; - } - ~TestStruct() { - // Check for writes outside the counter. - for (size_t j = 0; j < sizeof(T); ++j) { - ASSERT( reinterpret_cast(&prefix)[j] == byte_type(0x11*(j+1)), NULL ); - ASSERT( reinterpret_cast(&suffix)[sizeof(T)-j-1] == byte_type(0x11*(j+1)), NULL ); - } - } -}; - -#if _MSC_VER && !defined(__INTEL_COMPILER) - #pragma warning( pop ) -#endif - -#if defined(__INTEL_COMPILER) - // reference to EBX in a function requiring stack alignment - #pragma warning( disable: 998 ) -#endif - -//! Test compare_and_swap template members of class atomic for memory_semantics=M -template -void TestCompareAndSwapAcquireRelease( T i, T j, T k ) { - ASSERT( i!=k, "values must be distinct" ); - // Test compare_and_swap that should fail - TestStruct x(i); - T old = x.counter.template compare_and_swap( j, k ); - ASSERT( old==i, NULL ); - ASSERT( x.counter==i, "old value not retained" ); - // Test compare and swap that should suceed - old = x.counter.template compare_and_swap( j, i ); - ASSERT( old==i, NULL ); - ASSERT( x.counter==j, "value not updated?" ); -} - -//! i, j, k must be different values -template -void TestCompareAndSwap( T i, T j, T k ) { - ASSERT( i!=k, "values must be distinct" ); - // Test compare_and_swap that should fail - TestStruct x(i); - T old = x.counter.compare_and_swap( j, k ); - ASSERT( old==i, NULL ); - ASSERT( x.counter==i, "old value not retained" ); - // Test compare and swap that should suceed - old = x.counter.compare_and_swap( j, i ); - ASSERT( old==i, NULL ); - if( x.counter==i ) { - ASSERT( x.counter==j, "value not updated?" ); - } else { - ASSERT( x.counter==j, "value trashed" ); - } - TestCompareAndSwapAcquireRelease(i,j,k); - TestCompareAndSwapAcquireRelease(i,j,k); -} - -//! memory_semantics variation on TestFetchAndStore -template -void TestFetchAndStoreAcquireRelease( T i, T j ) { - ASSERT( i!=j, "values must be distinct" ); - TestStruct x(i); - T old = x.counter.template fetch_and_store( j ); - ASSERT( old==i, NULL ); - ASSERT( x.counter==j, NULL ); -} - -//! i and j must be different values -template -void TestFetchAndStore( T i, T j ) { - ASSERT( i!=j, "values must be distinct" ); - TestStruct x(i); - T old = x.counter.fetch_and_store( j ); - ASSERT( old==i, NULL ); - ASSERT( x.counter==j, NULL ); - TestFetchAndStoreAcquireRelease(i,j); - TestFetchAndStoreAcquireRelease(i,j); -} - -#if _MSC_VER && !defined(__INTEL_COMPILER) - // conversion from to , possible loss of data - // the warning seems a complete nonsense when issued for e.g. short+=short - #pragma warning( push ) - #pragma warning( disable: 4244 ) -#endif - -//! Test fetch_and_add members of class atomic for memory_semantics=M -template -void TestFetchAndAddAcquireRelease( T i ) { - TestStruct x(i); - T actual; - T expected = i; - - // Test fetch_and_add member template - for( int j=0; j<10; ++j ) { - actual = x.counter.fetch_and_add(j); - ASSERT( actual==expected, NULL ); - expected += j; - } - for( int j=0; j<10; ++j ) { - actual = x.counter.fetch_and_add(-j); - ASSERT( actual==expected, NULL ); - expected -= j; - } - - // Test fetch_and_increment member template - ASSERT( x.counter==i, NULL ); - actual = x.counter.template fetch_and_increment(); - ASSERT( actual==i, NULL ); - ASSERT( x.counter==T(i+1), NULL ); - - // Test fetch_and_decrement member template - actual = x.counter.template fetch_and_decrement(); - ASSERT( actual==T(i+1), NULL ); - ASSERT( x.counter==i, NULL ); -} - -//! Test fetch_and_add and related operators -template -void TestFetchAndAdd( T i ) { - TestStruct x(i); - T value; - value = ++x.counter; - ASSERT( value==T(i+1), NULL ); - value = x.counter++; - ASSERT( value==T(i+1), NULL ); - value = x.counter--; - ASSERT( value==T(i+2), NULL ); - value = --x.counter; - ASSERT( value==i, NULL ); - T actual; - T expected = i; - for( int j=-100; j<=100; ++j ) { - expected += j; - actual = x.counter += j; - ASSERT( actual==expected, NULL ); - } - for( int j=-100; j<=100; ++j ) { - expected -= j; - actual = x.counter -= j; - ASSERT( actual==expected, NULL ); - } - // Test fetch_and_increment - ASSERT( x.counter==i, NULL ); - actual = x.counter.fetch_and_increment(); - ASSERT( actual==i, NULL ); - ASSERT( x.counter==T(i+1), NULL ); - - // Test fetch_and_decrement - actual = x.counter.fetch_and_decrement(); - ASSERT( actual==T(i+1), NULL ); - ASSERT( x.counter==i, NULL ); - x.counter = i; - ASSERT( x.counter==i, NULL ); - - TestFetchAndAddAcquireRelease(i); - TestFetchAndAddAcquireRelease(i); -} - -#if _MSC_VER && !defined(__INTEL_COMPILER) - #pragma warning( pop ) -#endif // warning 4244 is back - -//! A type with unknown size. -class IncompleteType; - -void TestFetchAndAdd( IncompleteType* ) { - // There are no fetch-and-add operations on a IncompleteType*. -} -void TestFetchAndAdd( void* ) { - // There are no fetch-and-add operations on a void*. -} - -void TestFetchAndAdd( bool ) { - // There are no fetch-and-add operations on a bool. -} - -template -void TestConst( T i ) { - // Try const - const TestStruct x(i); - ASSERT( memcmp( &i, &x.counter, sizeof(T) )==0, "write to atomic broken?" );; - ASSERT( x.counter==i, "read of atomic broken?" ); -} - -template -void TestOperations( T i, T j, T k ) { - TestConst(i); - TestCompareAndSwap(i,j,k); - TestFetchAndStore(i,k); // Pass i,k instead of i,j, because callee requires two distinct values. -} - -template -void TestParallel( const char* name ); - -bool ParallelError; - -template -struct AlignmentChecker { - char c; - tbb::atomic i; -}; - -#include "harness.h" - -#if _MSC_VER && !defined(__INTEL_COMPILER) - // unary minus operator applied to unsigned type, result still unsigned - #pragma warning( push ) - #pragma warning( disable: 4146 ) -#endif - -/** T is an integral type. */ -template -void TestAtomicInteger( const char* name ) { - REMARK("testing atomic<%s> (size=%d)\n",name,sizeof(tbb::atomic)); -#if ( __linux__ && __TBB_x86_32 && __GNUC__==3 && __GNUC_MINOR__==3 ) || defined(__SUNPRO_CC) - // gcc 3.3 has known problem for 32-bit Linux, so only warn if there is a problem. - // SUNPRO_CC does have this problem as well - if( sizeof(T)==8 ) { - if( sizeof(AlignmentChecker)!=2*sizeof(tbb::atomic) ) { - REPORT("Known issue: alignment for atomic<%s> is wrong with gcc 3.3 and sunCC 5.9 2008/01/28 for IA32\n",name); - } - } else -#endif /* ( __linux__ && __TBB_x86_32 && __GNUC__==3 && __GNUC_MINOR__==3 ) || defined(__SUNPRO_CC) */ - ASSERT( sizeof(AlignmentChecker)==2*sizeof(tbb::atomic), NULL ); - TestOperations(0L,T(-T(1)),T(1)); - for( int k=0; k(T(1L<(T(-1L<(T(-1L<( name ); -} - -#if _MSC_VER && !defined(__INTEL_COMPILER) - #pragma warning( pop ) -#endif - - -template -struct Foo { - T x, y, z; -}; - - -template -void TestIndirection() { - Foo item; - tbb::atomic*> pointer; - pointer = &item; - for( int k=-10; k<=10; ++k ) { - // Test various syntaxes for indirection to fields with non-zero offset. - T value1=T(), value2=T(); - for( size_t j=0; jy = value1; - (*pointer).z = value2; - T result1 = (*pointer).y; - T result2 = pointer->z; - ASSERT( memcmp(&value1,&result1,sizeof(T))==0, NULL ); - ASSERT( memcmp(&value2,&result2,sizeof(T))==0, NULL ); - } -} - -//! Test atomic -template -void TestAtomicPointer() { - REMARK("testing atomic pointer (%d)\n",int(sizeof(T))); - T array[1000]; - TestOperations(&array[500],&array[250],&array[750]); - TestFetchAndAdd(&array[500]); - TestIndirection(); - TestParallel( "pointer" ); -} - -//! Test atomic where Ptr is a pointer to a type of unknown size -template -void TestAtomicPointerToTypeOfUnknownSize( const char* name ) { - REMARK("testing atomic<%s>\n",name); - char array[1000]; - TestOperations((Ptr)(void*)&array[500],(Ptr)(void*)&array[250],(Ptr)(void*)&array[750]); - TestParallel( name ); -} - -void TestAtomicBool() { - REMARK("testing atomic\n"); - TestOperations(true,true,false); - TestOperations(false,false,true); - TestParallel( "bool" ); -} - -enum Color {Red=0,Green=1,Blue=-1}; - -void TestAtomicEnum() { - REMARK("testing atomic\n"); - TestOperations(Red,Green,Blue); - TestParallel( "Color" ); -} - -template -void TestAtomicFloat( const char* name ) { - REMARK("testing atomic<%s>\n", name ); - TestOperations(0.5,3.25,10.75); - TestParallel( name ); -} - -const int numMaskedOperations = 100000; -const int testSpaceSize = 8; -int prime[testSpaceSize] = {3,5,7,11,13,17,19,23}; - -#if _MSC_VER && !defined(__INTEL_COMPILER) - // "possible loss of data" warning suppressed again - #pragma warning( push ) - #pragma warning( disable: 4244 ) -#endif - -template -class TestMaskedCAS_Body: NoAssign { - T* test_space_uncontended; - T* test_space_contended; -public: - TestMaskedCAS_Body( T* _space1, T* _space2 ) : test_space_uncontended(_space1), test_space_contended(_space2) {} - void operator()( int my_idx ) const { - using tbb::internal::__TBB_MaskedCompareAndSwap; - const T my_prime = T(prime[my_idx]); - T* const my_ptr = test_space_uncontended+my_idx; - T old_value=0; - for( int i=0; i(my_ptr,new_value,old_value-1); - ASSERT(result!=old_value-1, "masked CAS succeeded while it should fail"); - ASSERT(result==*my_ptr, "masked CAS result mismatch with real value"); - // The following one should succeed - result = __TBB_MaskedCompareAndSwap(my_ptr,new_value,old_value); - ASSERT(result==old_value && *my_ptr==new_value, "masked CAS failed while it should succeed"); - // The following one should fail again - result = __TBB_MaskedCompareAndSwap(my_ptr,new_value,old_value); - ASSERT(result!=old_value, "masked CAS succeeded while it should fail"); - ASSERT(result==*my_ptr, "masked CAS result mismatch with real value"); - // Test contended case - for( int j=0; j(test_space_contended+j,value+my_prime,value); - } while( result!=value ); - } - } - } -}; - -template -struct intptr_as_array_of -{ - static const int how_many_Ts = sizeof(intptr_t)/sizeof(T); - union { - intptr_t result; - T space[ how_many_Ts ]; - }; -}; - -template -intptr_t getCorrectUncontendedValue(int slot_idx) { - intptr_as_array_of slot; - slot.result = 0; - for( int i=0; i -intptr_t getCorrectContendedValue() { - intptr_as_array_of slot; - slot.result = 0; - for( int i=0; i -void TestMaskedCAS() { - REMARK("testing masked CAS<%d>\n",int(sizeof(T))); - - const int num_slots = sizeof(T)*testSpaceSize/sizeof(intptr_t); - intptr_t arr1[num_slots+2]; // two more "canary" slots at boundaries - intptr_t arr2[num_slots+2]; - for(int i=0; i(test_space_uncontended, test_space_contended) ); - - ASSERT( arr1[0]==0 && arr1[num_slots+1]==0 && arr2[0]==0 && arr2[num_slots+1]==0 , "adjacent memory was overwritten" ); - const intptr_t correctContendedValue = getCorrectContendedValue(); - for(int i=0; i(i), "unexpected value in an uncontended slot" ); - ASSERT( arr2[i+1]==correctContendedValue, "unexpected value in a contended slot" ); - } -} - -template -class ArrayElement { - char item[N]; -}; - -int TestMain () { - TestAtomicInteger("unsigned long long"); - TestAtomicInteger("long long"); - TestAtomicInteger("unsigned long"); - TestAtomicInteger("long"); - TestAtomicInteger("unsigned int"); - TestAtomicInteger("int"); - TestAtomicInteger("unsigned short"); - TestAtomicInteger("short"); - TestAtomicInteger("signed char"); - TestAtomicInteger("unsigned char"); - TestAtomicInteger("char"); - TestAtomicInteger("wchar_t"); - TestAtomicInteger("size_t"); - TestAtomicInteger("ptrdiff_t"); - TestAtomicPointer >(); - TestAtomicPointer >(); - TestAtomicPointer >(); - TestAtomicPointer >(); - TestAtomicPointer >(); - TestAtomicPointer >(); - TestAtomicPointer >(); - TestAtomicPointer >(); - TestAtomicPointerToTypeOfUnknownSize( "IncompleteType*" ); - TestAtomicPointerToTypeOfUnknownSize( "void*" ); - TestAtomicBool(); - TestAtomicEnum(); - TestAtomicFloat("float"); - TestAtomicFloat("double"); - ASSERT( !ParallelError, NULL ); - TestMaskedCAS(); - TestMaskedCAS(); - return Harness::Done; -} - -template -struct FlagAndMessage { - //! 0 if message not set yet, 1 if message is set. - tbb::atomic flag; - /** Force flag and message to be on distinct cache lines for machines with cache line size <= 4096 bytes */ - char pad[4096/sizeof(T)]; - //! Non-zero if message is ready - T message; -}; - -// A special template function used for summation. -// Actually it is only necessary because of its specialization for void* -template -T special_sum(intptr_t arg1, intptr_t arg2) { - return (T)((T)arg1 + arg2); -} - -// The specialization for IncompleteType* is required -// because pointer arithmetic (+) is impossible with IncompleteType* -template<> -IncompleteType* special_sum(intptr_t arg1, intptr_t arg2) { - return (IncompleteType*)(arg1 + arg2); -} - -// The specialization for void* is required -// because pointer arithmetic (+) is impossible with void* -template<> -void* special_sum(intptr_t arg1, intptr_t arg2) { - return (void*)(arg1 + arg2); -} - -// The specialization for bool is required to shut up gratuitous compiler warnings, -// because some compilers warn about casting int to bool. -template<> -bool special_sum(intptr_t arg1, intptr_t arg2) { - return ((arg1!=0) + arg2)!=0; -} - -volatile int One = 1; - -template -class HammerLoadAndStoreFence: NoAssign { - FlagAndMessage* fam; - const int n; - const int p; - const int trial; - const char* name; - mutable T accum; -public: - HammerLoadAndStoreFence( FlagAndMessage* fam_, int n_, int p_, const char* name_, int trial_ ) : fam(fam_), n(n_), p(p_), trial(trial_), name(name_) {} - void operator()( int k ) const { - int one = One; - FlagAndMessage* s = fam+k; - FlagAndMessage* s_next = fam + (k+1)%p; - for( int i=0; iflag; - message = s->message; - } else { - flag = s->flag; - message = s->message; - } - if( flag ) { - if( flag!=(T)-1 ) { - REPORT("ERROR: flag!=(T)-1 k=%d i=%d trial=%x type=%s (atomicity problem?)\n", k, i, trial, name ); - ParallelError = true; - } - if( message!=(T)-1 ) { - REPORT("ERROR: message!=(T)-1 k=%d i=%d trial=%x type=%s (memory fence problem?)\n", k, i, trial, name ); - ParallelError = true; - } - s->message = T(0); - s->flag = T(0); - // Set message and then the flag - if( trial&2 ) { - // COMPLICATED_ZERO here tempts compiler to sink store below setting of flag - s_next->message = special_sum(-1, COMPLICATED_ZERO); - s_next->flag = (T)-1; - } else { - s_next->message = (T)-1; - s_next->flag = (T)-1; - } - break; - } else { - // Force compiler to use message anyway, so it cannot sink read of s->message below the if. - accum = message; - } - } - } - } -}; - -//! Test that atomic has acquire semantics for loads and release semantics for stores. -/** Test performs round-robin passing of message among p processors, - where p goes from MinThread to MaxThread. */ -template -void TestLoadAndStoreFences( const char* name ) { - for( int p=MinThread<2 ? 2 : MinThread; p<=MaxThread; ++p ) { - FlagAndMessage* fam = new FlagAndMessage[p]; - // Each of four trials excercise slightly different expresion pattern within the test. - // See occurrences of COMPLICATED_ZERO for details. - for( int trial=0; trial<4; ++trial ) { - memset( fam, 0, p*sizeof(FlagAndMessage) ); - fam->message = (T)-1; - fam->flag = (T)-1; - NativeParallelFor( p, HammerLoadAndStoreFence( fam, 100, p, name, trial ) ); - for( int k=0; k -class SparseValueSet { - T factor; -public: - SparseValueSet() { - // Compute factor such that: - // 1. It has at least one 1 in most of its bytes. - // 2. The bytes are typically different. - // 3. When multiplied by any value <=127, the product does not overflow. - factor = T(0); - for( unsigned i=0; i -class SparseValueSet { - SparseValueSet my_set; -public: - T* get( int i ) const {return reinterpret_cast(my_set.get(i));} - bool contains( T* x ) const {return my_set.contains(reinterpret_cast(x));} -}; - -//! Specialization for bool. -/** Checking bool for atomic read/write is pointless in practice, because - there is no way to *not* atomically read or write a bool value. */ -template<> -class SparseValueSet { -public: - bool get( int i ) const {return i&1;} - bool contains( bool ) const {return true;} -}; - -#if _MSC_VER==1500 && !defined(__INTEL_COMPILER) - // VS2008/VC9 seems to have an issue; limits pull in math.h - #pragma warning( push ) - #pragma warning( disable: 4985 ) -#endif -#include /* Need std::numeric_limits */ -#if _MSC_VER==1500 && !defined(__INTEL_COMPILER) - #pragma warning( pop ) -#endif - -//! Commonality inherited by specializations for floating-point types. -template -class SparseFloatSet: NoAssign { - const T epsilon; -public: - SparseFloatSet() : epsilon(std::numeric_limits::epsilon()) {} - T get( int i ) const { - return i==0 ? T(0) : 1/T((i&0x7F)+1); - } - bool contains( T x ) const { - if( x==T(0) ) { - return true; - } else { - int j = int(1/x+T(0.5)); - if( 0 -class SparseValueSet: public SparseFloatSet {}; - -template<> -class SparseValueSet: public SparseFloatSet {}; - -template -class HammerAssignment: NoAssign { - tbb::atomic& x; - const char* name; - SparseValueSet set; -public: - HammerAssignment( tbb::atomic& x_, const char* name_ ) : x(x_), name(name_) {} - void operator()( int k ) const { - const int n = 1000000; - if( k ) { - tbb::atomic z; - AssertSameType( z=x, z ); // Check that return type from assignment is correct - for( int i=0; i is not atomic\n", name); - ParallelError = true; - return; - } - } - } else { - tbb::atomic y; - for( int i=0; i void TestAssignmentSignature( T& (T::*)(const T&) ) {} - -#if _MSC_VER && !defined(__INTEL_COMPILER) - // Suppress "conditional expression is constant" warning. - #pragma warning( push ) - #pragma warning( disable: 4127 ) -#endif - -template -void TestAssignment( const char* name ) { - TestAssignmentSignature( &tbb::atomic::operator= ); - tbb::atomic x; - x = T(0); - NativeParallelFor( 2, HammerAssignment( x, name ) ); -#if __TBB_x86_32 && (__linux__ || __FreeBSD__ || _WIN32) - if( sizeof(T)==8 ) { - // 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 atomic and atomic use different tactics depending upon - // whether the object is properly aligned or not. The following abusive test ensures that we - // cover both the proper and improper alignment cases, one with the x above and the other with - // the y below, perhaps not respectively. - - // Allocate space big enough to always contain 8-byte locations that are aligned and misaligned. - char raw_space[15]; - // Set delta to 0 if x is aligned, 4 otherwise. - uintptr_t delta = ((reinterpret_cast(&x)&7) ? 0 : 4); - // y crosses 8-byte boundary if and only if x does not cross. - tbb::atomic& y = *reinterpret_cast*>((reinterpret_cast(&raw_space[7+delta])&~7u) - delta); - // Assertion checks that y really did end up somewhere inside "raw_space". - ASSERT( raw_space<=reinterpret_cast(&y), "y starts before raw_space" ); - ASSERT( reinterpret_cast(&y+1) <= raw_space+sizeof(raw_space), "y starts after raw_space" ); - y = T(0); - NativeParallelFor( 2, HammerAssignment( y, name ) ); - } -#endif /* __TBB_x86_32 && (__linux__ || __FreeBSD__ || _WIN32) */ -} - -#if _MSC_VER && !defined(__INTEL_COMPILER) - #pragma warning( pop ) -#endif - -template -void TestParallel( const char* name ) { - TestLoadAndStoreFences(name); - TestAssignment(name); -} diff --git a/deal.II/contrib/tbb/tbb30_104oss/src/test/test_blocked_range.cpp b/deal.II/contrib/tbb/tbb30_104oss/src/test/test_blocked_range.cpp deleted file mode 100644 index 2ee2c885a9..0000000000 --- a/deal.II/contrib/tbb/tbb30_104oss/src/test/test_blocked_range.cpp +++ /dev/null @@ -1,128 +0,0 @@ -/* - Copyright 2005-2010 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. -*/ - -#include "tbb/blocked_range.h" -#include "harness_assert.h" - -// First test as much as we can without including other headers. -// Doing so should catch problems arising from failing to include headers. - -class AbstractValueType { - AbstractValueType() {} - int value; -public: - friend AbstractValueType MakeAbstractValueType( int i ); - friend int GetValueOf( const AbstractValueType& v ) {return v.value;} -}; - -AbstractValueType MakeAbstractValueType( int i ) { - AbstractValueType x; - x.value = i; - return x; -} - -std::size_t operator-( const AbstractValueType& u, const AbstractValueType& v ) { - return GetValueOf(u)-GetValueOf(v); -} - -bool operator<( const AbstractValueType& u, const AbstractValueType& v ) { - return GetValueOf(u) range_type; - range_type r( i, j, k ); - AssertSameType( r.empty(), true ); - AssertSameType( range_type::size_type(), std::size_t() ); - AssertSameType( static_cast(0), static_cast(0) ); - AssertSameType( r.begin(), MakeAbstractValueType(0) ); - AssertSameType( r.end(), MakeAbstractValueType(0) ); - ASSERT( r.empty()==(y<=x), NULL ); - ASSERT( r.grainsize()==k, NULL ); - if( x<=y ) { - AssertSameType( r.is_divisible(), true ); - ASSERT( r.is_divisible()==(std::size_t(y-x)>k), NULL ); - ASSERT( r.size()==std::size_t(y-x), NULL ); - if( r.is_divisible() ) { - tbb::blocked_range r2(r,tbb::split()); - ASSERT( GetValueOf(r.begin())==x, NULL ); - ASSERT( GetValueOf(r.end())==GetValueOf(r2.begin()), NULL ); - ASSERT( GetValueOf(r2.end())==y, NULL ); - ASSERT( r.grainsize()==k, NULL ); - ASSERT( r2.grainsize()==k, NULL ); - } - } - } - } -} - -#include "tbb/parallel_for.h" -#include "harness.h" - -const int N = 1<<22; - -unsigned char Array[N]; - -struct Striker { - // Note: we use here instead of in order to test for Quad 407676 - void operator()( const tbb::blocked_range& r ) const { - for( tbb::blocked_range::const_iterator i=r.begin(); i!=r.end(); ++i ) - ++Array[i]; - } -}; - -void ParallelTest() { - for( int i=0; i r( 0, i, 10 ); - tbb::parallel_for( r, Striker() ); - for( int k=0; k -class AbstractValueType { - AbstractValueType() {} - int value; -public: - template - friend AbstractValueType MakeAbstractValueType( int i ); - - template - friend int GetValueOf( const AbstractValueType& v ) ; -}; - -template -AbstractValueType MakeAbstractValueType( int i ) { - AbstractValueType x; - x.value = i; - return x; -} - -template -int GetValueOf( const AbstractValueType& v ) {return v.value;} - -template -bool operator<( const AbstractValueType& u, const AbstractValueType& v ) { - return GetValueOf(u) -std::size_t operator-( const AbstractValueType& u, const AbstractValueType& v ) { - return GetValueOf(u)-GetValueOf(v); -} - -template -AbstractValueType operator+( const AbstractValueType& u, std::size_t offset ) { - return MakeAbstractValueType(GetValueOf(u)+int(offset)); -} - -struct RowTag {}; -struct ColTag {}; - -static void SerialTest() { - typedef AbstractValueType row_type; - typedef AbstractValueType col_type; - typedef tbb::blocked_range2d range_type; - for( int rowx=-10; rowx<10; ++rowx ) { - for( int rowy=rowx; rowy<10; ++rowy ) { - row_type rowi = MakeAbstractValueType(rowx); - row_type rowj = MakeAbstractValueType(rowy); - for( int rowg=1; rowg<10; ++rowg ) { - for( int colx=-10; colx<10; ++colx ) { - for( int coly=colx; coly<10; ++coly ) { - col_type coli = MakeAbstractValueType(colx); - col_type colj = MakeAbstractValueType(coly); - for( int colg=1; colg<10; ++colg ) { - range_type r( rowi, rowj, rowg, coli, colj, colg ); - AssertSameType( r.is_divisible(), true ); - AssertSameType( r.empty(), true ); - AssertSameType( static_cast(0), static_cast(0) ); - AssertSameType( static_cast(0), static_cast(0) ); - AssertSameType( r.rows(), tbb::blocked_range( rowi, rowj, 1 )); - AssertSameType( r.cols(), tbb::blocked_range( coli, colj, 1 )); - ASSERT( r.empty()==(rowx==rowy||colx==coly), NULL ); - ASSERT( r.is_divisible()==(rowy-rowx>rowg||coly-colx>colg), NULL ); - if( r.is_divisible() ) { - range_type r2(r,tbb::split()); - if( GetValueOf(r2.rows().begin())==GetValueOf(r.rows().begin()) ) { - ASSERT( GetValueOf(r2.rows().end())==GetValueOf(r.rows().end()), NULL ); - ASSERT( GetValueOf(r2.cols().begin())==GetValueOf(r.cols().end()), NULL ); - } else { - ASSERT( GetValueOf(r2.cols().end())==GetValueOf(r.cols().end()), NULL ); - ASSERT( GetValueOf(r2.rows().begin())==GetValueOf(r.rows().end()), NULL ); - } - } - } - } - } - } - } - } -} - -#include "tbb/parallel_for.h" -#include "harness.h" - -const int N = 1<<10; - -unsigned char Array[N][N]; - -struct Striker { - // Note: we use here instead of in order to test for problems similar to Quad 407676 - void operator()( const tbb::blocked_range2d& r ) const { - for( tbb::blocked_range::const_iterator i=r.rows().begin(); i!=r.rows().end(); ++i ) - for( tbb::blocked_range::const_iterator j=r.cols().begin(); j!=r.cols().end(); ++j ) - ++Array[i][j]; - } -}; - -void ParallelTest() { - for( int i=0; i r( 0, i, 7, 0, j, 5 ); - tbb::parallel_for( r, Striker() ); - for( int k=0; k -class AbstractValueType { - AbstractValueType() {} - int value; -public: - template - friend AbstractValueType MakeAbstractValueType( int i ); - - template - friend int GetValueOf( const AbstractValueType& v ) ; -}; - -template -AbstractValueType MakeAbstractValueType( int i ) { - AbstractValueType x; - x.value = i; - return x; -} - -template -int GetValueOf( const AbstractValueType& v ) {return v.value;} - -template -bool operator<( const AbstractValueType& u, const AbstractValueType& v ) { - return GetValueOf(u) -std::size_t operator-( const AbstractValueType& u, const AbstractValueType& v ) { - return GetValueOf(u)-GetValueOf(v); -} - -template -AbstractValueType operator+( const AbstractValueType& u, std::size_t offset ) { - return MakeAbstractValueType(GetValueOf(u)+int(offset)); -} - -struct PageTag {}; -struct RowTag {}; -struct ColTag {}; - -static void SerialTest() { - typedef AbstractValueType page_type; - typedef AbstractValueType row_type; - typedef AbstractValueType col_type; - typedef tbb::blocked_range3d range_type; - for( int pagex=-4; pagex<4; ++pagex ) { - for( int pagey=pagex; pagey<4; ++pagey ) { - page_type pagei = MakeAbstractValueType(pagex); - page_type pagej = MakeAbstractValueType(pagey); - for( int pageg=1; pageg<4; ++pageg ) { - for( int rowx=-4; rowx<4; ++rowx ) { - for( int rowy=rowx; rowy<4; ++rowy ) { - row_type rowi = MakeAbstractValueType(rowx); - row_type rowj = MakeAbstractValueType(rowy); - for( int rowg=1; rowg<4; ++rowg ) { - for( int colx=-4; colx<4; ++colx ) { - for( int coly=colx; coly<4; ++coly ) { - col_type coli = MakeAbstractValueType(colx); - col_type colj = MakeAbstractValueType(coly); - for( int colg=1; colg<4; ++colg ) { - range_type r( pagei, pagej, pageg, rowi, rowj, rowg, coli, colj, colg ); - AssertSameType( r.is_divisible(), true ); - - AssertSameType( r.empty(), true ); - - AssertSameType( static_cast(0), static_cast(0) ); - AssertSameType( static_cast(0), static_cast(0) ); - AssertSameType( static_cast(0), static_cast(0) ); - - AssertSameType( r.pages(), tbb::blocked_range( pagei, pagej, 1 )); - AssertSameType( r.rows(), tbb::blocked_range( rowi, rowj, 1 )); - AssertSameType( r.cols(), tbb::blocked_range( coli, colj, 1 )); - - ASSERT( r.empty()==(pagex==pagey||rowx==rowy||colx==coly), NULL ); - - ASSERT( r.is_divisible()==(pagey-pagex>pageg||rowy-rowx>rowg||coly-colx>colg), NULL ); - - if( r.is_divisible() ) { - range_type r2(r,tbb::split()); - if( (GetValueOf(r2.pages().begin())==GetValueOf(r.pages().begin())) && (GetValueOf(r2.rows().begin())==GetValueOf(r.rows().begin())) ) { - ASSERT( GetValueOf(r2.pages().end())==GetValueOf(r.pages().end()), NULL ); - ASSERT( GetValueOf(r2.rows().end())==GetValueOf(r.rows().end()), NULL ); - ASSERT( GetValueOf(r2.cols().begin())==GetValueOf(r.cols().end()), NULL ); - } else { - if ( (GetValueOf(r2.pages().begin())==GetValueOf(r.pages().begin())) && (GetValueOf(r2.cols().begin())==GetValueOf(r.cols().begin())) ) { - ASSERT( GetValueOf(r2.pages().end())==GetValueOf(r.pages().end()), NULL ); - ASSERT( GetValueOf(r2.cols().end())==GetValueOf(r.cols().end()), NULL ); - ASSERT( GetValueOf(r2.rows().begin())==GetValueOf(r.rows().end()), NULL ); - } else { - ASSERT( GetValueOf(r2.rows().end())==GetValueOf(r.rows().end()), NULL ); - ASSERT( GetValueOf(r2.cols().end())==GetValueOf(r.cols().end()), NULL ); - ASSERT( GetValueOf(r2.pages().begin())==GetValueOf(r.pages().end()), NULL ); - } - } - } - } - } - } - } - } - } - } - } - } -} - -#include "tbb/parallel_for.h" -#include "harness.h" - -const int N = 1<<5; - -unsigned char Array[N][N][N]; - -struct Striker { - // Note: we use here instead of in order to test for problems similar to Quad 407676 - void operator()( const tbb::blocked_range3d& r ) const { - for( tbb::blocked_range::const_iterator i=r.pages().begin(); i!=r.pages().end(); ++i ) - for( tbb::blocked_range::const_iterator j=r.rows().begin(); j!=r.rows().end(); ++j ) - for( tbb::blocked_range::const_iterator k=r.cols().begin(); k!=r.cols().end(); ++k ) - ++Array[i][j][k]; - } -}; - -void ParallelTest() { - for( int i=0; i r( 0, i, 5, 0, j, 3, 0, k, 1 ); - tbb::parallel_for( r, Striker() ); - for( int l=0; l -struct is_zero_filling > { - static const bool value = true; -}; - -int TestMain () { - int result = TestMain >(); - result += TestMain >(); - result += TestMain >(); - ASSERT( !result, NULL ); - return Harness::Done; -} diff --git a/deal.II/contrib/tbb/tbb30_104oss/src/test/test_cache_aligned_allocator_STL.cpp b/deal.II/contrib/tbb/tbb30_104oss/src/test/test_cache_aligned_allocator_STL.cpp deleted file mode 100644 index 7e9d16752c..0000000000 --- a/deal.II/contrib/tbb/tbb30_104oss/src/test/test_cache_aligned_allocator_STL.cpp +++ /dev/null @@ -1,43 +0,0 @@ -/* - Copyright 2005-2010 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. -*/ - -// Test whether cache_aligned_allocator works with some of the host's STL containers. - -#include "tbb/cache_aligned_allocator.h" -#include "tbb/tbb_allocator.h" - -#define HARNESS_NO_PARSE_COMMAND_LINE 1 -#include "test_allocator_STL.h" - -int TestMain () { - TestAllocatorWithSTL >(); - TestAllocatorWithSTL >(); - TestAllocatorWithSTL >(); - return Harness::Done; -} - diff --git a/deal.II/contrib/tbb/tbb30_104oss/src/test/test_cilk_interop.cpp b/deal.II/contrib/tbb/tbb30_104oss/src/test/test_cilk_interop.cpp deleted file mode 100644 index 382f519c09..0000000000 --- a/deal.II/contrib/tbb/tbb30_104oss/src/test/test_cilk_interop.cpp +++ /dev/null @@ -1,216 +0,0 @@ -/* - Copyright 2005-2010 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. -*/ - -#include "tbb/tbb_config.h" -#include "harness.h" - -#if __TBB_SURVIVE_THREAD_SWITCH && __INTEL_COMPILER >= 1200 - -static const int N = 14; -static const int P_outer = 4; -static const int P_nested = 2; - -#include -#define private public -#include "tbb/task.h" -#undef private -#include "tbb/task_scheduler_init.h" -#include -#include - -enum tbb_sched_injection_mode_t { - tbbsched_none = 0, - tbbsched_explicit_only = 1, - tbbsched_auto_only = 2, - tbbsched_mixed = 3 -}; - -tbb_sched_injection_mode_t g_sim = tbbsched_none; - -bool g_sandwich = false; - -// A time delay routine -void Delay( int n ) { - static volatile int Global; - for( int k=0; k<10000; ++k ) - for( int i=0; i -#include -#include - -#if !TBB_USE_EXCEPTIONS && _MSC_VER - #pragma warning (pop) -#endif - -#include "harness_assert.h" -#include "harness.h" - -#if __TBB_GCC_WARNING_SUPPRESSION_ENABLED -#pragma GCC diagnostic ignored "-Wuninitialized" -#endif - -static tbb::atomic construction_counter; -static tbb::atomic destruction_counter; - -const int REPETITIONS = 10; -const int N = 100000; -const int VALID_NUMBER_OF_KEYS = 100; -const double EXPECTED_SUM = (REPETITIONS + 1) * N; - -// -// A minimal class -// Define: default and copy constructor, and allow implicit operator& -// also operator= -// - -class minimal { -private: - int my_value; -public: - minimal(int val=0) : my_value(val) { ++construction_counter; } - minimal( const minimal &m ) : my_value(m.my_value) { ++construction_counter; } - minimal& operator=(const minimal& other) { my_value = other.my_value; return *this; } - minimal& operator+=(const minimal& other) { my_value += other.my_value; return *this; } - operator int() const { return my_value; } - ~minimal() { ++destruction_counter; } - void set_value( const int i ) { my_value = i; } - int value( ) const { return my_value; } -}; - -//// functors for initialization and combine - -// Addition -template -struct FunctorAddFinit { - T operator()() { return 0; } -}; - -template -struct FunctorAddFinit7 { - T operator()() { return 7; } -}; - -template -struct FunctorAddCombine { - T operator()(T left, T right ) const { - return left + right; - } -}; - -template -struct FunctorAddCombineRef { - T operator()(const T& left, const T& right ) const { - return left + right; - } -}; - -template -T my_finit( ) { return 0; } - -template -T my_combine( T left, T right) { return left + right; } - -template -T my_combine_ref( const T &left, const T &right) { return left + right; } - -template -class CombineEachHelper { -public: - CombineEachHelper(T& _result) : my_result(_result) {} - void operator()(const T& new_bit) { my_result += new_bit; } - CombineEachHelper& operator=(const CombineEachHelper& other) { - my_result = other; - return *this; - } -private: - T& my_result; -}; - -template -class CombineEachHelperCnt { -public: - CombineEachHelperCnt(T& _result, int& _nbuckets) : my_result(_result), nBuckets(_nbuckets) {} - void operator()(const T& new_bit) { my_result += new_bit; ++nBuckets; } - CombineEachHelperCnt& operator=(const CombineEachHelperCnt& other) { - my_result = other.my_result; - nBuckets = other.nBuckets; - return *this; - } -private: - T& my_result; - int& nBuckets; -}; - -template -class CombineEachVectorHelper { -public: - typedef std::vector > ContainerType; - CombineEachVectorHelper(T& _result) : my_result(_result) { } - void operator()(const ContainerType& new_bit) { - for(typename ContainerType::const_iterator ci = new_bit.begin(); ci != new_bit.end(); ++ci) { - my_result += *ci; - } - } - CombineEachVectorHelper& operator=(const CombineEachVectorHelper& other) { my_result=other.my_result; return *this;} -private: - T& my_result; -}; - - - -//// end functors - -template< typename T > -void run_serial_scalar_tests(const char *test_name) { - tbb::tick_count t0; - T sum = 0; - - REMARK("Testing serial %s... ", test_name); - for (int t = -1; t < REPETITIONS; ++t) { - if (Verbose && t == 0) t0 = tbb::tick_count::now(); - for (int i = 0; i < N; ++i) { - sum += 1; - } - } - - double ResultValue = sum; - ASSERT( EXPECTED_SUM == ResultValue, NULL); - REMARK("done\nserial %s, 0, %g, %g\n", test_name, ResultValue, ( tbb::tick_count::now() - t0).seconds()); -} - - -template -class ParallelScalarBody: NoAssign { - - tbb::combinable &sums; - -public: - - ParallelScalarBody ( tbb::combinable &_sums ) : sums(_sums) { } - - void operator()( const tbb::blocked_range &r ) const { - for (int i = r.begin(); i != r.end(); ++i) { - bool was_there; - T& my_local = sums.local(was_there); - if(!was_there) my_local = 0; - my_local += 1 ; - } - } - -}; - -// parallel body with no test for first access. -template -class ParallelScalarBodyNoInit: NoAssign { - - tbb::combinable &sums; - -public: - - ParallelScalarBodyNoInit ( tbb::combinable &_sums ) : sums(_sums) { } - - void operator()( const tbb::blocked_range &r ) const { - for (int i = r.begin(); i != r.end(); ++i) { - sums.local() += 1 ; - } - } - -}; - -template< typename T > -void RunParallelScalarTests(const char *test_name) { - - tbb::task_scheduler_init init(tbb::task_scheduler_init::deferred); - - for (int p = MinThread; p <= MaxThread; ++p) { - - - if (p == 0) continue; - - REMARK("Testing parallel %s on %d thread(s)... ", test_name, p); - init.initialize(p); - - tbb::tick_count t0; - - T assign_sum(0); - - T combine_sum(0); - - T combine_ref_sum(0); - - T combine_each_sum(0); - - T combine_finit_sum(0); - - for (int t = -1; t < REPETITIONS; ++t) { - if (Verbose && t == 0) t0 = tbb::tick_count::now(); - - tbb::combinable sums; - FunctorAddFinit my_finit_decl; - tbb::combinable finit_combinable(my_finit_decl); - - - tbb::parallel_for( tbb::blocked_range( 0, N, 10000 ), ParallelScalarBodyNoInit( finit_combinable ) ); - tbb::parallel_for( tbb::blocked_range( 0, N, 10000 ), ParallelScalarBody( sums ) ); - - // Use combine - combine_sum += sums.combine(my_combine); - combine_ref_sum += sums.combine(my_combine_ref); - - CombineEachHelper my_helper(combine_each_sum); - sums.combine_each(my_helper); - - // test assignment - tbb::combinable assigned; - assigned = sums; - - assign_sum += assigned.combine(my_combine); - - combine_finit_sum += finit_combinable.combine(my_combine); - } - - ASSERT( EXPECTED_SUM == combine_sum, NULL); - ASSERT( EXPECTED_SUM == combine_ref_sum, NULL); - ASSERT( EXPECTED_SUM == assign_sum, NULL); - ASSERT( EXPECTED_SUM == combine_finit_sum, NULL); - - REMARK("done\nparallel %s, %d, %g, %g\n", test_name, p, static_cast(combine_sum), - ( tbb::tick_count::now() - t0).seconds()); - init.terminate(); - } -} - - -template -class ParallelVectorForBody: NoAssign { - - tbb::combinable< std::vector > > &locals; - -public: - - ParallelVectorForBody ( tbb::combinable< std::vector > > &_locals ) : locals(_locals) { } - - void operator()( const tbb::blocked_range &r ) const { - T one = 1; - - for (int i = r.begin(); i < r.end(); ++i) { - locals.local().push_back( one ); - } - } - -}; - -template< typename T > -void RunParallelVectorTests(const char *test_name) { - tbb::tick_count t0; - tbb::task_scheduler_init init(tbb::task_scheduler_init::deferred); - typedef std::vector > ContainerType; - - for (int p = MinThread; p <= MaxThread; ++p) { - - if (p == 0) continue; - REMARK("Testing parallel %s on %d thread(s)... ", test_name, p); - init.initialize(p); - - T sum = 0; - T sum2 = 0; - T sum3 = 0; - - for (int t = -1; t < REPETITIONS; ++t) { - if (Verbose && t == 0) t0 = tbb::tick_count::now(); - typedef typename tbb::combinable< ContainerType > CombinableType; - CombinableType vs; - - tbb::parallel_for ( tbb::blocked_range (0, N, 10000), ParallelVectorForBody( vs ) ); - - // copy construct - CombinableType vs2(vs); // this causes an assertion failure, related to allocators... - - // assign - CombinableType vs3; - vs3 = vs; - - CombineEachVectorHelper MyCombineEach(sum); - vs.combine_each(MyCombineEach); - - CombineEachVectorHelper MyCombineEach2(sum2); - vs2.combine_each(MyCombineEach2); - - CombineEachVectorHelper MyCombineEach3(sum3); - vs2.combine_each(MyCombineEach3); - // combine_each sums all elements of each vector into the result. - } - - double ResultValue = sum; - ASSERT( EXPECTED_SUM == ResultValue, NULL); - ResultValue = sum2; - ASSERT( EXPECTED_SUM == ResultValue, NULL); - ResultValue = sum3; - ASSERT( EXPECTED_SUM == ResultValue, NULL); - REMARK("done\nparallel %s, %d, %g, %g\n", test_name, p, ResultValue, ( tbb::tick_count::now() - t0).seconds()); - init.terminate(); - } -} - -#include "harness_barrier.h" - -Harness::SpinBarrier sBarrier; - -struct Body : NoAssign { - tbb::combinable* locals; - const int nthread; - const int nIters; - Body( int nthread_, int niters_ ) : nthread(nthread_), nIters(niters_) { sBarrier.initialize(nthread_); } - - - void operator()(int thread_id ) const { - bool existed; - sBarrier.wait(); - for(int i = 0; i < nIters; ++i ) { - existed = thread_id & 1; - int oldval = locals->local(existed); - ASSERT(existed == (i > 0), "Error on first reference"); - ASSERT(!existed || (oldval == thread_id), "Error on fetched value"); - existed = thread_id & 1; - locals->local(existed) = thread_id; - ASSERT(existed, "Error on assignment"); - } - } -}; - -void -TestLocalAllocations( int nthread ) { - ASSERT(nthread > 0, "nthread must be positive"); -#define NITERATIONS 1000 - Body myBody(nthread, NITERATIONS); - tbb::combinable myCombinable; - myBody.locals = &myCombinable; - - NativeParallelFor( nthread, myBody ); - - int mySum = 0; - int mySlots = 0; - CombineEachHelperCnt myCountCombine(mySum, mySlots); - myCombinable.combine_each(myCountCombine); - - ASSERT(nthread == mySlots, "Incorrect number of slots"); - ASSERT(mySum == (nthread - 1) * nthread / 2, "Incorrect values in result"); -} - - -void -RunParallelTests() { - RunParallelScalarTests("int"); - RunParallelScalarTests("double"); - RunParallelScalarTests("minimal"); - RunParallelVectorTests("std::vector >"); - RunParallelVectorTests("std::vector >"); -} - -template -void -RunAssignmentAndCopyConstructorTest(const char *test_name) { - REMARK("Testing assignment and copy construction for %s\n", test_name); - - // test creation with finit function (combine returns finit return value if no threads have created locals) - FunctorAddFinit7 my_finit7_decl; - tbb::combinable create2(my_finit7_decl); - ASSERT(7 == create2.combine(my_combine), NULL); - - // test copy construction with function initializer - tbb::combinable copy2(create2); - ASSERT(7 == copy2.combine(my_combine), NULL); - - // test copy assignment with function initializer - FunctorAddFinit my_finit_decl; - tbb::combinable assign2(my_finit_decl); - assign2 = create2; - ASSERT(7 == assign2.combine(my_combine), NULL); -} - -void -RunAssignmentAndCopyConstructorTests() { - REMARK("Running assignment and copy constructor tests\n"); - RunAssignmentAndCopyConstructorTest("int"); - RunAssignmentAndCopyConstructorTest("double"); - RunAssignmentAndCopyConstructorTest("minimal"); -} - -int TestMain () { - if (MaxThread > 0) { - RunParallelTests(); - } - RunAssignmentAndCopyConstructorTests(); - for(int i = 1 <= MinThread ? MinThread : 1; i <= MaxThread; ++i) { - REMARK("Testing local() allocation with nthreads=%d\n", i); - for(int j = 0; j < 100; ++j) { - TestLocalAllocations(i); - } - } - return Harness::Done; -} - diff --git a/deal.II/contrib/tbb/tbb30_104oss/src/test/test_concurrent_hash_map.cpp b/deal.II/contrib/tbb/tbb30_104oss/src/test/test_concurrent_hash_map.cpp deleted file mode 100644 index 79dc35197f..0000000000 --- a/deal.II/contrib/tbb/tbb30_104oss/src/test/test_concurrent_hash_map.cpp +++ /dev/null @@ -1,918 +0,0 @@ -/* - Copyright 2005-2010 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_USE_PERFORMANCE_WARNINGS -#define TBB_USE_PERFORMANCE_WARNINGS 1 -#endif - -// Our tests usually include the header under test first. But this test needs -// to use the preprocessor to edit the identifier runtime_warning in concurrent_hash_map.h. -// Hence we include a few other headers before doing the abusive edit. -#include "tbb/tbb_stddef.h" /* Defines runtime_warning */ -#include "harness_assert.h" /* Prerequisite for defining hooked_warning */ - -// The symbol internal::runtime_warning is normally an entry point into the TBB library. -// Here for sake of testing, we define it to be hooked_warning, a routine peculiar to this unit test. -#define runtime_warning hooked_warning - -static bool bad_hashing = false; - -namespace tbb { - namespace internal { - static void hooked_warning( const char* /*format*/, ... ) { - ASSERT(bad_hashing, "unexpected runtime_warning: bad hashing"); - } - } // namespace internal -} // namespace tbb -#define __TBB_EXTRA_DEBUG 1 // enables additional checks -#include "tbb/concurrent_hash_map.h" - -// Restore runtime_warning as an entry point into the TBB library. -#undef runtime_warning - -namespace Jungle { - struct Tiger {}; - size_t tbb_hasher( const Tiger& ) {return 0;} -} - -#if !defined(_MSC_VER) || _MSC_VER>=1400 || __INTEL_COMPILER -void test_ADL() { - tbb::tbb_hash_compare::hash(Jungle::Tiger()); // Instantiation chain finds tbb_hasher via Argument Dependent Lookup -} -#endif - -struct UserDefinedKeyType { -}; - -namespace tbb { - // Test whether tbb_hash_compare can be partially specialized as stated in Reference manual. - template<> struct tbb_hash_compare { - size_t hash( UserDefinedKeyType ) const {return 0;} - bool equal( UserDefinedKeyType /*x*/, UserDefinedKeyType /*y*/ ) {return true;} - }; -} - -tbb::concurrent_hash_map TestInstantiationWithUserDefinedKeyType; - -// Test whether a sufficient set of headers were included to instantiate a concurernt_hash_map. OSS Bug #120 (& #130): -// http://www.threadingbuildingblocks.org/bug_desc.php?id=120 -tbb::concurrent_hash_map,const char*>,int> TestInstantiation; - -#include "tbb/parallel_for.h" -#include "tbb/blocked_range.h" -#include "tbb/atomic.h" -#include "tbb/tick_count.h" -#include "harness.h" -#include "harness_allocator.h" - -class MyException : public std::bad_alloc { -public: - virtual const char *what() const throw() { return "out of items limit"; } - virtual ~MyException() throw() {} -}; - -/** Has tightly controlled interface so that we can verify - that concurrent_hash_map uses only the required interface. */ -class MyKey { -private: - void operator=( const MyKey& ); // Deny access - int key; - friend class MyHashCompare; - friend class YourHashCompare; -public: - static MyKey make( int i ) { - MyKey result; - result.key = i; - return result; - } - int value_of() const {return key;} -}; - -tbb::atomic MyDataCount; -long MyDataCountLimit = 0; - -class MyData { -protected: - friend class MyData2; - int data; - enum state_t { - LIVE=0x1234, - DEAD=0x5678 - } my_state; - void operator=( const MyData& ); // Deny access -public: - MyData(int i = 0) { - my_state = LIVE; - data = i; - if(MyDataCountLimit && MyDataCount + 1 >= MyDataCountLimit) - __TBB_THROW( MyException() ); - ++MyDataCount; - } - MyData( const MyData& other ) { - ASSERT( other.my_state==LIVE, NULL ); - my_state = LIVE; - data = other.data; - if(MyDataCountLimit && MyDataCount + 1 >= MyDataCountLimit) - __TBB_THROW( MyException() ); - ++MyDataCount; - } - ~MyData() { - --MyDataCount; - my_state = DEAD; - } - static MyData make( int i ) { - MyData result; - result.data = i; - return result; - } - int value_of() const { - ASSERT( my_state==LIVE, NULL ); - return data; - } - void set_value( int i ) { - ASSERT( my_state==LIVE, NULL ); - data = i; - } - bool operator==( const MyData& other ) const { - ASSERT( other.my_state==LIVE, NULL ); - ASSERT( my_state==LIVE, NULL ); - return data == other.data; - } -}; - -class MyData2 : public MyData { -public: - MyData2( ) {} - MyData2( const MyData& other ) { - ASSERT( other.my_state==LIVE, NULL ); - ASSERT( my_state==LIVE, NULL ); - data = other.data; - } - void operator=( const MyData& other ) { - ASSERT( other.my_state==LIVE, NULL ); - ASSERT( my_state==LIVE, NULL ); - data = other.data; - } - void operator=( const MyData2& other ) { - ASSERT( other.my_state==LIVE, NULL ); - ASSERT( my_state==LIVE, NULL ); - data = other.data; - } - bool operator==( const MyData2& other ) const { - ASSERT( other.my_state==LIVE, NULL ); - ASSERT( my_state==LIVE, NULL ); - return data == other.data; - } -}; - -class MyHashCompare { -public: - bool equal( const MyKey& j, const MyKey& k ) const { - return j.key==k.key; - } - unsigned long hash( const MyKey& k ) const { - return k.key; - } -}; - -class YourHashCompare { -public: - bool equal( const MyKey& j, const MyKey& k ) const { - return j.key==k.key; - } - unsigned long hash( const MyKey& ) const { - return 1; - } -}; - -typedef local_counting_allocator > MyAllocator; -typedef tbb::concurrent_hash_map MyTable; -typedef tbb::concurrent_hash_map MyTable2; -typedef tbb::concurrent_hash_map YourTable; - -template -inline void CheckAllocator(MyTable &table, size_t expected_allocs, size_t expected_frees, bool exact = true) { - size_t items_allocated = table.get_allocator().items_allocated, items_freed = table.get_allocator().items_freed; - size_t allocations = table.get_allocator().allocations, frees = table.get_allocator().frees; - REMARK("checking allocators: items %u/%u, allocs %u/%u\n", - unsigned(items_allocated), unsigned(items_freed), unsigned(allocations), unsigned(frees) ); - ASSERT( items_allocated == allocations, NULL); ASSERT( items_freed == frees, NULL); - if(exact) { - ASSERT( allocations == expected_allocs, NULL); ASSERT( frees == expected_frees, NULL); - } else { - ASSERT( allocations >= expected_allocs, NULL); ASSERT( frees >= expected_frees, NULL); - ASSERT( allocations - frees == expected_allocs - expected_frees, NULL ); - } -} - -inline bool UseKey( size_t i ) { - return (i&3)!=3; -} - -struct Insert { - static void apply( MyTable& table, int i ) { - if( UseKey(i) ) { - if( i&4 ) { - MyTable::accessor a; - table.insert( a, MyKey::make(i) ); - if( i&1 ) - (*a).second.set_value(i*i); - else - a->second.set_value(i*i); - } else - if( i&1 ) { - MyTable::accessor a; - table.insert( a, std::make_pair(MyKey::make(i), MyData(i*i)) ); - ASSERT( (*a).second.value_of()==i*i, NULL ); - } else { - MyTable::const_accessor ca; - table.insert( ca, std::make_pair(MyKey::make(i), MyData(i*i)) ); - ASSERT( ca->second.value_of()==i*i, NULL ); - } - } - } -}; - -struct Find { - static void apply( MyTable& table, int i ) { - MyTable::accessor a; - const MyTable::accessor& ca = a; - bool b = table.find( a, MyKey::make(i) ); - ASSERT( b==!a.empty(), NULL ); - if( b ) { - if( !UseKey(i) ) - REPORT("Line %d: unexpected key %d present\n",__LINE__,i); - AssertSameType( &*a, static_cast(0) ); - ASSERT( ca->second.value_of()==i*i, NULL ); - ASSERT( (*ca).second.value_of()==i*i, NULL ); - if( i&1 ) - ca->second.set_value( ~ca->second.value_of() ); - else - (*ca).second.set_value( ~ca->second.value_of() ); - } else { - if( UseKey(i) ) - REPORT("Line %d: key %d missing\n",__LINE__,i); - } - } -}; - -struct FindConst { - static void apply( const MyTable& table, int i ) { - MyTable::const_accessor a; - const MyTable::const_accessor& ca = a; - bool b = table.find( a, MyKey::make(i) ); - ASSERT( b==(table.count(MyKey::make(i))>0), NULL ); - ASSERT( b==!a.empty(), NULL ); - ASSERT( b==UseKey(i), NULL ); - if( b ) { - AssertSameType( &*ca, static_cast(0) ); - ASSERT( ca->second.value_of()==~(i*i), NULL ); - ASSERT( (*ca).second.value_of()==~(i*i), NULL ); - } - } -}; - -tbb::atomic EraseCount; - -struct Erase { - static void apply( MyTable& table, int i ) { - bool b; - if(i&4) { - if(i&8) { - MyTable::const_accessor a; - b = table.find( a, MyKey::make(i) ) && table.erase( a ); - } else { - MyTable::accessor a; - b = table.find( a, MyKey::make(i) ) && table.erase( a ); - } - } else - b = table.erase( MyKey::make(i) ); - if( b ) ++EraseCount; - ASSERT( table.count(MyKey::make(i)) == 0, NULL ); - } -}; - -static const int IE_SIZE = 2; -tbb::atomic InsertEraseCount[IE_SIZE]; - -struct InsertErase { - static void apply( YourTable& table, int i ) { - if ( i%3 ) { - int key = i%IE_SIZE; - if ( table.insert( std::make_pair(MyKey::make(key), MyData2()) ) ) - ++InsertEraseCount[key]; - } else { - int key = i%IE_SIZE; - if( i&1 ) { - YourTable::accessor res; - if(table.find( res, MyKey::make(key) ) && table.erase( res ) ) - --InsertEraseCount[key]; - } else { - YourTable::const_accessor res; - if(table.find( res, MyKey::make(key) ) && table.erase( res ) ) - --InsertEraseCount[key]; - } - } - } -}; - -// Test for the deadlock discussed at: -// http://softwarecommunity.intel.com/isn/Community/en-US/forums/permalink/30253302/30253302/ShowThread.aspx#30253302 -struct InnerInsert { - static void apply( YourTable& table, int i ) { - YourTable::accessor a1, a2; - if(i&1) __TBB_Yield(); - table.insert( a1, MyKey::make(1) ); - __TBB_Yield(); - table.insert( a2, MyKey::make(1 + (1<<30)) ); // the same chain - table.erase( a2 ); // if erase by key it would lead to deadlock for single thread - } -}; - -template -class TableOperation: NoAssign { - MyTable& my_table; -public: - void operator()( const tbb::blocked_range& range ) const { - for( int i=range.begin(); i!=range.end(); ++i ) - Op::apply(my_table,i); - } - TableOperation( MyTable& table ) : my_table(table) {} -}; - -template -void DoConcurrentOperations( TableType& table, int n, const char* what, int nthread ) { - REMARK("testing %s with %d threads\n",what,nthread); - tbb::tick_count t0 = tbb::tick_count::now(); - tbb::parallel_for( tbb::blocked_range(0,n,100), TableOperation(table) ); - tbb::tick_count t1 = tbb::tick_count::now(); - REMARK("time for %s = %g with %d threads\n",what,(t1-t0).seconds(),nthread); -} - -//! Test traversing the table with an iterator. -void TraverseTable( MyTable& table, size_t n, size_t expected_size ) { - REMARK("testing traversal\n"); - size_t actual_size = table.size(); - ASSERT( actual_size==expected_size, NULL ); - size_t count = 0; - bool* array = new bool[n]; - memset( array, 0, n*sizeof(bool) ); - const MyTable& const_table = table; - MyTable::const_iterator ci = const_table.begin(); - for( MyTable::iterator i = table.begin(); i!=table.end(); ++i ) { - // Check iterator - int k = i->first.value_of(); - ASSERT( UseKey(k), NULL ); - ASSERT( (*i).first.value_of()==k, NULL ); - ASSERT( 0<=k && size_t(k) er = table.equal_range(i->first); - std::pair cer = const_table.equal_range(i->first); - ASSERT(cer.first == er.first && cer.second == er.second, NULL); - ASSERT(cer.first == i, NULL); - ASSERT(std::distance(cer.first, cer.second) == 1, NULL); - - // Check const_iterator - MyTable::const_iterator cic = ci++; - ASSERT( cic->first.value_of()==k, NULL ); - ASSERT( (*cic).first.value_of()==k, NULL ); - } - ASSERT( ci==const_table.end(), NULL ); - delete[] array; - if( count!=expected_size ) { - REPORT("Line %d: count=%ld but should be %ld\n",__LINE__,long(count),long(expected_size)); - } -} - -typedef tbb::atomic AtomicByte; - -template -struct ParallelTraverseBody: NoAssign { - const size_t n; - AtomicByte* const array; - ParallelTraverseBody( AtomicByte array_[], size_t n_ ) : - n(n_), - array(array_) - {} - void operator()( const RangeType& range ) const { - for( typename RangeType::iterator i = range.begin(); i!=range.end(); ++i ) { - int k = i->first.value_of(); - ASSERT( 0<=k && size_t(k)( array, n )); - Check( array, n, expected_size ); - - const MyTable& const_table = table; - memset( array, 0, n*sizeof(AtomicByte) ); - MyTable::const_range_type cr = const_table.range(10); - tbb::parallel_for( cr, ParallelTraverseBody( array, n )); - Check( array, n, expected_size ); - - delete[] array; -} - -void TestInsertFindErase( int nthread ) { - int n=250000; - - // compute m = number of unique keys - int m = 0; - for( int i=0; i(table,n,"insert",nthread); - ASSERT( MyDataCount==m, NULL ); - TraverseTable(table,n,m); - ParallelTraverseTable(table,n,m); - CheckAllocator(table, m, 100); - - DoConcurrentOperations(table,n,"find",nthread); - ASSERT( MyDataCount==m, NULL ); - CheckAllocator(table, m, 100); - - DoConcurrentOperations(table,n,"find(const)",nthread); - ASSERT( MyDataCount==m, NULL ); - CheckAllocator(table, m, 100); - - EraseCount=0; - DoConcurrentOperations(table,n,"erase",nthread); - ASSERT( EraseCount==m, NULL ); - ASSERT( MyDataCount==0, NULL ); - TraverseTable(table,n,0); - CheckAllocator(table, m, m+100); - - bad_hashing = true; - table.clear(); - bad_hashing = false; - - if(nthread > 1) { - YourTable ie_table; - for( int i=0; i(ie_table,n/2,"insert_erase",nthread); - for( int i=0; i(ie_table,2000,"inner insert",nthread); - } -} - -volatile int Counter; - -class AddToTable: NoAssign { - MyTable& my_table; - const int my_nthread; - const int my_m; -public: - AddToTable( MyTable& table, int nthread, int m ) : my_table(table), my_nthread(nthread), my_m(m) {} - void operator()( int ) const { - for( int i=0; isecond.set_value( 1 ); - else - a->second.set_value( a->second.value_of()+1 ); - k = a->second.value_of(); - } - if( k==my_nthread ) - Counter=i+1; - } - } -}; - -class RemoveFromTable: NoAssign { - MyTable& my_table; - const int my_nthread; - const int my_m; -public: - RemoveFromTable( MyTable& table, int nthread, int m ) : my_table(table), my_nthread(nthread), my_m(m) {} - void operator()(int) const { - for( int i=0; i(0), static_cast(0) ); - AssertSameType( static_cast(0), static_cast(0) ); - AssertSameType( static_cast(0), static_cast*>(0) ); - AssertSameType( static_cast(0), static_cast(0) ); - AssertSameType( static_cast(0), static_cast(0) ); - AssertSameType( static_cast(0), static_cast(0) ); - AssertSameType( static_cast(0), static_cast(0) ); -} - -template -void TestIteratorTraits() { - AssertSameType( static_cast(0), static_cast(0) ); - AssertSameType( static_cast(0), static_cast(0) ); - AssertSameType( static_cast(0), static_cast(0) ); - AssertSameType( static_cast(0), static_cast(0) ); - T x; - typename Iterator::reference xr = x; - typename Iterator::pointer xp = &x; - ASSERT( &xr==xp, NULL ); -} - -template -void TestIteratorAssignment( Iterator2 j ) { - Iterator1 i(j), k; - ASSERT( i==j, NULL ); ASSERT( !(i!=j), NULL ); - k = j; - ASSERT( k==j, NULL ); ASSERT( !(k!=j), NULL ); -} - -template -void TestRangeAssignment( Range2 r2 ) { - Range1 r1(r2); r1 = r2; -} -//------------------------------------------------------------------------ -// Test for copy constructor and assignment -//------------------------------------------------------------------------ - -template -static void FillTable( MyTable& x, int n ) { - for( int i=1; i<=n; ++i ) { - MyKey key( MyKey::make(-i) ); // hash values must not be specified in direct order - typename MyTable::accessor a; - bool b = x.insert(a,key); - ASSERT(b, NULL); - a->second.set_value( i*i ); - } -} - -template -static void CheckTable( const MyTable& x, int n ) { - ASSERT( x.size()==size_t(n), "table is different size than expected" ); - ASSERT( x.empty()==(n==0), NULL ); - ASSERT( x.size()<=x.max_size(), NULL ); - for( int i=1; i<=n; ++i ) { - MyKey key( MyKey::make(-i) ); - typename MyTable::const_accessor a; - bool b = x.find(a,key); - ASSERT( b, NULL ); - ASSERT( a->second.value_of()==i*i, NULL ); - } - int count = 0; - int key_sum = 0; - for( typename MyTable::const_iterator i(x.begin()); i!=x.end(); ++i ) { - ++count; - key_sum += -i->first.value_of(); - } - ASSERT( count==n, NULL ); - ASSERT( key_sum==n*(n+1)/2, NULL ); -} - -static void TestCopy() { - REMARK("testing copy\n"); - MyTable t1; - for( int i=0; i<10000; i=(i<100 ? i+1 : i*3) ) { - MyDataCount = 0; - - FillTable(t1,i); - // Do not call CheckTable(t1,i) before copying, it enforces rehashing - - MyTable t2(t1); - // Check that copy constructor did not mangle source table. - CheckTable(t1,i); - swap(t1, t2); - CheckTable(t1,i); - ASSERT( !(t1 != t2), NULL ); - - // Clear original table - t2.clear(); - swap(t2, t1); - CheckTable(t1,0); - - // Verify that copy of t1 is correct, even after t1 is cleared. - CheckTable(t2,i); - t2.clear(); - t1.swap( t2 ); - CheckTable(t1,0); - CheckTable(t2,0); - ASSERT( MyDataCount==0, "data leak?" ); - } -} - -void TestAssignment() { - REMARK("testing assignment\n"); - for( int i=0; i<1000; i=(i<30 ? i+1 : i*5) ) { - for( int j=0; j<1000; j=(j<30 ? j+1 : j*7) ) { - MyTable t1; - MyTable t2; - FillTable(t1,i); - FillTable(t2,j); - ASSERT( (t1 == t2) == (i == j), NULL ); - CheckTable(t2,j); - - MyTable& tref = t2=t1; - ASSERT( &tref==&t2, NULL ); - ASSERT( t1 == t2, NULL ); - CheckTable(t1,i); - CheckTable(t2,i); - - t1.clear(); - CheckTable(t1,0); - CheckTable(t2,i); - ASSERT( MyDataCount==i, "data leak?" ); - - t2.clear(); - CheckTable(t1,0); - CheckTable(t2,0); - ASSERT( MyDataCount==0, "data leak?" ); - } - } -} - -void TestIteratorsAndRanges() { - REMARK("testing iterators compliance\n"); - TestIteratorTraits(); - TestIteratorTraits(); - - MyTable v; - MyTable const &u = v; - - TestIteratorAssignment( u.begin() ); - TestIteratorAssignment( v.begin() ); - TestIteratorAssignment( v.begin() ); - // doesn't compile as expected: TestIteratorAssignment( u.begin() ); - - // check for non-existing - ASSERT(v.equal_range(MyKey::make(-1)) == std::make_pair(v.end(), v.end()), NULL); - ASSERT(u.equal_range(MyKey::make(-1)) == std::make_pair(u.end(), u.end()), NULL); - - REMARK("testing ranges compliance\n"); - TestRangeAssignment( u.range() ); - TestRangeAssignment( v.range() ); - TestRangeAssignment( v.range() ); - // doesn't compile as expected: TestRangeAssignment( u.range() ); - - REMARK("testing construction and insertion from iterators range\n"); - FillTable( v, 1000 ); - MyTable2 t(v.begin(), v.end()); - v.rehash(); - CheckTable(t, 1000); - t.insert(v.begin(), v.end()); // do nothing - CheckTable(t, 1000); - t.clear(); - t.insert(v.begin(), v.end()); // restore - CheckTable(t, 1000); - - REMARK("testing comparison\n"); - typedef tbb::concurrent_hash_map YourTable1; - typedef tbb::concurrent_hash_map YourTable2; - YourTable1 t1; - FillTable( t1, 10 ); - CheckTable(t1, 10 ); - YourTable2 t2(t1.begin(), t1.end()); - MyKey key( MyKey::make(-5) ); MyData2 data; - ASSERT(t2.erase(key), NULL); - YourTable2::accessor a; - ASSERT(t2.insert(a, key), NULL); - data.set_value(0); a->second = data; - ASSERT( t1 != t2, NULL); - data.set_value(5*5); a->second = data; - ASSERT( t1 == t2, NULL); -} - -void TestRehash() { - REMARK("testing rehashing\n"); - MyTable w; - w.insert( std::make_pair(MyKey::make(-5), MyData()) ); - w.rehash(); // without this, assertion will fail - MyTable::iterator it = w.begin(); - int i = 0; // check for non-rehashed buckets - for( ; it != w.end(); i++ ) - w.count( (it++)->first ); - ASSERT( i == 1, NULL ); - for( i=0; i<1000; i=(i<29 ? i+1 : i*2) ) { - for( int j=max(256+i, i*2); j<10000; j*=3 ) { - MyTable v; - FillTable( v, i ); - ASSERT(int(v.size()) == i, NULL); - ASSERT(int(v.bucket_count()) <= j, NULL); - v.rehash( j ); - ASSERT(int(v.bucket_count()) >= j, NULL); - CheckTable( v, i ); - } - } -} - -#if TBB_USE_EXCEPTIONS -void TestExceptions() { - typedef local_counting_allocator > allocator_t; - typedef tbb::concurrent_hash_map ThrowingTable; - enum methods { - zero_method = 0, - ctor_copy, op_assign, op_insert, - all_methods - }; - REMARK("testing exception-safety guarantees\n"); - ThrowingTable src; - FillTable( src, 1000 ); - ASSERT( MyDataCount==1000, NULL ); - - try { - for(int t = 0; t < 2; t++) // exception type - for(int m = zero_method+1; m < all_methods; m++) - { - allocator_t a; - if(t) MyDataCountLimit = 101; - else a.set_limits(101); - ThrowingTable victim(a); - MyDataCount = 0; - - try { - switch(m) { - case ctor_copy: { - ThrowingTable acopy(src, a); - } break; - case op_assign: { - victim = src; - } break; - case op_insert: { - FillTable( victim, 1000 ); - } break; - default:; - } - ASSERT(false, "should throw an exception"); - } catch(std::bad_alloc &e) { - MyDataCountLimit = 0; - size_t size = victim.size(); - switch(m) { - case op_assign: - ASSERT( MyDataCount==100, "data leak?" ); - ASSERT( size>=100, NULL ); - CheckAllocator(victim, 100+t, t); - case ctor_copy: - CheckTable(src, 1000); - break; - case op_insert: - ASSERT( size==size_t(100-t), NULL ); - ASSERT( MyDataCount==100-t, "data leak?" ); - CheckTable(victim, 100-t); - CheckAllocator(victim, 100, t); - break; - - default:; // nothing to check here - } - REMARK("Exception %d: %s\t- ok ()\n", m, e.what()); - } - catch ( ... ) { - ASSERT ( __TBB_EXCEPTION_TYPE_INFO_BROKEN, "Unrecognized exception" ); - } - } - } catch(...) { - ASSERT(false, "unexpected exception"); - } - src.clear(); MyDataCount = 0; -} -#endif /* TBB_USE_EXCEPTIONS */ - -//------------------------------------------------------------------------ -// Test driver -//------------------------------------------------------------------------ - -#include "tbb/task_scheduler_init.h" - -int TestMain () { - if( MinThread<0 ) { - REPORT("ERROR: must use at least one thread\n"); - exit(1); - } - - // Do serial tests - TestTypes(); - TestCopy(); - TestRehash(); - TestAssignment(); - TestIteratorsAndRanges(); -#if TBB_USE_EXCEPTIONS - TestExceptions(); -#endif /* TBB_USE_EXCEPTIONS */ - - // Do concurrency tests. - for( int nthread=MinThread; nthread<=MaxThread; ++nthread ) { - tbb::task_scheduler_init init( nthread ); - TestInsertFindErase( nthread ); - TestConcurrency( nthread ); - } - // check linking - if(bad_hashing) { //should be false - tbb::internal::runtime_warning("none\nERROR: it must not be executed"); - } - - return Harness::Done; -} diff --git a/deal.II/contrib/tbb/tbb30_104oss/src/test/test_concurrent_monitor.cpp b/deal.II/contrib/tbb/tbb30_104oss/src/test/test_concurrent_monitor.cpp deleted file mode 100644 index 71246d8091..0000000000 --- a/deal.II/contrib/tbb/tbb30_104oss/src/test/test_concurrent_monitor.cpp +++ /dev/null @@ -1,244 +0,0 @@ -/* - Copyright 2005-2010 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. -*/ - -#include "tbb/concurrent_monitor.h" -#include "tbb/atomic.h" -#include "tbb/parallel_for.h" -#include "tbb/blocked_range.h" -#include "harness.h" -#include "tbb/concurrent_monitor.cpp" - -using namespace tbb; - -//! Queuing lock with concurrent_monitor; to test concurrent_monitor::notify( Predicate p ) -class QueuingMutex { -public: - //! Construct unacquired mutex. - QueuingMutex() { q_tail = NULL; } - - //! The scoped locking pattern - class ScopedLock: internal::no_copy { - void Initialize() { mutex = NULL; } - public: - ScopedLock() {Initialize();} - ScopedLock( QueuingMutex& m ) { Initialize(); Acquire(m); } - ~ScopedLock() { if( mutex ) Release(); } - void Acquire( QueuingMutex& m ); - void Release(); - void SleepPerhaps(); - - private: - QueuingMutex* mutex; - ScopedLock* next; - uintptr_t going; - internal::concurrent_monitor::thread_context thr_ctx; - }; - - friend class ScopedLock; -private: - //! The last competitor requesting the lock - atomic q_tail; - internal::concurrent_monitor waitq; -}; - -struct PredicateEq { - void* p; - PredicateEq( void* p_ ) : p(p_) {} - bool operator() ( void* v ) const {return p==v;} -}; - -//! A method to acquire QueuingMutex lock -void QueuingMutex::ScopedLock::Acquire( QueuingMutex& m ) -{ - // Must set all fields before the fetch_and_store, because once the - // fetch_and_store executes, *this becomes accessible to other threads. - mutex = &m; - next = NULL; - going = 0; - - // The fetch_and_store must have release semantics, because we are - // "sending" the fields initialized above to other processors. - ScopedLock* pred = m.q_tail.fetch_and_store(this); - if( pred ) { - __TBB_ASSERT( !pred->next, "the predecessor has another successor!"); - pred->next = this; - for( int i=0; i<16; ++i ) { - if( going!=0ul ) break; - __TBB_Yield(); - } - SleepPerhaps(); - } - - // Force acquire so that user's critical section receives correct values - // from processor that was previously in the user's critical section. - __TBB_load_with_acquire(going); -} - -//! A method to release QueuingMutex lock -void QueuingMutex::ScopedLock::Release( ) -{ - if( !next ) { - if( this == mutex->q_tail.compare_and_swap(NULL, this) ) { - // this was the only item in the queue, and the queue is now empty. - goto done; - } - // Someone in the queue - spin_wait_while_eq( next, (ScopedLock*)0 ); - } - __TBB_store_with_release(next->going, 1); - mutex->waitq.notify( PredicateEq(next) ); -done: - Initialize(); -} - -//! Yield and block; go to sleep -void QueuingMutex::ScopedLock::SleepPerhaps() -{ - bool slept = false; - internal::concurrent_monitor& mq = mutex->waitq; - mq.prepare_wait( thr_ctx, this ); - while( going==0ul ) { - if( (slept=mq.commit_wait( thr_ctx ))==true ) - break; - mq.prepare_wait( thr_ctx, this ); - } - if( !slept ) - mq.cancel_wait( thr_ctx ); -} - -// Spin lock with concurrent_monitor; to test concurrent_monitor::notify_all() and concurrent_monitor::notify() -class SpinMutex { -public: - //! Construct unacquired mutex. - SpinMutex() : toggle(false) { flag = 0; } - - //! The scoped locking pattern - class ScopedLock: internal::no_copy { - void Initialize() { mutex = NULL; } - public: - ScopedLock() {Initialize();} - ScopedLock( SpinMutex& m ) { Initialize(); Acquire(m); } - ~ScopedLock() { if( mutex ) Release(); } - void Acquire( SpinMutex& m ); - void Release(); - void SleepPerhaps(); - - private: - SpinMutex* mutex; - internal::concurrent_monitor::thread_context thr_ctx; - }; - - friend class ScopedLock; -private: - tbb::atomic flag; - bool toggle; - internal::concurrent_monitor waitq; -}; - -//! A method to acquire SpinMutex lock -void SpinMutex::ScopedLock::Acquire( SpinMutex& m ) -{ - mutex = &m; -retry: - if( m.flag.compare_and_swap( 1, 0 )!=0 ) { - SleepPerhaps(); - goto retry; - } -} - -//! A method to release SpinMutex lock -void SpinMutex::ScopedLock::Release() -{ - bool old_toggle = mutex->toggle; - mutex->toggle = !mutex->toggle; - mutex->flag = 0; - if( old_toggle ) - mutex->waitq.notify_one(); - else - mutex->waitq.notify_all(); -} - -//! Yield and block; go to sleep -void SpinMutex::ScopedLock::SleepPerhaps() -{ - bool slept = false; - internal::concurrent_monitor& mq = mutex->waitq; - mq.prepare_wait( thr_ctx, this ); - while( mutex->flag ) { - if( (slept=mq.commit_wait( thr_ctx ))==true ) - break; - mq.prepare_wait( thr_ctx, this ); - } - if( !slept ) - mq.cancel_wait( thr_ctx ); -} - -template -struct Counter { - typedef M mutex_type; - M mutex; - volatile long value; -}; - -//! Function object for use with parallel_for.h. -template -struct AddOne: NoAssign { - C& counter; - /** Increments counter once for each iteration in the iteration space. */ - void operator()( tbb::blocked_range& range ) const { - for( size_t i=range.begin(); i!=range.end(); ++i ) { - typename C::mutex_type::ScopedLock lock(counter.mutex); - counter.value = counter.value+1; - } - } - AddOne( C& counter_ ) : counter(counter_) {} -}; - -//! Generic test of a TBB mutex type M. -/** Does not test features specific to reader-writer locks. */ -template -void Test() { - Counter counter; - counter.value = 0; - const int n = 100000; - tbb::parallel_for(tbb::blocked_range(0,n,n/10),AddOne >(counter)); - if( counter.value!=n ) - REPORT("ERROR : counter.value=%ld\n",counter.value); -} - -int TestMain () { - for( int p=MinThread; p<=MaxThread; ++p ) { - REMARK( "testing with %d workers\n", static_cast(p) ); - // test the predicated notify - Test(); - // test the notify_all method - Test(); - REMARK( "calling destructor for task_scheduler_init\n" ); - } - return Harness::Done; -} diff --git a/deal.II/contrib/tbb/tbb30_104oss/src/test/test_concurrent_queue.cpp b/deal.II/contrib/tbb/tbb30_104oss/src/test/test_concurrent_queue.cpp deleted file mode 100644 index 1704c75e44..0000000000 --- a/deal.II/contrib/tbb/tbb30_104oss/src/test/test_concurrent_queue.cpp +++ /dev/null @@ -1,968 +0,0 @@ -/* - Copyright 2005-2010 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. -*/ - -#include "tbb/concurrent_queue.h" -#include "tbb/atomic.h" -#include "tbb/tick_count.h" -#include "harness.h" -#include "harness_allocator.h" - -static tbb::atomic FooConstructed; -static tbb::atomic FooDestroyed; - -class Foo { - enum state_t{ - LIVE=0x1234, - DEAD=0xDEAD - }; - state_t state; -public: - int thread_id; - int serial; - Foo() : state(LIVE), thread_id(0), serial(0) { - ++FooConstructed; - } - Foo( const Foo& item ) : state(LIVE) { - ASSERT( item.state==LIVE, NULL ); - ++FooConstructed; - thread_id = item.thread_id; - serial = item.serial; - } - ~Foo() { - ASSERT( state==LIVE, NULL ); - ++FooDestroyed; - state=DEAD; - thread_id=0xDEAD; - serial=0xDEAD; - } - void operator=( const Foo& item ) { - ASSERT( item.state==LIVE, NULL ); - ASSERT( state==LIVE, NULL ); - thread_id = item.thread_id; - serial = item.serial; - } - bool is_const() {return false;} - bool is_const() const {return true;} -}; - -// problem size -static const int N = 50000; // # of bytes - -#if TBB_USE_EXCEPTIONS -//! Exception for concurrent_queue -class Foo_exception : public std::bad_alloc { -public: - virtual const char *what() const throw() { return "out of Foo limit"; } - virtual ~Foo_exception() throw() {} -}; - -static tbb::atomic FooExConstructed; -static tbb::atomic FooExDestroyed; -static tbb::atomic serial_source; -static long MaxFooCount = 0; -static const long Threshold = 400; - -class FooEx { - enum state_t{ - LIVE=0x1234, - DEAD=0xDEAD - }; - state_t state; -public: - int serial; - FooEx() : state(LIVE) { - ++FooExConstructed; - serial = serial_source++; - } - - FooEx( const FooEx& item ) : state(LIVE) { - ++FooExConstructed; - if( MaxFooCount && (FooExConstructed-FooExDestroyed) >= MaxFooCount ) // in push() - throw Foo_exception(); - serial = item.serial; - } - ~FooEx() { - ASSERT( state==LIVE, NULL ); - ++FooExDestroyed; - state=DEAD; - serial=0xDEAD; - } - void operator=( FooEx& item ) { - ASSERT( item.state==LIVE, NULL ); - ASSERT( state==LIVE, NULL ); - serial = item.serial; - if( MaxFooCount==2*Threshold && (FooExConstructed-FooExDestroyed) <= MaxFooCount/4 ) // in pop() - throw Foo_exception(); - } -} ; -#endif /* TBB_USE_EXCEPTIONS */ - -const size_t MAXTHREAD = 256; - -static int Sum[MAXTHREAD]; - -//! Count of various pop operations -/** [0] = pop_if_present that failed - [1] = pop_if_present that succeeded - [2] = pop */ -static tbb::atomic PopKind[3]; - -const int M = 10000; - -#if TBB_DEPRECATED -#define CALL_BLOCKING_POP(q,v) (q)->pop(v) -#define CALL_TRY_POP(q,v,i) (((i)&0x2)?q->try_pop(v):q->pop_if_present(v)) -#define SIZE() size() -#else -#define CALL_BLOCKING_POP(q,v) while( !(q)->try_pop(v) ) __TBB_Yield() -#define CALL_TRY_POP(q,v,i) q->try_pop(v) -#define SIZE() unsafe_size() -#endif - -struct Body: NoAssign { - tbb::concurrent_queue* queue; - const int nthread; - Body( int nthread_ ) : nthread(nthread_) {} - void operator()( int thread_id ) const { - long pop_kind[3] = {0,0,0}; - int serial[MAXTHREAD+1]; - memset( serial, 0, nthread*sizeof(int) ); - ASSERT( thread_idpush( g ); - if( !prepopped ) { - CALL_BLOCKING_POP(queue,f); - ++pop_kind[2]; - } - ASSERT( f.thread_id<=nthread, NULL ); - ASSERT( f.thread_id==nthread || serial[f.thread_id]0, "nthread must be positive" ); -#if TBB_DEPRECATED - ptrdiff_t signed_prefill = ptrdiff_t(prefill); - if( signed_prefill+1>=capacity ) - return; -#endif - bool success = false; - for( int k=0; k<3; ++k ) - PopKind[k] = 0; - for( int trial=0; !success; ++trial ) { - FooConstructed = 0; - FooDestroyed = 0; - Body body(nthread); - tbb::concurrent_queue queue; -#if TBB_DEPRECATED - queue.set_capacity( capacity ); -#endif - body.queue = &queue; - for( size_t i=0; i=0; ) { - ASSERT( !queue.empty(), NULL ); - Foo f; - bool result = queue.try_pop(f); - ASSERT( result, NULL ); - ASSERT( int(queue.SIZE())==i, NULL ); - sum += f.serial-1; - } - ASSERT( queue.empty(), NULL ); - ASSERT( queue.SIZE()==0, NULL ); - if( sum!=expected ) - REPORT("sum=%d expected=%d\n",sum,expected); - ASSERT( FooConstructed==FooDestroyed, NULL ); - // TODO: checks by counting allocators - - success = true; - if( nthread>1 && prefill==0 ) { - // Check that pop_if_present got sufficient exercise - for( int k=0; k<2; ++k ) { -#if (_WIN32||_WIN64) - // The TBB library on Windows seems to have a tough time generating - // the desired interleavings for pop_if_present, so the code tries longer, and settles - // for fewer desired interleavings. - const int max_trial = 100; - const int min_requirement = 20; -#else - const int min_requirement = 100; - const int max_trial = 20; -#endif /* _WIN32||_WIN64 */ - if( PopKind[k]=max_trial ) { - if( Verbose ) - REPORT("Warning: %d threads had only %ld pop_if_present operations %s after %d trials (expected at least %d). " - "This problem may merely be unlucky scheduling. " - "Investigate only if it happens repeatedly.\n", - nthread, long(PopKind[k]), k==0?"failed":"succeeded", max_trial, min_requirement); - else - REPORT("Warning: the number of %s pop_if_present operations is less than expected for %d threads. Investigate if it happens repeatedly.\n", - k==0?"failed":"succeeded", nthread ); - - } else { - success = false; - } - } - } - } - } -} - -class Bar { - enum state_t { - LIVE=0x1234, - DEAD=0xDEAD - }; - state_t state; -public: - ptrdiff_t my_id; - Bar() : state(LIVE), my_id(-1) {} - Bar(size_t _i) : state(LIVE), my_id(_i) {} - Bar( const Bar& a_bar ) : state(LIVE) { - ASSERT( a_bar.state==LIVE, NULL ); - my_id = a_bar.my_id; - } - ~Bar() { - ASSERT( state==LIVE, NULL ); - state = DEAD; - my_id = DEAD; - } - void operator=( const Bar& a_bar ) { - ASSERT( a_bar.state==LIVE, NULL ); - ASSERT( state==LIVE, NULL ); - my_id = a_bar.my_id; - } - friend bool operator==(const Bar& bar1, const Bar& bar2 ) ; -} ; - -bool operator==(const Bar& bar1, const Bar& bar2) { - ASSERT( bar1.state==Bar::LIVE, NULL ); - ASSERT( bar2.state==Bar::LIVE, NULL ); - return bar1.my_id == bar2.my_id; -} - -class BarIterator -{ - Bar* bar_ptr; - BarIterator(Bar* bp_) : bar_ptr(bp_) {} -public: - ~BarIterator() {} - BarIterator& operator=( const BarIterator& other ) { - bar_ptr = other.bar_ptr; - return *this; - } - Bar& operator*() const { - return *bar_ptr; - } - BarIterator& operator++() { - ++bar_ptr; - return *this; - } - Bar* operator++(int) { - Bar* result = &operator*(); - operator++(); - return result; - } - friend bool operator==(const BarIterator& bia, const BarIterator& bib) ; - friend bool operator!=(const BarIterator& bia, const BarIterator& bib) ; - friend void TestConstructors (); -} ; - -bool operator==(const BarIterator& bia, const BarIterator& bib) { - return bia.bar_ptr==bib.bar_ptr; -} - -bool operator!=(const BarIterator& bia, const BarIterator& bib) { - return bia.bar_ptr!=bib.bar_ptr; -} - -#if TBB_USE_EXCEPTIONS -class Bar_exception : public std::bad_alloc { -public: - virtual const char *what() const throw() { return "making the entry invalid"; } - virtual ~Bar_exception() throw() {} -}; - -class BarEx { - enum state_t { - LIVE=0x1234, - DEAD=0xDEAD - }; - static int count; -public: - state_t state; - typedef enum { - PREPARATION, - COPY_CONSTRUCT - } mode_t; - static mode_t mode; - ptrdiff_t my_id; - ptrdiff_t my_tilda_id; - static int button; - BarEx() : state(LIVE), my_id(-1), my_tilda_id(-1) {} - BarEx(size_t _i) : state(LIVE), my_id(_i), my_tilda_id(my_id^(-1)) {} - BarEx( const BarEx& a_bar ) : state(LIVE) { - ASSERT( a_bar.state==LIVE, NULL ); - my_id = a_bar.my_id; - if( mode==PREPARATION ) - if( !( ++count % 100 ) ) - throw Bar_exception(); - my_tilda_id = a_bar.my_tilda_id; - } - ~BarEx() { - ASSERT( state==LIVE, NULL ); - state = DEAD; - my_id = DEAD; - } - static void set_mode( mode_t m ) { mode = m; } - void operator=( const BarEx& a_bar ) { - ASSERT( a_bar.state==LIVE, NULL ); - ASSERT( state==LIVE, NULL ); - my_id = a_bar.my_id; - my_tilda_id = a_bar.my_tilda_id; - } - friend bool operator==(const BarEx& bar1, const BarEx& bar2 ) ; -} ; - -int BarEx::count = 0; -BarEx::mode_t BarEx::mode = BarEx::PREPARATION; - -bool operator==(const BarEx& bar1, const BarEx& bar2) { - ASSERT( bar1.state==BarEx::LIVE, NULL ); - ASSERT( bar2.state==BarEx::LIVE, NULL ); - ASSERT( (bar1.my_id ^ bar1.my_tilda_id) == -1, NULL ); - ASSERT( (bar2.my_id ^ bar2.my_tilda_id) == -1, NULL ); - return bar1.my_id==bar2.my_id && bar1.my_tilda_id==bar2.my_tilda_id; -} -#endif /* TBB_USE_EXCEPTIONS */ - -#if TBB_DEPRECATED -#define CALL_BEGIN(q,i) (((i)&0x1)?q.begin():q.unsafe_begin()) -#define CALL_END(q,i) (((i)&0x1)?q.end():q.unsafe_end()) -#else -#define CALL_BEGIN(q,i) q.unsafe_begin() -#define CALL_END(q,i) q.unsafe_end() -#endif - -void TestConstructors () -{ - tbb::concurrent_queue src_queue; - tbb::concurrent_queue::const_iterator dqb; - tbb::concurrent_queue::const_iterator dqe; - tbb::concurrent_queue::const_iterator iter; - - for( size_t size=0; size<1001; ++size ) { - for( size_t i=0; i::const_iterator sqb( CALL_BEGIN(src_queue,size) ); - tbb::concurrent_queue::const_iterator sqe( CALL_END(src_queue,size)); - - tbb::concurrent_queue dst_queue(sqb, sqe); - - ASSERT(src_queue.SIZE()==dst_queue.SIZE(), "different size"); - - src_queue.clear(); - } - - Bar bar_array[1001]; - for( size_t size=0; size<1001; ++size ) { - for( size_t i=0; i dst_queue2(sab, sae); - - ASSERT( size==unsigned(dst_queue2.SIZE()), NULL ); - ASSERT( sab==BarIterator(bar_array+0), NULL ); - ASSERT( sae==BarIterator(bar_array+size), NULL ); - - dqb = CALL_BEGIN(dst_queue2,size); - dqe = CALL_END(dst_queue2,size); - BarIterator v_iter(sab); - for( ; dqb != dqe; ++dqb, ++v_iter ) - ASSERT( *dqb == *v_iter, "unexpected element" ); - ASSERT( v_iter==sae, "different size?" ); - } - - src_queue.clear(); - - tbb::concurrent_queue dst_queue3( src_queue ); - ASSERT( src_queue.SIZE()==dst_queue3.SIZE(), NULL ); - ASSERT( 0==dst_queue3.SIZE(), NULL ); - - int k=0; - for( size_t i=0; i<1001; ++i ) { - Bar tmp_bar; - src_queue.push(Bar(++k)); - src_queue.push(Bar(++k)); - src_queue.try_pop(tmp_bar); - - tbb::concurrent_queue dst_queue4( src_queue ); - - ASSERT( src_queue.SIZE()==dst_queue4.SIZE(), NULL ); - - dqb = CALL_BEGIN(dst_queue4,i); - dqe = CALL_END(dst_queue4,i); - iter = CALL_BEGIN(src_queue,i); - - for( ; dqb != dqe; ++dqb, ++iter ) - ASSERT( *dqb == *iter, "unexpected element" ); - - ASSERT( iter==CALL_END(src_queue,i), "different size?" ); - } - - tbb::concurrent_queue dst_queue5( src_queue ); - - ASSERT( src_queue.SIZE()==dst_queue5.SIZE(), NULL ); - dqb = dst_queue5.unsafe_begin(); - dqe = dst_queue5.unsafe_end(); - iter = src_queue.unsafe_begin(); - for( ; dqb != dqe; ++dqb, ++iter ) - ASSERT( *dqb == *iter, "unexpected element" ); - - for( size_t i=0; i<100; ++i) { - Bar tmp_bar; - src_queue.push(Bar(i+1000)); - src_queue.push(Bar(i+1000)); - src_queue.try_pop(tmp_bar); - - dst_queue5.push(Bar(i+1000)); - dst_queue5.push(Bar(i+1000)); - dst_queue5.try_pop(tmp_bar); - } - - ASSERT( src_queue.SIZE()==dst_queue5.SIZE(), NULL ); - dqb = dst_queue5.unsafe_begin(); - dqe = dst_queue5.unsafe_end(); - iter = src_queue.unsafe_begin(); - for( ; dqb != dqe; ++dqb, ++iter ) - ASSERT( *dqb == *iter, "unexpected element" ); - ASSERT( iter==src_queue.unsafe_end(), "different size?" ); - -#if __TBB_THROW_ACROSS_MODULE_BOUNDARY_BROKEN || __TBB_PLACEMENT_NEW_EXCEPTION_SAFETY_BROKEN - REPORT("Known issue: part of the constructor test is skipped.\n"); -#elif TBB_USE_EXCEPTIONS - k = 0; -#if TBB_DEPRECATED==0 - unsigned -#endif - int n_elements=0; - tbb::concurrent_queue src_queue_ex; - for( size_t size=0; size<1001; ++size ) { - BarEx tmp_bar_ex; - int n_successful_pushes=0; - BarEx::set_mode( BarEx::PREPARATION ); - try { - src_queue_ex.push(BarEx(k+(k^size))); - ++n_successful_pushes; - } catch (...) { - } - ++k; - try { - src_queue_ex.push(BarEx(k+(k^size))); - ++n_successful_pushes; - } catch (...) { - } - ++k; - src_queue_ex.try_pop(tmp_bar_ex); - n_elements += (n_successful_pushes - 1); - ASSERT( src_queue_ex.SIZE()==n_elements, NULL); - - BarEx::set_mode( BarEx::COPY_CONSTRUCT ); - tbb::concurrent_queue dst_queue_ex( src_queue_ex ); - - ASSERT( src_queue_ex.SIZE()==dst_queue_ex.SIZE(), NULL ); - - tbb::concurrent_queue::const_iterator dqb_ex = CALL_BEGIN(dst_queue_ex, size); - tbb::concurrent_queue::const_iterator dqe_ex = CALL_END(dst_queue_ex, size); - tbb::concurrent_queue::const_iterator iter_ex = CALL_BEGIN(src_queue_ex, size); - - for( ; dqb_ex != dqe_ex; ++dqb_ex, ++iter_ex ) - ASSERT( *dqb_ex == *iter_ex, "unexpected element" ); - ASSERT( iter_ex==CALL_END(src_queue_ex,size), "different size?" ); - } -#endif /* TBB_USE_EXCEPTIONS */ -} - -template -void TestIteratorAux( Iterator1 i, Iterator2 j, int size ) { - // Now test iteration - Iterator1 old_i; - for( int k=0; k" - ASSERT( k+2==i->serial, NULL ); - } - // Test assignment - old_i = i; - } - ASSERT( k+1==f.serial, NULL ); - } - ASSERT( !(i!=j), NULL ); - ASSERT( i==j, NULL ); -} - -template -void TestIteratorAssignment( Iterator2 j ) { - Iterator1 i(j); - ASSERT( i==j, NULL ); - ASSERT( !(i!=j), NULL ); - Iterator1 k; - k = j; - ASSERT( k==j, NULL ); - ASSERT( !(k!=j), NULL ); -} - -template -void TestIteratorTraits() { - AssertSameType( static_cast(0), static_cast(0) ); - AssertSameType( static_cast(0), static_cast(0) ); - AssertSameType( static_cast(0), static_cast(0) ); - AssertSameType( static_cast(0), static_cast(0) ); - T x; - typename Iterator::reference xr = x; - typename Iterator::pointer xp = &x; - ASSERT( &xr==xp, NULL ); -} - -//! Test the iterators for concurrent_queue -void TestIterator() { - tbb::concurrent_queue queue; - const tbb::concurrent_queue& const_queue = queue; - for( int j=0; j<500; ++j ) { - TestIteratorAux( CALL_BEGIN(queue,j) , CALL_END(queue,j) , j ); - TestIteratorAux( CALL_BEGIN(const_queue,j), CALL_END(const_queue,j), j ); - TestIteratorAux( CALL_BEGIN(const_queue,j), CALL_END(queue,j) , j ); - TestIteratorAux( CALL_BEGIN(queue,j) , CALL_END(const_queue,j), j ); - Foo f; - f.serial = j+1; - queue.push(f); - } - TestIteratorAssignment::const_iterator>( const_queue.unsafe_begin() ); - TestIteratorAssignment::const_iterator>( queue.unsafe_begin() ); - TestIteratorAssignment::iterator>( queue.unsafe_begin() ); - TestIteratorTraits::const_iterator, const Foo>(); - TestIteratorTraits::iterator, Foo>(); -} - -void TestConcurrentQueueType() { - AssertSameType( tbb::concurrent_queue::value_type(), Foo() ); - Foo f; - const Foo g; - tbb::concurrent_queue::reference r = f; - ASSERT( &r==&f, NULL ); - ASSERT( !r.is_const(), NULL ); - tbb::concurrent_queue::const_reference cr = g; - ASSERT( &cr==&g, NULL ); - ASSERT( cr.is_const(), NULL ); -} - -template -void TestEmptyQueue() { - const tbb::concurrent_queue queue; - ASSERT( queue.SIZE()==0, NULL ); -#if TBB_DEPRECATED - ASSERT( queue.capacity()>0, NULL ); - ASSERT( size_t(queue.capacity())>=size_t(-1)/(sizeof(void*)+sizeof(T)), NULL ); -#endif -} - -#if TBB_DEPRECATED -#define CALL_TRY_PUSH(q,f,i) (((i)&0x1)?(q).push_if_not_full(f):(q).try_push(f)) -void TestFullQueue() { - for( int n=0; n<10; ++n ) { - FooConstructed = 0; - FooDestroyed = 0; - tbb::concurrent_queue queue; - queue.set_capacity(n); - for( int i=0; i<=n; ++i ) { - Foo f; - f.serial = i; - bool result = CALL_TRY_PUSH(queue, f, i ); - ASSERT( result==(i queue; -#if TBB_DEPRECATED - const int q_capacity=10; - queue.set_capacity(q_capacity); -#endif - for( size_t i=0; i -struct TestNegativeQueueBody: NoAssign { - tbb::concurrent_queue& queue; - const int nthread; - TestNegativeQueueBody( tbb::concurrent_queue& q, int n ) : queue(q), nthread(n) {} - void operator()( int k ) const { - if( k==0 ) { - int number_of_pops = nthread-1; - // Wait for all pops to pend. - while( queue.size()>-number_of_pops ) { - __TBB_Yield(); - } - for( int i=0; ; ++i ) { - ASSERT( queue.size()==i-number_of_pops, NULL ); - ASSERT( queue.empty()==(queue.size()<=0), NULL ); - if( i==number_of_pops ) break; - // Satisfy another pop - queue.push( T() ); - } - } else { - // Pop item from queue - T item; - queue.pop(item); - } - } -}; - -//! Test a queue with a negative size. -template -void TestNegativeQueue( int nthread ) { - tbb::concurrent_queue queue; - NativeParallelFor( nthread, TestNegativeQueueBody(queue,nthread) ); -} -#endif /* if TBB_DEPRECATED */ - -#if TBB_USE_EXCEPTIONS -void TestExceptions() { - typedef static_counting_allocator, size_t> allocator_t; - typedef static_counting_allocator, size_t> allocator_char_t; - typedef tbb::concurrent_queue concur_queue_t; - - enum methods { - m_push = 0, - m_pop - }; - - REMARK("Testing exception safety\n"); - // verify 'clear()' on exception; queue's destructor calls its clear() - // Do test on queues of two different types at the same time to - // catch problem with incorrect sharing between templates. - { - concur_queue_t queue0; - tbb::concurrent_queue queue1; - for( int i=0; i<2; ++i ) { - bool caught = false; - try { - allocator_char_t::init_counters(); - allocator_char_t::set_limits(N/2); - for( int k=0; k=0, "n_pushed cannot be less than 0" ); - for( int k=0; k<1000; k++ ) { - queue_test.push( FooEx() ); - n_pushed++; - } - ASSERT( !queue_test.empty(), "queue must not be empty" ); - ASSERT( ptrdiff_t(queue_test.SIZE())==n_pushed, "queue size must be equal to n pushed" ); - for( int k=0; k0, "incorrect queue size"); - break; - case m_pop: - if( !t ) ASSERT( false, "should not throw an exceptin" ); - break; - } - } - REMARK("... for t=%d and m=%d, exception test passed\n", t, m); - } - } - } catch(...) { - ASSERT(false, "unexpected exception"); - } -} -#endif /* TBB_USE_EXCEPTIONS */ - -template -struct TestQueueElements: NoAssign { - tbb::concurrent_queue& queue; - const int nthread; - TestQueueElements( tbb::concurrent_queue& q, int n ) : queue(q), nthread(n) {} - void operator()( int k ) const { - for( int i=0; i<1000; ++i ) { - if( (i&0x1)==0 ) { - __TBB_ASSERT( T(k) -void TestPrimitiveTypes( int nthread, T exemplar ) -{ - tbb::concurrent_queue queue; - for( int i=0; i<100; ++i ) - queue.push( exemplar ); - NativeParallelFor( nthread, TestQueueElements(queue,nthread) ); -} - -#include "harness_m128.h" - -#if HAVE_m128 - -//! Test concurrent queue with SSE type -/** Type Queue should be a queue of ClassWithSSE. */ -template -void TestSSE() { - Queue q1; - for( int i=0; i<100; ++i ) - q1.push(ClassWithSSE(i)); - - // Copy the queue - Queue q2 = q1; - // Check that elements of the copy are correct - typename Queue::const_iterator ci = q2.unsafe_begin(); - for( int i=0; i<100; ++i ) { - ClassWithSSE foo = *ci; - ASSERT( *ci==ClassWithSSE(i), NULL ); - ++ci; - } - - for( int i=0; i<101; ++i ) { - ClassWithSSE tmp; - bool b = q1.try_pop( tmp ); - ASSERT( b==(i<100), NULL ); - ASSERT( !b || tmp==ClassWithSSE(i), NULL ); - } -} -#endif /* HAVE_m128 */ - -int TestMain () { - TestEmptyQueue(); - TestEmptyQueue(); -#if TBB_DEPRECATED - TestFullQueue(); -#endif - TestClear(); - TestConcurrentQueueType(); - TestIterator(); - TestConstructors(); - - TestPrimitiveTypes( MaxThread, (char)1 ); - TestPrimitiveTypes( MaxThread, (int)-12 ); - TestPrimitiveTypes( MaxThread, (float)-1.2f ); - TestPrimitiveTypes( MaxThread, (double)-4.3 ); -#if HAVE_m128 - TestSSE >(); - TestSSE >(); -#endif /* HAVE_m128 */ - - // Test concurrent operations - for( int nthread=MinThread; nthread<=MaxThread; ++nthread ) { -#if TBB_DEPRECATED - TestNegativeQueue(nthread); -#endif - for( size_t prefill=0; prefill<64; prefill+=(1+prefill/3) ) { - TestPushPop(prefill,ptrdiff_t(-1),nthread); - TestPushPop(prefill,ptrdiff_t(1),nthread); - TestPushPop(prefill,ptrdiff_t(2),nthread); - TestPushPop(prefill,ptrdiff_t(10),nthread); - TestPushPop(prefill,ptrdiff_t(100),nthread); - } - } -#if __TBB_THROW_ACROSS_MODULE_BOUNDARY_BROKEN - REPORT("Known issue: exception safety test is skipped.\n"); -#elif TBB_USE_EXCEPTIONS - TestExceptions(); -#endif /* TBB_USE_EXCEPTIONS */ - return Harness::Done; -} diff --git a/deal.II/contrib/tbb/tbb30_104oss/src/test/test_concurrent_unordered.cpp b/deal.II/contrib/tbb/tbb30_104oss/src/test/test_concurrent_unordered.cpp deleted file mode 100644 index fc32a5f4fb..0000000000 --- a/deal.II/contrib/tbb/tbb30_104oss/src/test/test_concurrent_unordered.cpp +++ /dev/null @@ -1,464 +0,0 @@ -/* - Copyright 2005-2010 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. -*/ - -/* Some tests in this source file are based on PPL tests provided by Microsoft. */ - -#define __TBB_EXTRA_DEBUG 1 -#include "tbb/concurrent_unordered_map.h" -#include "tbb/parallel_for.h" -#include "tbb/tick_count.h" -#include -#include "harness.h" -#include "harness_allocator.h" - -using namespace std; - -typedef local_counting_allocator,std::allocator> > MyAllocator; -typedef tbb::concurrent_unordered_map, std::equal_to, MyAllocator> Mycumap; -//typedef tbb::concurrent_unordered_map Mycumap; -//typedef concurrent_unordered_multimap Mycummap; - -#define CheckAllocatorE(t,a,f) CheckAllocator(t,a,f,true,__LINE__) -#define CheckAllocatorA(t,a,f) CheckAllocator(t,a,f,false,__LINE__) -template -inline void CheckAllocator(MyTable &table, size_t expected_allocs, size_t expected_frees, bool exact = true, int line = 0) { - typename MyTable::allocator_type a = table.get_allocator(); - REMARK("#%d checking allocators: items %u/%u, allocs %u/%u\n", line, - unsigned(a.items_allocated), unsigned(a.items_freed), unsigned(a.allocations), unsigned(a.frees) ); - ASSERT( a.items_allocated == a.allocations, NULL); ASSERT( a.items_freed == a.frees, NULL); - if(exact) { - ASSERT( a.allocations == expected_allocs, NULL); ASSERT( a.frees == expected_frees, NULL); - } else { - ASSERT( a.allocations >= expected_allocs, NULL); ASSERT( a.frees >= expected_frees, NULL); - ASSERT( a.allocations - a.frees == expected_allocs - expected_frees, NULL ); - } -} - -template > -struct ValueFactory { - static V make(const K &value) { return V(value, value); } - static K get(const V& value) { return value.second; } -}; - -template -struct ValueFactory { - static T make(const T &value) { return value; } - static T get(const T &value) { return value; } -}; - -template -struct Value : ValueFactory {}; - -#if _MSC_VER -#pragma warning(disable: 4189) // warning 4189 -- local variable is initialized but not referenced -#pragma warning(disable: 4127) // warning 4127 -- while (true) has a constant expression in it -#endif - -template -std::pair CheckRecursiveRange(RangeType range) { - std::pair sum(0, 0); // count, sum - for( Iterator i = range.begin(), e = range.end(); i != e; ++i ) { - ++sum.first; sum.second += i->second; - } - if( range.is_divisible() ) { - RangeType range2( range, tbb::split() ); - std::pair sum1 = CheckRecursiveRange( range ); - std::pair sum2 = CheckRecursiveRange( range2 ); - sum1.first += sum2.first; sum1.second += sum2.second; - ASSERT( sum == sum1, "Mismatched ranges after division"); - } - return sum; -} - -template -struct SpecialTests { - static void Test() {} -}; - -template <> -struct SpecialTests -{ - static void Test() - { - Mycumap cont(0); - const Mycumap &ccont(cont); - - // mapped_type& operator[](const key_type& k); - cont[1] = 2; - - // bool empty() const; - ASSERT(!ccont.empty(), "Concurrent container empty after adding an element"); - - // size_type size() const; - ASSERT(ccont.size() == 1, "Concurrent container size incorrect"); - - ASSERT(cont[1] == 2, "Concurrent container size incorrect"); - - // mapped_type& at( const key_type& k ); - // const mapped_type& at(const key_type& k) const; - ASSERT(cont.at(1) == 2, "Concurrent container size incorrect"); - ASSERT(ccont.at(1) == 2, "Concurrent container size incorrect"); - - // iterator find(const key_type& k); - Mycumap::const_iterator it = cont.find(1); - ASSERT(it != cont.end() && Value::get(*(it)) == 2, "Element with key 1 not properly found"); - - REMARK("passed -- specialized concurrent unordered map tests\n"); - } -}; - -template -void test_basic(const char * str) -{ - T cont; - const T &ccont(cont); - - // bool empty() const; - ASSERT(ccont.empty(), "Concurrent container not empty after construction"); - - // size_type size() const; - ASSERT(ccont.size() == 0, "Concurrent container not empty after construction"); - - // size_type max_size() const; - ASSERT(ccont.max_size() > 0, "Concurrent container max size invalid"); - - //iterator begin(); - //iterator end(); - ASSERT(cont.begin() == cont.end(), "Concurrent container iterators invalid after construction"); - ASSERT(ccont.begin() == ccont.end(), "Concurrent container iterators invalid after construction"); - ASSERT(cont.cbegin() == cont.cend(), "Concurrent container iterators invalid after construction"); - - //std::pair insert(const value_type& obj); - std::pair ins = cont.insert(Value::make(1)); - ASSERT(ins.second == true && Value::get(*(ins.first)) == 1, "Element 1 not properly inserted"); - - // bool empty() const; - ASSERT(!ccont.empty(), "Concurrent container empty after adding an element"); - - // size_type size() const; - ASSERT(ccont.size() == 1, "Concurrent container size incorrect"); - - std::pair ins2 = cont.insert(Value::make(1)); - - if (T::allow_multimapping) - { - // std::pair insert(const value_type& obj); - ASSERT(ins2.second == true && Value::get(*(ins2.first)) == 1, "Element 1 not properly inserted"); - - // size_type size() const; - ASSERT(ccont.size() == 2, "Concurrent container size incorrect"); - - // size_type count(const key_type& k) const; - ASSERT(ccont.count(1) == 2, "Concurrent container count(1) incorrect"); - - // std::pair equal_range(const key_type& k); - std::pair range = cont.equal_range(1); - typename T::iterator it = range.first; - ASSERT(it != cont.end() && Value::get(*it) == 1, "Element 1 not properly found"); - unsigned int count = 0; - for (; it != range.second; it++) - { - count++; - ASSERT(Value::get(*it) == 1, "Element 1 not properly found"); - } - - ASSERT(count == 2, "Range doesn't have the right number of elements"); - } - else - { - // std::pair insert(const value_type& obj); - ASSERT(ins2.second == false && ins2.first == ins.first, "Element 1 should not be re-inserted"); - - // size_type size() const; - ASSERT(ccont.size() == 1, "Concurrent container size incorrect"); - - // size_type count(const key_type& k) const; - ASSERT(ccont.count(1) == 1, "Concurrent container count(1) incorrect"); - - // std::pair equal_range(const key_type& k) const; - // std::pair equal_range(const key_type& k); - std::pair range = cont.equal_range(1); - typename T::iterator i = range.first; - ASSERT(i != cont.end() && Value::get(*i) == 1, "Element 1 not properly found"); - ASSERT(++i == range.second, "Range doesn't have the right number of elements"); - } - - // const_iterator find(const key_type& k) const; - // iterator find(const key_type& k); - typename T::iterator it = cont.find(1); - ASSERT(it != cont.end() && Value::get(*(it)) == 1, "Element 1 not properly found"); - ASSERT(ccont.find(1) == it, "Element 1 not properly found"); - - // iterator insert(const_iterator hint, const value_type& obj); - typename T::iterator it2 = cont.insert(ins.first, Value::make(2)); - ASSERT(Value::get(*it2) == 2, "Element 2 not properly inserted"); - - // T(const T& _Umap) - T newcont = ccont; - ASSERT(T::allow_multimapping ? (newcont.size() == 3) : (newcont.size() == 2), "Copy construction did not copy the elements properly"); - - // size_type unsafe_erase(const key_type& k); - typename T::size_type size = cont.unsafe_erase(1); - ASSERT(T::allow_multimapping ? (size == 2) : (size == 1), "Erase did not remove the right number of elements"); - - // iterator unsafe_erase(const_iterator position); - typename T::iterator it4 = cont.unsafe_erase(cont.find(2)); - ASSERT(it4 == cont.end() && cont.size() == 0, "Erase did not remove the last element properly"); - - // template void insert(InputIterator first, InputIterator last); - cont.insert(newcont.begin(), newcont.end()); - ASSERT(T::allow_multimapping ? (cont.size() == 3) : (cont.size() == 2), "Range insert did not copy the elements properly"); - - // iterator unsafe_erase(const_iterator first, const_iterator last); - std::pair range2 = newcont.equal_range(1); - newcont.unsafe_erase(range2.first, range2.second); - ASSERT(newcont.size() == 1, "Range erase did not erase the elements properly"); - - // void clear(); - newcont.clear(); - ASSERT(newcont.begin() == newcont.end() && newcont.size() == 0, "Clear did not clear the container"); - - // T& operator=(const T& _Umap) - newcont = ccont; - ASSERT(T::allow_multimapping ? (newcont.size() == 3) : (newcont.size() == 2), "Assignment operator did not copy the elements properly"); - - // void rehash(size_type n); - newcont.rehash(16); - ASSERT(T::allow_multimapping ? (newcont.size() == 3) : (newcont.size() == 2), "Rehash should not affect the container elements"); - - // float load_factor() const; - // float max_load_factor() const; - ASSERT(ccont.load_factor() <= ccont.max_load_factor(), "Load factor invalid"); - - // void max_load_factor(float z); - cont.max_load_factor(16.0f); - ASSERT(ccont.max_load_factor() == 16.0f, "Max load factor not properly changed"); - - // hasher hash_function() const; - ccont.hash_function(); - - // key_equal key_eq() const; - ccont.key_eq(); - - cont.clear(); - CheckAllocatorA(cont, 1, 0); // one dummy is always allocated - for (int i = 0; i < 256; i++) - { - std::pair ins3 = cont.insert(Value::make(i)); - ASSERT(ins3.second == true && Value::get(*(ins3.first)) == i, "Element 1 not properly inserted"); - } - ASSERT(cont.size() == 256, "Wrong number of elements inserted"); - ASSERT(256 == CheckRecursiveRange(cont.range()).first, NULL); - ASSERT(256 == CheckRecursiveRange(ccont.range()).first, NULL); - - // size_type unsafe_bucket_count() const; - ASSERT(ccont.unsafe_bucket_count() == 16, "Wrong number of buckets"); - - // size_type unsafe_max_bucket_count() const; - ASSERT(ccont.unsafe_max_bucket_count() > 65536, "Wrong max number of buckets"); - - for (unsigned int i = 0; i < 256; i++) - { - typename T::size_type buck = ccont.unsafe_bucket(i); - - // size_type unsafe_bucket(const key_type& k) const; - ASSERT(buck < 16, "Wrong bucket mapping"); - } - - for (unsigned int i = 0; i < 16; i++) - { - // size_type unsafe_bucket_size(size_type n); - ASSERT(cont.unsafe_bucket_size(i) == 16, "Wrong number elements in a bucket"); - - // local_iterator unsafe_begin(size_type n); - // const_local_iterator unsafe_begin(size_type n) const; - // local_iterator unsafe_end(size_type n); - // const_local_iterator unsafe_end(size_type n) const; - // const_local_iterator unsafe_cbegin(size_type n) const; - // const_local_iterator unsafe_cend(size_type n) const; - unsigned int count = 0; - for (typename T::iterator bit = cont.unsafe_begin(i); bit != cont.unsafe_end(i); bit++) - { - count++; - } - ASSERT(count == 16, "Bucket iterators are invalid"); - } - - // void swap(T&); - cont.swap(newcont); - ASSERT(newcont.size() == 256, "Wrong number of elements after swap"); - ASSERT(newcont.count(200) == 1, "Element with key 200 not present after swap"); - ASSERT(newcont.count(16) == 1, "Element with key 16 not present after swap"); - ASSERT(newcont.count(99) == 1, "Element with key 99 not present after swap"); - ASSERT(T::allow_multimapping ? (cont.size() == 3) : (cont.size() == 2), "Wrong number of elements after swap"); - - REMARK("passed -- basic %S tests\n", str); - -#if defined (VERBOSE) - REMARK("container dump debug:\n"); - cont._Dump(); - REMARK("container dump release:\n"); - cont.dump(); - REMARK("\n"); -#endif - - SpecialTests::Test(); -} - -void test_machine() { - ASSERT(__TBB_ReverseByte(0)==0, NULL ); - ASSERT(__TBB_ReverseByte(1)==0x80, NULL ); - ASSERT(__TBB_ReverseByte(0xFE)==0x7F, NULL ); - ASSERT(__TBB_ReverseByte(0xFF)==0xFF, NULL ); -} - -template -class FillTable: NoAssign { - T &table; - const int items; - typedef std::pair pairIB; -public: - FillTable(T &t, int i) : table(t), items(i) { - ASSERT( !(items&1) && items > 100, NULL); - } - void operator()(int threadn) const { - if( threadn == 0 ) { // Fill even keys forward (single thread) - bool last_inserted = true; - for( int i = 0; i < items; i+=2 ) { - pairIB pib = table.insert(Value::make(i)); - ASSERT(Value::get(*(pib.first)) == i, "Element not properly inserted"); - ASSERT( last_inserted || !pib.second, "Previous key was not inserted but this is inserted" ); - last_inserted = pib.second; - } - } else if( threadn == 1 ) { // Fill even keys backward (single thread) - bool last_inserted = true; - for( int i = items-2; i >= 0; i-=2 ) { - pairIB pib = table.insert(Value::make(i)); - ASSERT(Value::get(*(pib.first)) == i, "Element not properly inserted"); - ASSERT( last_inserted || !pib.second, "Previous key was not inserted but this is inserted" ); - last_inserted = pib.second; - } - } else if( !(threadn&1) ) { // Fill odd keys forward (multiple threads) - for( int i = 1; i < items; i+=2 ) { - pairIB pib = table.insert(Value::make(i)); - ASSERT(Value::get(*(pib.first)) == i, "Element not properly inserted"); - } - } else { // Check odd keys backward (multiple threads) - bool last_found = false; - for( int i = items-1; i >= 0; i-=2 ) { - typename T::iterator it = table.find(i); - if( it != table.end() ) { // found - ASSERT(Value::get(*it) == i, "Element not properly inserted"); - last_found = true; - } else ASSERT( !last_found, "Previous key was found but this is not" ); - } - } - } -}; - -typedef tbb::atomic AtomicByte; - -template -struct ParallelTraverseBody: NoAssign { - const int n; - AtomicByte* const array; - ParallelTraverseBody( AtomicByte an_array[], int a_n ) : - n(a_n), array(an_array) - {} - void operator()( const RangeType& range ) const { - for( typename RangeType::iterator i = range.begin(); i!=range.end(); ++i ) { - int k = i->first; - ASSERT( k == i->second, NULL ); - ASSERT( 0<=k && k -class CheckTable: NoAssign { - T &table; -public: - CheckTable(T &t) : NoAssign(), table(t) {} - void operator()(int i) const { - int c = (int)table.count( i ); - ASSERT( c, "must exist" ); - } -}; - -template -void test_concurrent(const char *tablename) { -#if TBB_USE_ASSERT - int items = 2000; -#else - int items = 100000; -#endif - T table(items/1000); - tbb::tick_count t0 = tbb::tick_count::now(); - NativeParallelFor( 16/*min 6*/, FillTable(table, items) ); - tbb::tick_count t1 = tbb::tick_count::now(); - REMARK( "time for filling '%s' by %d items = %g\n", tablename, items, (t1-t0).seconds() ); - ASSERT( int(table.size()) == items, NULL); - - AtomicByte* array = new AtomicByte[items]; - memset( array, 0, items*sizeof(AtomicByte) ); - - typename T::range_type r = table.range(); - ASSERT(items == CheckRecursiveRange(r).first, NULL); - tbb::parallel_for( r, ParallelTraverseBody( array, items )); - CheckRange( array, items ); - - const T &const_table = table; - memset( array, 0, items*sizeof(AtomicByte) ); - typename T::const_range_type cr = const_table.range(); - ASSERT(items == CheckRecursiveRange(cr).first, NULL); - tbb::parallel_for( cr, ParallelTraverseBody( array, items )); - CheckRange( array, items ); - delete[] array; - - tbb::parallel_for( 0, items, CheckTable( table ) ); - - table.clear(); - CheckAllocatorA(table, items+1, items); // one dummy is always allocated -} - -int TestMain () { - test_machine(); - test_basic("concurrent unordered map"); - test_concurrent("concurrent unordered map"); - return Harness::Done; -} diff --git a/deal.II/contrib/tbb/tbb30_104oss/src/test/test_concurrent_vector.cpp b/deal.II/contrib/tbb/tbb30_104oss/src/test/test_concurrent_vector.cpp deleted file mode 100644 index f6fbfe7db5..0000000000 --- a/deal.II/contrib/tbb/tbb30_104oss/src/test/test_concurrent_vector.cpp +++ /dev/null @@ -1,1016 +0,0 @@ -/* - Copyright 2005-2010 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. -*/ - -#include "tbb/concurrent_vector.h" -#include "tbb/tbb_allocator.h" -#include "tbb/cache_aligned_allocator.h" -#include "tbb/tbb_exception.h" -#include -#include -#include "harness_report.h" -#include "harness_assert.h" -#include "harness_allocator.h" - -#if TBB_USE_EXCEPTIONS -static bool known_issue_verbose = false; -#define KNOWN_ISSUE(msg) if(!known_issue_verbose) known_issue_verbose = true, REPORT(msg) -#endif /* TBB_USE_EXCEPTIONS */ - -tbb::atomic FooCount; -long MaxFooCount = 0; - -//! Problem size -const size_t N = 500000; - -//! Exception for concurrent_vector -class Foo_exception : public std::bad_alloc { -public: - virtual const char *what() const throw() { return "out of Foo limit"; } - virtual ~Foo_exception() throw() {} -}; - -static const int initial_value_of_bar = 42; -struct Foo { - int my_bar; -public: - enum State { - ZeroInitialized=0, - DefaultInitialized=0xDEFAUL, - CopyInitialized=0xC0314, - Destroyed=0xDEADF00 - } state; - bool is_valid() const { - return state==DefaultInitialized||state==CopyInitialized; - } - bool is_valid_or_zero() const { - return is_valid()||(state==ZeroInitialized && !my_bar); - } - int& zero_bar() { - ASSERT( is_valid_or_zero(), NULL ); - return my_bar; - } - int& bar() { - ASSERT( is_valid(), NULL ); - return my_bar; - } - int bar() const { - ASSERT( is_valid(), NULL ); - return my_bar; - } - Foo( int barr = initial_value_of_bar ) { - my_bar = barr; - if(MaxFooCount && FooCount >= MaxFooCount) - __TBB_THROW( Foo_exception() ); - FooCount++; - state = DefaultInitialized; - } - Foo( const Foo& foo ) { - my_bar = foo.my_bar; - ASSERT( foo.is_valid_or_zero(), "bad source for copy" ); - if(MaxFooCount && FooCount >= MaxFooCount) - __TBB_THROW( Foo_exception() ); - FooCount++; - state = CopyInitialized; - } - ~Foo() { - ASSERT( is_valid_or_zero(), NULL ); - my_bar = ~initial_value_of_bar; - if(state != ZeroInitialized) --FooCount; - state = Destroyed; - } - bool operator==(const Foo &f) const { return my_bar == f.my_bar; } - bool operator<(const Foo &f) const { return my_bar < f.my_bar; } - bool is_const() const {return true;} - bool is_const() {return false;} -protected: - char reserve[1]; - void operator=( const Foo& ) {} -}; - -class FooWithAssign: public Foo { -public: - void operator=( const FooWithAssign& x ) { - my_bar = x.my_bar; - ASSERT( x.is_valid_or_zero(), "bad source for assignment" ); - ASSERT( is_valid(), NULL ); - } - bool operator==(const Foo &f) const { return my_bar == f.my_bar; } - bool operator<(const Foo &f) const { return my_bar < f.my_bar; } -}; - -class FooIterator: public std::iterator { - int x_bar; -public: - FooIterator(int x) { - x_bar = x; - } - FooIterator &operator++() { - x_bar++; return *this; - } - FooWithAssign operator*() { - FooWithAssign foo; foo.bar() = x_bar; - return foo; - } - bool operator!=(const FooIterator &i) { return x_bar != i.x_bar; } -}; - -inline void NextSize( int& s ) { - if( s<=32 ) ++s; - else s += s/10; -} - -//! Check vector have expected size and filling -template -static void CheckVector( const vector_t& cv, size_t expected_size, size_t old_size ) { - ASSERT( cv.capacity()>=expected_size, NULL ); - ASSERT( cv.size()==expected_size, NULL ); - ASSERT( cv.empty()==(expected_size==0), NULL ); - for( int j=0; j, std::size_t> allocator_t; - typedef tbb::concurrent_vector vector_t; - allocator_t::init_counters(); - for( int old_size=0; old_size<=128; NextSize( old_size ) ) { - for( int new_size=0; new_size<=1280; NextSize( new_size ) ) { - long count = FooCount; - vector_t v; - ASSERT( count==FooCount, NULL ); - v.assign(old_size/2, Foo() ); - ASSERT( count+old_size/2==FooCount, NULL ); - for( int j=0; j, std::size_t> allocator_t; - typedef tbb::concurrent_vector vector_t; - allocator_t::init_counters(); - for( size_t old_size=0; old_size<=11000; old_size=(old_size<5 ? old_size+1 : 3*old_size) ) { - for( size_t new_size=0; new_size<=11000; new_size=(new_size<5 ? new_size+1 : 3*new_size) ) { - long count = FooCount; - { - vector_t v; v.reserve(old_size); - ASSERT( v.capacity()>=old_size, NULL ); - v.reserve( new_size ); - ASSERT( v.capacity()>=old_size, NULL ); - ASSERT( v.capacity()>=new_size, NULL ); - ASSERT( v.empty(), NULL ); - size_t fill_size = 2*new_size; - for( size_t i=0; i __TBB_Log2(fill_size|1) ) - ASSERT( v.capacity() != copy_of_v.capacity(), NULL ); - v.shrink_to_fit(); - ASSERT( v.capacity() == copy_of_v.capacity(), NULL ); - CheckVector(v, new_size*2, old_size); // check vector correctness - ASSERT( v==copy_of_v, NULL ); // TODO: check also segments layout equality - } - ASSERT( FooCount==count, NULL ); - } - } - ASSERT( allocator_t::items_allocated == allocator_t::items_freed, NULL); - ASSERT( allocator_t::allocations == allocator_t::frees, NULL); -} - -struct AssignElement { - typedef tbb::concurrent_vector::range_type::iterator iterator; - iterator base; - void operator()( const tbb::concurrent_vector::range_type& range ) const { - for( iterator i=range.begin(); i!=range.end(); ++i ) { - if( *i!=0 ) - REPORT("ERROR for v[%ld]\n", long(i-base)); - *i = int(i-base); - } - } - AssignElement( iterator base_ ) : base(base_) {} -}; - -struct CheckElement { - typedef tbb::concurrent_vector::const_range_type::iterator iterator; - iterator base; - void operator()( const tbb::concurrent_vector::const_range_type& range ) const { - for( iterator i=range.begin(); i!=range.end(); ++i ) - if( *i != int(i-base) ) - REPORT("ERROR for v[%ld]\n", long(i-base)); - } - CheckElement( iterator base_ ) : base(base_) {} -}; - -#include "tbb/tick_count.h" -#include "tbb/parallel_for.h" -#include "harness.h" - -//! Test parallel access by iterators -void TestParallelFor( int nthread ) { - typedef tbb::concurrent_vector vector_t; - vector_t v; - v.resize(N); - tbb::tick_count t0 = tbb::tick_count::now(); - REMARK("Calling parallel_for with %ld threads\n",long(nthread)); - tbb::parallel_for( v.range(10000), AssignElement(v.begin()) ); - tbb::tick_count t1 = tbb::tick_count::now(); - const vector_t& u = v; - tbb::parallel_for( u.range(10000), CheckElement(u.begin()) ); - tbb::tick_count t2 = tbb::tick_count::now(); - REMARK("Time for parallel_for: assign time = %8.5f, check time = %8.5f\n", - (t1-t0).seconds(),(t2-t1).seconds()); - for( long i=0; size_t(i) -void TestIteratorAssignment( Iterator2 j ) { - Iterator1 i(j); - ASSERT( i==j, NULL ); - ASSERT( !(i!=j), NULL ); - Iterator1 k; - k = j; - ASSERT( k==j, NULL ); - ASSERT( !(k!=j), NULL ); -} - -template -void TestRangeAssignment( Range2 r2 ) { - Range1 r1(r2); r1 = r2; -} - -template -void TestIteratorTraits() { - AssertSameType( static_cast(0), static_cast(0) ); - AssertSameType( static_cast(0), static_cast(0) ); - AssertSameType( static_cast(0), static_cast(0) ); - AssertSameType( static_cast(0), static_cast(0) ); - T x; - typename Iterator::reference xr = x; - typename Iterator::pointer xp = &x; - ASSERT( &xr==xp, NULL ); -} - -template -void CheckConstIterator( const Vector& u, int i, const Iterator& cp ) { - typename Vector::const_reference pref = *cp; - if( pref.bar()!=i ) - REPORT("ERROR for u[%ld] using const_iterator\n", long(i)); - typename Vector::difference_type delta = cp-u.begin(); - ASSERT( delta==i, NULL ); - if( u[i].bar()!=i ) - REPORT("ERROR for u[%ld] using subscripting\n", long(i)); - ASSERT( u.begin()[i].bar()==i, NULL ); -} - -template -void CheckIteratorComparison( V& u ) { - V u2 = u; - Iterator1 i = u.begin(); - - for( int i_count=0; i_count<100; ++i_count ) { - Iterator2 j = u.begin(); - Iterator2 i2 = u2.begin(); - for( int j_count=0; j_count<100; ++j_count ) { - ASSERT( (i==j)==(i_count==j_count), NULL ); - ASSERT( (i!=j)==(i_count!=j_count), NULL ); - ASSERT( (i-j)==(i_count-j_count), NULL ); - ASSERT( (ij)==(i_count>j_count), NULL ); - ASSERT( (i<=j)==(i_count<=j_count), NULL ); - ASSERT( (i>=j)==(i_count>=j_count), NULL ); - ASSERT( !(i==i2), NULL ); - ASSERT( i!=i2, NULL ); - ++j; - ++i2; - } - ++i; - } -} - -//! Test sequential iterators for vector type V. -/** Also does timing. */ -template -void TestSequentialFor() { - typedef tbb::concurrent_vector V; - V v(N); - ASSERT(v.grow_by(0) == v.grow_by(0, FooWithAssign()), NULL); - - // Check iterator - tbb::tick_count t0 = tbb::tick_count::now(); - typename V::iterator p = v.begin(); - ASSERT( !(*p).is_const(), NULL ); - ASSERT( !p->is_const(), NULL ); - for( int i=0; size_t(i)is_const(), NULL ); - ASSERT( *cp == v.front(), NULL); - for( int i=0; size_t(i)0; ) { - --i; - V::const_iterator &cpr = --cp; - ASSERT( &cpr == &cp, "predecrement not returning a reference?"); - if( i>0 ) { - typename V::const_iterator cp_old = cp--; - int here = (*cp_old).bar(); - ASSERT( here==u[i].bar(), NULL ); - typename V::const_iterator cp_new = cp++; - int prev = (*cp_new).bar(); - ASSERT( prev==u[i-1].bar(), NULL ); - } - CheckConstIterator(u,i,cp); - } - - // Now go forwards and backwards - ptrdiff_t k = 0; - cp = u.begin(); - for( size_t i=0; i(v); - CheckIteratorComparison(v); - CheckIteratorComparison(v); - CheckIteratorComparison(v); - - TestIteratorAssignment( u.begin() ); - TestIteratorAssignment( v.begin() ); - TestIteratorAssignment( v.cbegin() ); - TestIteratorAssignment( v.begin() ); - // doesn't compile as expected: TestIteratorAssignment( u.begin() ); - - TestRangeAssignment( u.range() ); - TestRangeAssignment( v.range() ); - TestRangeAssignment( v.range() ); - // doesn't compile as expected: TestRangeAssignment( u.range() ); - - // Check reverse_iterator - typename V::reverse_iterator rp = v.rbegin(); - for( size_t i=v.size(); i>0; --i, ++rp ) { - typename V::reference pref = *rp; - ASSERT( size_t(pref.bar())==i-1, NULL ); - ASSERT( rp!=v.rend(), NULL ); - } - ASSERT( rp==v.rend(), NULL ); - - // Check const_reverse_iterator - typename V::const_reverse_iterator crp = u.rbegin(); - ASSERT( crp == v.crbegin(), NULL ); - ASSERT( *crp == v.back(), NULL); - for( size_t i=v.size(); i>0; --i, ++crp ) { - typename V::const_reference cpref = *crp; - ASSERT( size_t(cpref.bar())==i-1, NULL ); - ASSERT( crp!=u.rend(), NULL ); - } - ASSERT( crp == u.rend(), NULL ); - ASSERT( crp == v.crend(), NULL ); - - TestIteratorAssignment( u.rbegin() ); - TestIteratorAssignment( v.rbegin() ); - - // test compliance with C++ Standard 2003, clause 23.1.1p9 - { - tbb::concurrent_vector v1, v2(1, 100); - v1.assign(1, 100); ASSERT(v1 == v2, NULL); - ASSERT(v1.size() == 1 && v1[0] == 100, "used integral iterators"); - } - - // cross-allocator tests -#if !defined(_WIN64) || defined(_CPPLIB_VER) - typedef local_counting_allocator, size_t> allocator1_t; - typedef tbb::cache_aligned_allocator allocator2_t; - typedef tbb::concurrent_vector V1; - typedef tbb::concurrent_vector V2; - V1 v1( v ); // checking cross-allocator copying - V2 v2( 10 ); v2 = v1; // checking cross-allocator assignment - ASSERT( (v1 == v) && !(v2 != v), NULL); - ASSERT( !(v1 < v) && !(v2 > v), NULL); - ASSERT( (v1 <= v) && (v2 >= v), NULL); -#endif -} - -static const size_t Modulus = 7; - -typedef static_counting_allocator > MyAllocator; -typedef tbb::concurrent_vector MyVector; - -template -class GrowToAtLeast: NoAssign { - MyVector& my_vector; -public: - void operator()( const tbb::blocked_range& range ) const { - for( size_t i=range.begin(); i!=range.end(); ++i ) { - size_t n = my_vector.size(); - size_t req = (i % (2*n+1))+1; -#if TBB_DEPRECATED - my_vector.grow_to_at_least(req); -#else - typename MyVector::iterator p = my_vector.grow_to_at_least(req); - if( p-my_vector.begin() < typename MyVector::difference_type(req) ) - ASSERT( p->state == Foo::DefaultInitialized || p->state == Foo::ZeroInitialized, NULL); -#endif - ASSERT( my_vector.size()>=req, NULL ); - } - } - GrowToAtLeast( MyVector& vector ) : my_vector(vector) {} -}; - -void TestConcurrentGrowToAtLeast() { - typedef static_counting_allocator< tbb::zero_allocator > MyAllocator; - typedef tbb::concurrent_vector MyVector; - MyAllocator::init_counters(); - MyVector v(2, Foo(), MyAllocator()); - for( size_t s=1; s<1000; s*=10 ) { - tbb::parallel_for( tbb::blocked_range(0,10000*s,s), GrowToAtLeast(v), tbb::simple_partitioner() ); - } - v.clear(); - ASSERT( 0 == v.get_allocator().frees, NULL); - v.shrink_to_fit(); - size_t items_allocated = v.get_allocator().items_allocated, - items_freed = v.get_allocator().items_freed; - size_t allocations = v.get_allocator().allocations, - frees = v.get_allocator().frees; - ASSERT( items_allocated == items_freed, NULL); - ASSERT( allocations == frees, NULL); -} - -//! Test concurrent invocations of method concurrent_vector::grow_by -template -class GrowBy: NoAssign { - MyVector& my_vector; -public: - void operator()( const tbb::blocked_range& range ) const { - ASSERT( range.begin() < range.end(), NULL ); -#if TBB_DEPRECATED - for( int i=range.begin(); i!=range.end(); ++i ) -#else - int i = range.begin(), h = (range.end() - i) / 2; - typename MyVector::iterator s = my_vector.grow_by(h); - for( h += i; i < h; ++i, ++s ) - s->bar() = i; - for(; i!=range.end(); ++i ) -#endif - { - if( i&1 ) { -#if TBB_DEPRECATED - typename MyVector::reference element = my_vector[my_vector.grow_by(1)]; - element.bar() = i; -#else - my_vector.grow_by(1)->bar() = i; -#endif - } else { - typename MyVector::value_type f; - f.bar() = i; -#if TBB_DEPRECATED - size_t r; -#else - typename MyVector::iterator r; -#endif - if( i&2 ) - r = my_vector.push_back( f ); - else - r = my_vector.grow_by(1, f); -#if TBB_DEPRECATED - ASSERT( my_vector[r].bar()==i, NULL ); -#else - ASSERT( r->bar()==i, NULL ); -#endif - } - } - } - GrowBy( MyVector& vector ) : my_vector(vector) {} -}; - -//! Test concurrent invocations of method concurrent_vector::grow_by -void TestConcurrentGrowBy( int nthread ) { - MyAllocator::init_counters(); - { - int m = 100000; MyAllocator a; - MyVector v( a ); - tbb::parallel_for( tbb::blocked_range(0,m,100), GrowBy(v), tbb::simple_partitioner() ); - ASSERT( v.size()==size_t(m), NULL ); - - // Verify that v is a permutation of 0..m - int inversions = 0, def_inits = 0, copy_inits = 0; - bool* found = new bool[m]; - memset( found, 0, m ); - for( int i=0; i0 ) - inversions += v[i].bar()1 || v[i].bar()==i, "sequential execution is wrong" ); - } - delete[] found; - REMARK("Initialization by default constructor: %d, by copy: %d\n", def_inits, copy_inits); - ASSERT( def_inits >= m/2, NULL ); - ASSERT( copy_inits >= m/4, NULL ); - if( nthread>1 && inversions, size_t > > vector_t; - local_counting_allocator, size_t > init_alloc; - init_alloc.allocations = 100; - for( int dst_size=1; dst_size<=128; NextSize( dst_size ) ) { - for( int src_size=2; src_size<=128; NextSize( src_size ) ) { - vector_t u(FooIterator(0), FooIterator(src_size), init_alloc); - for( int i=0; i - -#if !TBB_USE_EXCEPTIONS && _MSC_VER - #pragma warning (pop) -#endif - -void TestComparison() { - std::string str[3]; str[0] = "abc"; - str[1].assign("cba"); - str[2].assign("abc"); // same as 0th - tbb::concurrent_vector var[3]; - var[0].assign(str[0].begin(), str[0].end()); - var[1].assign(str[0].rbegin(), str[0].rend()); - var[2].assign(var[1].rbegin(), var[1].rend()); // same as 0th - for (int i = 0; i < 3; ++i) { - for (int j = 0; j < 3; ++j) { - ASSERT( (var[i] == var[j]) == (str[i] == str[j]), NULL ); - ASSERT( (var[i] != var[j]) == (str[i] != str[j]), NULL ); - ASSERT( (var[i] < var[j]) == (str[i] < str[j]), NULL ); - ASSERT( (var[i] > var[j]) == (str[i] > str[j]), NULL ); - ASSERT( (var[i] <= var[j]) == (str[i] <= str[j]), NULL ); - ASSERT( (var[i] >= var[j]) == (str[i] >= str[j]), NULL ); - } - } -} - -//------------------------------------------------------------------------ -// Regression test for problem where on oversubscription caused -// concurrent_vector::grow_by to run very slowly (TR#196). -//------------------------------------------------------------------------ - -#include "tbb/task_scheduler_init.h" -#include - -typedef unsigned long Number; - -static tbb::concurrent_vector Primes; - -class FindPrimes { - bool is_prime( Number val ) const { - int limit, factor = 3; - if( val<5u ) - return val==2; - else { - limit = long(sqrtf(float(val))+0.5f); - while( factor<=limit && val % factor ) - ++factor; - return factor>limit; - } - } -public: - void operator()( const tbb::blocked_range& r ) const { - for( Number i=r.begin(); i!=r.end(); ++i ) { - if( i%2 && is_prime(i) ) { -#if TBB_DEPRECATED - Primes[Primes.grow_by(1)] = i; -#else - Primes.push_back( i ); -#endif - } - } - } -}; - -double TimeFindPrimes( int nthread ) { - Primes.clear(); - Primes.reserve(1000000);// TODO: or compact()? - tbb::task_scheduler_init init(nthread); - tbb::tick_count t0 = tbb::tick_count::now(); - tbb::parallel_for( tbb::blocked_range(0,1000000,500), FindPrimes() ); - tbb::tick_count t1 = tbb::tick_count::now(); - return (t1-t0).seconds(); -} - -void TestFindPrimes() { - // Time fully subscribed run. - double t2 = TimeFindPrimes( tbb::task_scheduler_init::automatic ); - - // Time parallel run that is very likely oversubscribed. -#if _XBOX - double t128 = TimeFindPrimes(32); //XBOX360 can't handle too many threads -#else - double t128 = TimeFindPrimes(128); -#endif - REMARK("TestFindPrimes: t2==%g t128=%g k=%g\n", t2, t128, t128/t2); - - // We allow the 128-thread run a little extra time to allow for thread overhead. - // Theoretically, following test will fail on machine with >128 processors. - // But that situation is not going to come up in the near future, - // and the generalization to fix the issue is not worth the trouble. - if( t128 > 1.3*t2 ) { - REPORT("Warning: grow_by is pathetically slow: t2==%g t128=%g k=%g\n", t2, t128, t128/t2); - } -} - -//------------------------------------------------------------------------ -// Test compatibility with STL sort. -//------------------------------------------------------------------------ - -#include - -void TestSort() { - for( int n=0; n<100; n=n*3+1 ) { - tbb::concurrent_vector array(n); - for( int i=0; i, std::size_t> allocator_t; - typedef tbb::concurrent_vector vector_t; - - enum methods { - zero_method = 0, - ctor_copy, ctor_size, assign_nt, assign_ir, op_equ, reserve, compact, grow, - all_methods - }; - ASSERT( !FooCount, NULL ); - - try { - vector_t src(FooIterator(0), FooIterator(N)); // original data - - for(int t = 0; t < 2; ++t) // exception type - for(int m = zero_method+1; m < all_methods; ++m) - { - ASSERT( FooCount == N, "Previous iteration miss some Foo's de-/initialization" ); - allocator_t::init_counters(); - if(t) MaxFooCount = FooCount + N/4; - else allocator_t::set_limits(N/4); - vector_t victim; - try { - switch(m) { - case ctor_copy: { - vector_t acopy(src); - } break; // auto destruction after exception is checked by ~Foo - case ctor_size: { - vector_t sized(N); - } break; // auto destruction after exception is checked by ~Foo - // Do not test assignment constructor due to reusing of same methods as below - case assign_nt: { - victim.assign(N, FooWithAssign()); - } break; - case assign_ir: { - victim.assign(FooIterator(0), FooIterator(N)); - } break; - case op_equ: { - victim.reserve(2); victim = src; // fragmented assignment - } break; - case reserve: { - try { - victim.reserve(victim.max_size()+1); - } catch(std::length_error &) { - } catch(...) { - KNOWN_ISSUE("ERROR: unrecognized exception - known compiler issue\n"); - } - victim.reserve(N); - } break; - case compact: { - if(t) MaxFooCount = 0; else allocator_t::set_limits(); // reset limits - victim.reserve(2); victim = src; // fragmented assignment - if(t) MaxFooCount = FooCount + 10; else allocator_t::set_limits(1, false); // block any allocation, check NULL return from allocator - victim.shrink_to_fit(); // should start defragmenting first segment - } break; - case grow: { - tbb::task_scheduler_init init(2); - if(t) MaxFooCount = FooCount + 31; // these numbers help to reproduce the live lock for versions < TBB2.2 - try { - tbb::parallel_for( tbb::blocked_range(0, N, 70), GrowBy(victim) ); - } catch(...) { -#if TBB_USE_CAPTURED_EXCEPTION - throw tbb::bad_last_alloc(); -#else - throw; -#endif - } - } break; - default:; - } - if(!t || m != reserve) ASSERT(false, "should throw an exception"); - } catch(std::bad_alloc &e) { - allocator_t::set_limits(); MaxFooCount = 0; - size_t capacity = victim.capacity(); - size_t size = victim.size(); -#if TBB_DEPRECATED - size_t req_size = victim.grow_by(0); -#else - size_t req_size = victim.grow_by(0) - victim.begin(); -#endif - ASSERT( size <= capacity, NULL); - ASSERT( req_size >= size, NULL); - switch(m) { - case reserve: - if(t) ASSERT(false, NULL); - case assign_nt: - case assign_ir: - if(!t) { - ASSERT(capacity < N/2, "unexpected capacity"); - ASSERT(size == 0, "unexpected size"); - break; - } else { - ASSERT(size == N, "unexpected size"); - ASSERT(capacity >= N, "unexpected capacity"); - int i; - for(i = 1; ; ++i) - if(!victim[i].zero_bar()) break; - else ASSERT(victim[i].bar() == (m == assign_ir)? i : initial_value_of_bar, NULL); - for(; size_t(i) < size; ++i) ASSERT(!victim[i].zero_bar(), NULL); - ASSERT(size_t(i) == size, NULL); - break; - } - case grow: - case op_equ: - if(!t) { - ASSERT(capacity > 0, NULL); - ASSERT(capacity < N, "unexpected capacity"); - } - { - vector_t copy_of_victim(victim); - ASSERT(copy_of_victim.size() > 0, NULL); - for(int i = 0; ; ++i) { - try { - FooWithAssign &foo = victim.at(i); - if( !foo.is_valid_or_zero() ) { - std::printf("i: %d size: %u req_size: %u state: %d\n", i, unsigned(size), unsigned(req_size), foo.state); - } - int bar = foo.zero_bar(); - if(m != grow) ASSERT( bar == i || (t && bar == 0), NULL); - if(size_t(i) < copy_of_victim.size()) ASSERT( copy_of_victim[i].bar() == bar, NULL); - } catch(std::range_error &) { // skip broken segment - ASSERT( size_t(i) < req_size, NULL ); - if(m == op_equ) break; - } catch(std::out_of_range &){ - ASSERT( i > 0, NULL ); break; - } catch(...) { - KNOWN_ISSUE("ERROR: unrecognized exception - known compiler issue\n"); break; - } - } - vector_t copy_of_victim2(10); copy_of_victim2 = victim; - ASSERT(copy_of_victim == copy_of_victim2, "assignment doesn't match copying"); - if(m == op_equ) { - try { - victim = copy_of_victim2; - } catch(tbb::bad_last_alloc &) { break; - } catch(...) { - KNOWN_ISSUE("ERROR: unrecognized exception - known compiler issue\n"); break; - } - ASSERT(t, NULL); - } - } break; - case compact: - ASSERT(capacity > 0, "unexpected capacity"); - ASSERT(victim == src, "shrink_to_fit() is broken"); - break; - - default:; // nothing to check here - } - REMARK("Exception %d: %s\t- ok\n", m, e.what()); - } - } - } catch(...) { - ASSERT(false, "unexpected exception"); - } -} -#endif /* TBB_USE_EXCEPTIONS */ - -//------------------------------------------------------------------------ -// Test SSE -//------------------------------------------------------------------------ -#include "harness_m128.h" - -#if HAVE_m128 - -void TestSSE() { - tbb::concurrent_vector v; - for( int i=0; i<100; ++i ) { - v.push_back(ClassWithSSE(i)); - for( int j=0; i::iterator,Foo>(); - TestIteratorTraits::const_iterator,const Foo>(); - TestSequentialFor (); - TestResizeAndCopy(); - TestAssign(); -#if HAVE_m128 - TestSSE(); -#endif /* HAVE_m128 */ -#endif - TestCapacity(); - ASSERT( !FooCount, NULL ); - for( int nthread=MinThread; nthread<=MaxThread; ++nthread ) { - tbb::task_scheduler_init init( nthread ); - TestParallelFor( nthread ); - TestConcurrentGrowToAtLeast(); - TestConcurrentGrowBy( nthread ); - } - ASSERT( !FooCount, NULL ); -#if !TBB_DEPRECATED - TestComparison(); - TestFindPrimes(); - TestSort(); -#if __TBB_THROW_ACROSS_MODULE_BOUNDARY_BROKEN - REPORT("Known issue: exception safety test is skipped.\n"); -#elif TBB_USE_EXCEPTIONS - TestExceptions(); -#endif /* TBB_USE_EXCEPTIONS */ -#endif /* !TBB_DEPRECATED */ - ASSERT( !FooCount, NULL ); - REMARK("sizeof(concurrent_vector) == %d\n", (int)sizeof(tbb::concurrent_vector)); - return Harness::Done; -} diff --git a/deal.II/contrib/tbb/tbb30_104oss/src/test/test_condition_variable.h b/deal.II/contrib/tbb/tbb30_104oss/src/test/test_condition_variable.h deleted file mode 100644 index 542255785e..0000000000 --- a/deal.II/contrib/tbb/tbb30_104oss/src/test/test_condition_variable.h +++ /dev/null @@ -1,693 +0,0 @@ -/* - Copyright 2005-2010 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. -*/ - -#include "tbb/compat/condition_variable" -#include "tbb/mutex.h" -#include "tbb/recursive_mutex.h" -#include "tbb/tick_count.h" -#include "tbb/atomic.h" - -#include "harness.h" - -// This test deliberately avoids a "using tbb" statement, -// so that the error of putting types in the wrong namespace will be caught. - -using namespace std; - -template -struct Counter { - typedef M mutex_type; - M mutex; - volatile long value; - void flog_once_lock_guard( size_t mode ); - void flog_once_unique_lock( size_t mode ); -}; - -template -void Counter::flog_once_lock_guard(size_t mode) -/** Increments counter once for each iteration in the iteration space. */ -{ - if( mode&1 ) { - // Try acquire and release with implicit lock_guard - // precondition: if mutex_type is not a recursive mutex, the calling thread does not own the mutex m. - // if the prcondition is not met, either dead-lock incorrect 'value' would result in. - lock_guard lg(mutex); - value = value+1; - } else { - // Try acquire and release with adopt lock_quard - // precodition: the calling thread owns the mutex m. - // if the prcondition is not met, incorrect 'value' would result in because the thread unlocks - // mutex that it does not own. - mutex.lock(); - lock_guard lg( mutex, adopt_lock ); - value = value+1; - } -} - -template -void Counter::flog_once_unique_lock(size_t mode) -/** Increments counter once for each iteration in the iteration space. */ -{ - switch( mode&7 ) { - case 0: - {// implicitly acquire and release mutex with unique_lock - unique_lock ul( mutex ); - value = value+1; - ASSERT( ul==true, NULL ); - } - break; - case 1: - {// unique_lock with defer_lock - unique_lock ul( mutex, defer_lock ); - ASSERT( ul.owns_lock()==false, NULL ); - ul.lock(); - value = value+1; - ASSERT( ul.owns_lock()==true, NULL ); - } - break; - case 2: - {// unique_lock::try_lock() with try_to_lock - unique_lock ul( mutex, try_to_lock ); - if( !ul ) - while( !ul.try_lock() ) - __TBB_Yield(); - value = value+1; - } - break; - case 3: - {// unique_lock::try_lock_for() with try_to_lock - unique_lock ul( mutex, defer_lock ); - tbb::tick_count::interval_t i(1.0); - while( !ul.try_lock_for( i ) ) - ; - value = value+1; - ASSERT( ul.owns_lock()==true, NULL ); - } - break; - case 4: - { - unique_lock ul_o4; - {// unique_lock with adopt_lock - mutex.lock(); - unique_lock ul( mutex, adopt_lock ); - value = value+1; - ASSERT( ul.owns_lock()==true, NULL ); - ASSERT( ul.mutex()==&mutex, NULL ); - ASSERT( ul_o4.owns_lock()==false, NULL ); - ASSERT( ul_o4.mutex()==NULL, NULL ); - swap( ul, ul_o4 ); - ASSERT( ul.owns_lock()==false, NULL ); - ASSERT( ul.mutex()==NULL, NULL ); - ASSERT( ul_o4.owns_lock()==true, NULL ); - ASSERT( ul_o4.mutex()==&mutex, NULL ); - ul_o4.unlock(); - } - ASSERT( ul_o4.owns_lock()==false, NULL ); - } - break; - case 5: - { - unique_lock ul_o5; - {// unique_lock with adopt_lock - mutex.lock(); - unique_lock ul( mutex, adopt_lock ); - value = value+1; - ASSERT( ul.owns_lock()==true, NULL ); - ASSERT( ul.mutex()==&mutex, NULL ); - ASSERT( ul_o5.owns_lock()==false, NULL ); - ASSERT( ul_o5.mutex()==NULL, NULL ); - ul_o5.swap( ul ); - ASSERT( ul.owns_lock()==false, NULL ); - ASSERT( ul.mutex()==NULL, NULL ); - ASSERT( ul_o5.owns_lock()==true, NULL ); - ASSERT( ul_o5.mutex()==&mutex, NULL ); - ul_o5.unlock(); - } - ASSERT( ul_o5.owns_lock()==false, NULL ); - } - break; - default: - {// unique_lock with adopt_lock, and release() - mutex.lock(); - unique_lock ul( mutex, adopt_lock ); - ASSERT( ul==true, NULL ); - value = value+1; - M* old_m = ul.release(); - old_m->unlock(); - ASSERT( ul.owns_lock()==false, NULL ); - } - break; - } -} - -static tbb::atomic Order; - -template -struct WorkForLocks: NoAssign { - static const size_t chunk = 100; - State& state; - WorkForLocks( State& state_ ) : state(state_) {} - void operator()( int ) const { - size_t step; - while( (step=Order.fetch_and_add(chunk)) -void TestLocks( const char* name, int nthread ) { - REMARK("testing %s in TestLocks\n",name); - Counter counter; - counter.value = 0; - Order = 0; - const long test_size = 100000; - NativeParallelFor( nthread, WorkForLocks, test_size>(counter) ); - - if( counter.value!=2*test_size ) - REPORT("ERROR for %s in TestLocks: counter.value=%ld != 2 * %ld=test_size\n",name,counter.value,test_size); -} - -static tbb::atomic barrier; - -// Test if the constructor works and if native_handle() works -template -struct WorkForCondVarCtor: NoAssign { - condition_variable& my_cv; - M& my_mtx; - WorkForCondVarCtor( condition_variable& cv_, M& mtx_ ) : my_cv(cv_), my_mtx(mtx_) {} - void operator()( int tid ) const { - ASSERT( tid<=1, NULL ); // test with 2 threads. - condition_variable::native_handle_type handle = my_cv.native_handle(); - if( tid&1 ) { - my_mtx.lock(); - ++barrier; -#if _WIN32||_WIN64 - if( !tbb::interface5::internal::internal_condition_variable_wait( *handle, &my_mtx ) ) { - int ec = GetLastError(); - ASSERT( ec!=WAIT_TIMEOUT, NULL ); - throw_exception( tbb::internal::eid_condvar_wait_failed ); - } -#else - if( pthread_cond_wait( handle, my_mtx.native_handle() ) ) - throw_exception( tbb::internal::eid_condvar_wait_failed ); -#endif - ++barrier; - my_mtx.unlock(); - } else { - bool res; - while( (res=my_mtx.try_lock())==true && barrier==0 ) { - my_mtx.unlock(); - __TBB_Yield(); - } - if( res ) my_mtx.unlock(); - do { -#if _WIN32||_WIN64 - tbb::interface5::internal::internal_condition_variable_notify_one( *handle ); -#else - pthread_cond_signal( handle ); -#endif - __TBB_Yield(); - } while ( barrier<2 ); - } - } -}; - -static condition_variable* test_cv; -static tbb::atomic n_waiters; - -// Test if the destructor works -template -struct WorkForCondVarDtor: NoAssign { - int nthread; - M& my_mtx; - WorkForCondVarDtor( int n, M& mtx_ ) : nthread(n), my_mtx(mtx_) {} - void operator()( int tid ) const { - if( tid==0 ) { - unique_lock ul( my_mtx, defer_lock ); - test_cv = new condition_variable; - - while( n_waitersnotify_all(); - ul.unlock(); - while( n_waiters>0 ) - __TBB_Yield(); - delete test_cv; - } else { - while( test_cv==NULL ) - __TBB_Yield(); - unique_lock ul(my_mtx); - ++n_waiters; - test_cv->wait( ul ); - --n_waiters; - } - } -}; - -static const int max_ticket = 100; -static const int short_delay = 10; -static const int long_delay = 100; - -tbb::atomic n_signaled; -tbb::atomic n_done, n_done_1, n_done_2; -tbb::atomic n_timed_out; - -static bool false_to_true; - -struct TestPredicateFalseToTrue { - TestPredicateFalseToTrue() {} - bool operator()() { return false_to_true; } -}; - -struct TestPredicateFalse { - TestPredicateFalse() {} - bool operator()() { return false; } -}; - -struct TestPredicateTrue { - TestPredicateTrue() {} - bool operator()() { return true; } -}; - -// Test timed wait and timed wait with pred -template -struct WorkForCondVarTimedWait: NoAssign { - int nthread; - condition_variable& test_cv; - M& my_mtx; - WorkForCondVarTimedWait( int n_, condition_variable& cv_, M& mtx_ ) : nthread(n_), test_cv(cv_), my_mtx(mtx_) {} - void operator()( int tid ) const { - tbb::tick_count t1, t2; - - unique_lock ul( my_mtx, defer_lock ); - - ASSERT( n_timed_out==0, NULL ); - ++barrier; - while( barrier0, "should have been timed-out at least once\n" ); - ++n_done_1; - while( n_done_10, "too small an interval?" ); - n_signaled = 0; - - } else { - while( n_done_20, "too small an interval?" ); - } else { - - while( n_done<1 ) __TBB_Yield(); // gate 3 - - tbb::tick_count::interval_t intv((double)2.0 /*seconds*/); - ul.lock(); - ++n_waiters; - // wait_for w/ predciate - t1 = tbb::tick_count::now(); - ASSERT( test_cv.wait_for( ul, intv, TestPredicateFalseToTrue())==true, NULL ); // gate 4 - t2 = tbb::tick_count::now(); - ul.unlock(); - if( (t2-t1).seconds() ticket_for_sleep, ticket_for_wakeup, signaled_ticket, wokeup_ticket; -tbb::atomic n_visit_to_waitq; -unsigned max_waitq_length; - -template -struct WorkForCondVarWaitAndNotifyOne: NoAssign { - int nthread; - condition_variable& test_cv; - M& my_mtx; - WorkForCondVarWaitAndNotifyOne( int n_, condition_variable& cv_, M& mtx_ ) : nthread(n_), test_cv(cv_), my_mtx(mtx_) {} - void operator()( int tid ) const { - if( tid&1 ) { - // exercise signal part - while( ticket_for_wakeupmax_ticket ) - break; - - for( ;; ) { - unique_lock ul( my_mtx, defer_lock ); - ul.lock(); - if( n_waiters>0 && my_ticket<=ticket_for_sleep && my_ticket==(wokeup_ticket+1) ) { - signaled_ticket = my_ticket; - test_cv.notify_one(); - ++n_signaled; - ul.unlock(); - break; - } - ul.unlock(); - __TBB_Yield(); - } - - // give waiters time to go to sleep. - for( int m=0; m ul( my_mtx, defer_lock ); - ul.lock(); - // exercise wait part - int my_ticket = ++ticket_for_sleep; // grab my ticket - if( my_ticket>max_ticket ) break; - - // each waiter should go to sleep at least once - unsigned nw = ++n_waiters; - for( ;; ) { - // update to max_waitq_length - if( nw>max_waitq_length ) max_waitq_length = nw; - ++n_visit_to_waitq; - test_cv.wait( ul ); - // if( ret==false ) ++n_timedout; - ASSERT( ul, "mutex should have been locked" ); - --n_waiters; - if( signaled_ticket==my_ticket ) { - wokeup_ticket = my_ticket; - break; - } - if( n_waiters>0 ) - test_cv.notify_one(); - nw = ++n_waiters; // update to max_waitq_length occurs above - } - - ul.unlock(); - __TBB_Yield(); // give other threads chance to run. - } - } - ++n_done; - spin_wait_until_eq( n_done, nthread ); - ASSERT( n_signaled==max_ticket, "incorrect number of notifications sent" ); - } -}; - -struct TestPredicate1 { - int target; - TestPredicate1( int i_ ) : target(i_) {} - bool operator()( ) { return signaled_ticket==target; } -}; - -template -struct WorkForCondVarWaitPredAndNotifyAll: NoAssign { - int nthread; - condition_variable& test_cv; - M& my_mtx; - int multiple; - WorkForCondVarWaitPredAndNotifyAll( int n_, condition_variable& cv_, M& mtx_, int m_ ) : - nthread(n_), test_cv(cv_), my_mtx(mtx_), multiple(m_) {} - void operator()( int tid ) const { - if( tid&1 ) { - while( ticket_for_sleep ul( my_mtx, defer_lock ); - // exercise wait part - int my_ticket = ++ticket_for_sleep; // grab my ticket - if( my_ticket>max_ticket ) - break; - - ul.lock(); - ++n_visit_to_waitq; - unsigned nw = ++n_waiters; - if( nw>max_waitq_length ) max_waitq_length = nw; - test_cv.wait( ul, TestPredicate1( my_ticket ) ); - wokeup_ticket = my_ticket; - --n_waiters; - ASSERT( ul, "mutex should have been locked" ); - ul.unlock(); - - __TBB_Yield(); // give other threads chance to run. - } - } else { - // exercise signal part - while( ticket_for_wakeupmax_ticket ) - break; - - for( ;; ) { - unique_lock ul( my_mtx ); - if( n_waiters>0 && my_ticket<=ticket_for_sleep && my_ticket==(wokeup_ticket+1) ) { - signaled_ticket = my_ticket; - test_cv.notify_all(); - ++n_signaled; - ul.unlock(); - break; - } - ul.unlock(); - __TBB_Yield(); - } - - // give waiters time to go to sleep. - for( int m=0; m -void TestConditionVariable( const char* name, int nthread ) -{ - REMARK("testing %s in TestConditionVariable\n",name); - Counter counter; - M mtx; - - ASSERT( nthread>1, "at least two threads are needed for testing condition_variable" ); - REMARK(" - constructor\n" ); - // Test constructor. - { - condition_variable cv1; -#if _WIN32||_WIN64 - condition_variable::native_handle_type handle = cv1.native_handle(); - ASSERT( uintptr_t(&handle->cv_event)==uintptr_t(&handle->cv_native), NULL ); -#endif - M mtx1; - barrier = 0; - NativeParallelFor( 2, WorkForCondVarCtor( cv1, mtx1 ) ); - } - - REMARK(" - destructor\n" ); - // Test destructor. - { - M mtx2; - test_cv = NULL; - n_waiters = 0; - NativeParallelFor( nthread, WorkForCondVarDtor( nthread, mtx2 ) ); - } - - REMARK(" - timed_wait (i.e., wait_for)\n"); - // Test timed wait. - { - condition_variable cv_tw; - M mtx_tw; - barrier = 0; - InitGlobalCounters(); - int nthr = nthread>4?4:nthread; - NativeParallelFor( nthr, WorkForCondVarTimedWait( nthr, cv_tw, mtx_tw ) ); - } - - REMARK(" - wait with notify_one\n"); - // Test wait and notify_one - do { - condition_variable cv3; - M mtx3; - InitGlobalCounters(); - NativeParallelFor( nthread, WorkForCondVarWaitAndNotifyOne( nthread, cv3, mtx3 ) ); - } while( n_visit_to_waitq==0 || max_waitq_length==0 ); - - REMARK(" - predicated wait with notify_all\n"); - // Test wait_pred and notify_all - int delay_multiple = 1; - do { - condition_variable cv4; - M mtx4; - InitGlobalCounters(); - NativeParallelFor( nthread, WorkForCondVarWaitPredAndNotifyAll( nthread, cv4, mtx4, delay_multiple ) ); - if( max_waitq_length err_count; - -#define TRY_AND_CATCH_RUNTIME_ERROR(op,msg) \ - try { \ - op; \ - ++err_count; \ - } catch( std::runtime_error& e ) {ASSERT( strstr(e.what(), msg) , NULL );} catch(...) {++err_count;} - -template -void TestUniqueLockException( const char * name ) { - REMARK("testing %s TestUniqueLockException\n",name); - M mtx; - unique_lock ul_0; - err_count = 0; - - TRY_AND_CATCH_RUNTIME_ERROR( ul_0.lock(), "Operation not permitted" ); - TRY_AND_CATCH_RUNTIME_ERROR( ul_0.try_lock(), "Operation not permitted" ); - - unique_lock ul_1( mtx ); - - TRY_AND_CATCH_RUNTIME_ERROR( ul_1.lock(), "Resource deadlock" ); - TRY_AND_CATCH_RUNTIME_ERROR( ul_1.try_lock(), "Resource deadlock" ); - - ul_1.unlock(); - TRY_AND_CATCH_RUNTIME_ERROR( ul_1.unlock(), "Operation not permitted" ); - - ASSERT( !err_count, "Some exceptions are not thrown or incorrect ones are thrown" ); -} - -template -void TestConditionVariableException( const char * name ) { - REMARK("testing %s in TestConditionVariableException; yet to be implemented\n",name); -} -#endif /* TBB_USE_EXCEPTIONS */ - -template -void DoCondVarTest() -{ - for( int p=MinThread; p<=MaxThread; ++p ) { - REMARK( "testing with %d threads\n", p ); - TestLocks( "mutex", p ); - TestLocks( "recursive_mutex", p ); - - if( p<=1 ) continue; - - // for testing condition_variable, at least one sleeper and one notifier are needed - TestConditionVariable( "mutex", p ); - } -#if __TBB_THROW_ACROSS_MODULE_BOUNDARY_BROKEN - REPORT("Known issue: exception handling tests are skipped.\n"); -#elif TBB_USE_EXCEPTIONS - TestUniqueLockException( "mutex" ); - TestUniqueLockException( "recursive_mutex" ); - TestConditionVariableException( "mutex" ); -#endif /* TBB_USE_EXCEPTIONS */ -} diff --git a/deal.II/contrib/tbb/tbb30_104oss/src/test/test_critical_section.cpp b/deal.II/contrib/tbb/tbb30_104oss/src/test/test_critical_section.cpp deleted file mode 100644 index 7ca00b8366..0000000000 --- a/deal.II/contrib/tbb/tbb30_104oss/src/test/test_critical_section.cpp +++ /dev/null @@ -1,224 +0,0 @@ -/* - Copyright 2005-2010 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. -*/ - -// test critical section -// -#include "tbb/critical_section.h" -#include "tbb/task_scheduler_init.h" -#include "tbb/enumerable_thread_specific.h" -#include "tbb/tick_count.h" -#include "harness_assert.h" -#include "harness.h" -#include - -#include "harness_barrier.h" -Harness::SpinBarrier sBarrier; -tbb::critical_section cs; -const int MAX_WORK = 300; - -struct BusyBody : NoAssign { - tbb::enumerable_thread_specific &locals; - const int nThread; - const int WorkRatiox100; - int &unprotected_count; - bool test_throw; - - BusyBody( int nThread_, int workRatiox100_, tbb::enumerable_thread_specific &locals_, int &unprotected_count_, bool test_throw_) : - locals(locals_), - nThread(nThread_), - WorkRatiox100(workRatiox100_), - unprotected_count(unprotected_count_), - test_throw(test_throw_) { - sBarrier.initialize(nThread_); - } - - void operator()(const int /* threadID */ ) const { - int nIters = MAX_WORK/nThread; - sBarrier.wait(); - tbb::tick_count t0 = tbb::tick_count::now(); - for(int j = 0; j < nIters; j++) { - - for(int i = 0; i < MAX_WORK * (100 - WorkRatiox100); i++) { - locals.local() += 1.0; - } - cs.lock(); - ASSERT( !cs.try_lock(), "recursive try_lock must fail" ); -#if TBB_USE_EXCEPTIONS && !__TBB_THROW_ACROSS_MODULE_BOUNDARY_BROKEN - if(test_throw && j == (nIters / 2)) { - bool was_caught = false, - unknown_exception = false; - try { - cs.lock(); - } - catch(tbb::improper_lock& e) { - ASSERT( e.what(), "Error message is absent" ); - was_caught = true; - } - catch(...) { - was_caught = unknown_exception = true; - } - ASSERT(was_caught, "Recursive lock attempt did not throw"); - ASSERT(!unknown_exception, "tbb::improper_lock exception is expected"); - } -#endif /* TBB_USE_EXCEPTIONS && !__TBB_THROW_ACROSS_MODULE_BOUNDARY_BROKEN */ - for(int i = 0; i < MAX_WORK * WorkRatiox100; i++) { - locals.local() += 1.0; - } - unprotected_count++; - cs.unlock(); - } - locals.local() = (tbb::tick_count::now() - t0).seconds(); - } -}; - -struct BusyBodyScoped : NoAssign { - tbb::enumerable_thread_specific &locals; - const int nThread; - const int WorkRatiox100; - int &unprotected_count; - bool test_throw; - - BusyBodyScoped( int nThread_, int workRatiox100_, tbb::enumerable_thread_specific &locals_, int &unprotected_count_, bool test_throw_) : - locals(locals_), - nThread(nThread_), - WorkRatiox100(workRatiox100_), - unprotected_count(unprotected_count_), - test_throw(test_throw_) { - sBarrier.initialize(nThread_); - } - - void operator()(const int /* threadID */ ) const { - int nIters = MAX_WORK/nThread; - sBarrier.wait(); - tbb::tick_count t0 = tbb::tick_count::now(); - for(int j = 0; j < nIters; j++) { - - for(int i = 0; i < MAX_WORK * (100 - WorkRatiox100); i++) { - locals.local() += 1.0; - } - { - tbb::critical_section::scoped_lock my_lock(cs); - for(int i = 0; i < MAX_WORK * WorkRatiox100; i++) { - locals.local() += 1.0; - } - unprotected_count++; - } - } - locals.local() = (tbb::tick_count::now() - t0).seconds(); - } -}; - -void -RunOneCriticalSectionTest(int nThreads, int csWorkRatio, bool test_throw) { - tbb::task_scheduler_init init(tbb::task_scheduler_init::deferred); - tbb::enumerable_thread_specific test_locals; - int myCount = 0; - BusyBody myBody(nThreads, csWorkRatio, test_locals, myCount, test_throw); - BusyBodyScoped myScopedBody(nThreads, csWorkRatio, test_locals, myCount, test_throw); - init.initialize(nThreads); - tbb::tick_count t0; - { - t0 = tbb::tick_count::now(); - myCount = 0; - NativeParallelFor(nThreads, myBody); - ASSERT(myCount == (MAX_WORK - (MAX_WORK % nThreads)), NULL); - REMARK("%d threads, work ratio %d per cent, time %g", nThreads, csWorkRatio, (tbb::tick_count::now() - t0).seconds()); - if (nThreads > 1) { - double etsSum = 0; - double etsMax = 0; - double etsMin = 0; - double etsSigmaSq = 0; - double etsSigma = 0; - - for(tbb::enumerable_thread_specific::const_iterator ci = test_locals.begin(); ci != test_locals.end(); ci++) { - etsSum += *ci; - if(etsMax==0.0) { - etsMin = *ci; - } - else { - if(etsMin > *ci) etsMin = *ci; - } - if(etsMax < *ci) etsMax = *ci; - } - double etsAvg = etsSum / (double)nThreads; - for(tbb::enumerable_thread_specific::const_iterator ci = test_locals.begin(); ci != test_locals.end(); ci++) { - etsSigma = etsAvg - *ci; - etsSigmaSq += etsSigma * etsSigma; - } - // an attempt to gauge the "fairness" of the scheduling of the threads. We figure - // the standard deviation, and compare it with the maximum deviation from the - // average time. If the difference is 0 that means all threads finished in the same - // amount of time. If non-zero, the difference is divided by the time, and the - // negative log is taken. If > 2, then the difference is on the order of 0.01*t - // where T is the average time. We aritrarily define this as "fair." - etsSigma = sqrt(etsSigmaSq/double(nThreads)); - etsMax -= etsAvg; // max - a == delta1 - etsMin = etsAvg - etsMin; // a - min == delta2 - if(etsMax < etsMin) etsMax = etsMin; - etsMax -= etsSigma; - // ASSERT(etsMax >= 0, NULL); // shouldn't the maximum difference from the mean be > the stddev? - etsMax = (etsMax > 0.0) ? etsMax : 0.0; // possible rounding error - double fairness = etsMax / etsAvg; - if(fairness == 0.0) { - fairness = 100.0; - } - else fairness = - log10(fairness); - if(fairness > 2.0 ) { - REMARK(" Fair (%g)\n", fairness); - } - else { - REMARK(" Unfair (%g)\n", fairness); - } - } - myCount = 0; - NativeParallelFor(nThreads, myScopedBody); - ASSERT(myCount == (MAX_WORK - (MAX_WORK % nThreads)), NULL); - - } - - init.terminate(); -} - -void -RunParallelTests() { - for(int p = MinThread; p <= MaxThread; p++) { - for(int cs_ratio = 1; cs_ratio < 95; cs_ratio *= 2) { - RunOneCriticalSectionTest(p, cs_ratio, /*test_throw*/true); - } - } -} - -int TestMain () { - if(MinThread <= 0) MinThread = 1; - - if(MaxThread > 0) { - RunParallelTests(); - } - - return Harness::Done; -} diff --git a/deal.II/contrib/tbb/tbb30_104oss/src/test/test_eh_algorithms.cpp b/deal.II/contrib/tbb/tbb30_104oss/src/test/test_eh_algorithms.cpp deleted file mode 100644 index 833a281661..0000000000 --- a/deal.II/contrib/tbb/tbb30_104oss/src/test/test_eh_algorithms.cpp +++ /dev/null @@ -1,1281 +0,0 @@ -/* - Copyright 2005-2010 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. -*/ - -#include // for INT_MAX -#include "tbb/task_scheduler_init.h" -#include "tbb/tbb_exception.h" -#include "tbb/task.h" -#include "tbb/atomic.h" -#include "tbb/parallel_for.h" -#include "tbb/parallel_reduce.h" -#include "tbb/parallel_do.h" -#include "tbb/pipeline.h" -#include "tbb/parallel_scan.h" -#include "tbb/blocked_range.h" -#include "harness_assert.h" - -#if __TBB_TASK_GROUP_CONTEXT - -#define FLAT_RANGE 100000 -#define FLAT_GRAIN 100 -#define NESTING_RANGE 100 -#define NESTING_GRAIN 10 -#define NESTED_RANGE (FLAT_RANGE / NESTING_RANGE) -#define NESTED_GRAIN (FLAT_GRAIN / NESTING_GRAIN) - -tbb::atomic g_FedTasksCount; // number of tasks added by parallel_do feeder - -inline intptr_t Existed () { return INT_MAX; } - -#include "harness_eh.h" - -inline void ResetGlobals ( bool throwException = true, bool flog = false ) { - ResetEhGlobals( throwException, flog ); - g_FedTasksCount = 0; -} - -//////////////////////////////////////////////////////////////////////////////// -// Tests for tbb::parallel_for and tbb::parallel_reduce - -typedef size_t count_type; -typedef tbb::blocked_range range_type; - -inline intptr_t NumSubranges ( intptr_t length, intptr_t grain ) { - intptr_t n = 1; - for( ; length > grain; length -= length >> 1 ) - n *= 2; - return n; -} - -template -intptr_t TestNumSubrangesCalculation ( intptr_t length, intptr_t grain, intptr_t nested_length, intptr_t nested_grain ) { - ResetGlobals(); - g_ThrowException = false; - intptr_t nestingCalls = NumSubranges(length, grain), - nestedCalls = NumSubranges(nested_length, nested_grain), - maxExecuted = nestingCalls * (nestedCalls + 1); - tbb::parallel_for( range_type(0, length, grain), Body() ); - ASSERT (g_CurExecuted == maxExecuted, "Wrong estimation of bodies invocation count"); - return maxExecuted; -} - -class NoThrowParForBody { -public: - void operator()( const range_type& r ) const { - volatile long x; - count_type end = r.end(); - for( count_type i=r.begin(); i -class SimpleParReduceBody: NoAssign { - ParForBody m_Body; -public: - void operator()( const range_type& r ) const { m_Body(r); } - SimpleParReduceBody() {} - SimpleParReduceBody( SimpleParReduceBody& left, tbb::split ) : m_Body(left.m_Body) {} - void join( SimpleParReduceBody& /*right*/ ) {} -}; // SimpleParReduceBody - -//! Test parallel_for and parallel_reduce for a given partitioner. -/** The Body need only be suitable for a parallel_for. */ -template -void TestParallelLoopAux( Partitioner& partitioner ) { - for( int i=0; i<2; ++i ) { - ResetGlobals(); - TRY(); - if( i==0 ) - tbb::parallel_for( range_type(0, FLAT_RANGE, FLAT_GRAIN), ParForBody(), partitioner ); - else { - SimpleParReduceBody rb; - tbb::parallel_reduce( range_type(0, FLAT_RANGE, FLAT_GRAIN), rb, partitioner ); - } - CATCH_AND_ASSERT(); - ASSERT (exceptionCaught, "No exception thrown from the nesting parallel_for"); - ASSERT (g_CurExecuted <= g_ExecutedAtCatch + g_NumThreads, "Too many tasks survived exception"); - ASSERT (g_Exceptions == 1, "No try_blocks in any body expected in this test"); - if ( !g_SolitaryException ) - ASSERT (g_CurExecuted <= g_ExecutedAtCatch + g_NumThreads, "Too many tasks survived exception"); - } -} - -//! Test with parallel_for and parallel_reduce, over all three kinds of partitioners. -/** The Body only needs to be suitable for tbb::parallel_for. */ -template -void TestParallelLoop() { - // The simple and auto partitioners should be const, but not the affinity partitioner. - const tbb::simple_partitioner p0; - TestParallelLoopAux( p0 ); - const tbb::auto_partitioner p1; - TestParallelLoopAux( p1 ); -} - -class SimpleParForBody: NoAssign { -public: - void operator()( const range_type& r ) const { - Harness::ConcurrencyTracker ct; - volatile long x; - for( count_type i = r.begin(); i != r.end(); ++i ) - x = 0; - ++g_CurExecuted; - WaitUntilConcurrencyPeaks(); - ThrowTestException(1); - } -}; - -void Test1() { - TestParallelLoop(); -} // void Test1 () - -class NestingParForBody: NoAssign { -public: - void operator()( const range_type& ) const { - Harness::ConcurrencyTracker ct; - ++g_CurExecuted; - tbb::parallel_for( tbb::blocked_range(0, NESTED_RANGE, NESTED_GRAIN), SimpleParForBody() ); - } -}; - -//! Uses parallel_for body containing a nested parallel_for with the default context not wrapped by a try-block. -/** Nested algorithms are spawned inside the new bound context by default. Since - exceptions thrown from the nested parallel_for are not handled by the caller - (nesting parallel_for body) in this test, they will cancel all the sibling nested - algorithms. **/ -void Test2 () { - TestParallelLoop(); -} // void Test2 () - -class NestingParForBodyWithIsolatedCtx { -public: - void operator()( const range_type& ) const { - tbb::task_group_context ctx(tbb::task_group_context::isolated); - ++g_CurExecuted; - tbb::parallel_for( tbb::blocked_range(0, NESTED_RANGE, NESTED_GRAIN), SimpleParForBody(), tbb::simple_partitioner(), ctx ); - } -}; - -//! Uses parallel_for body invoking a nested parallel_for with an isolated context without a try-block. -/** Even though exceptions thrown from the nested parallel_for are not handled - by the caller in this test, they will not affect sibling nested algorithms - already running because of the isolated contexts. However because the first - exception cancels the root parallel_for only the first g_NumThreads subranges - will be processed (which launch nested parallel_fors) **/ -void Test3 () { - ResetGlobals(); - typedef NestingParForBodyWithIsolatedCtx body_type; - intptr_t nestedCalls = NumSubranges(NESTED_RANGE, NESTED_GRAIN), - minExecuted = (g_NumThreads - 1) * nestedCalls; - TRY(); - tbb::parallel_for( range_type(0, NESTING_RANGE, NESTING_GRAIN), body_type() ); - CATCH_AND_ASSERT(); - ASSERT (exceptionCaught, "No exception thrown from the nesting parallel_for"); - if ( g_SolitaryException ) { - ASSERT (g_CurExecuted > minExecuted, "Too few tasks survived exception"); - ASSERT (g_CurExecuted <= minExecuted + (g_ExecutedAtCatch + g_NumThreads), "Too many tasks survived exception"); - } - ASSERT (g_Exceptions == 1, "No try_blocks in any body expected in this test"); - if ( !g_SolitaryException ) - ASSERT (g_CurExecuted <= g_ExecutedAtCatch + g_NumThreads, "Too many tasks survived exception"); -} // void Test3 () - -class NestingParForExceptionSafeBody { -public: - void operator()( const range_type& ) const { - tbb::task_group_context ctx(tbb::task_group_context::isolated); - TRY(); - tbb::parallel_for( tbb::blocked_range(0, NESTED_RANGE, NESTED_GRAIN), SimpleParForBody(), tbb::simple_partitioner(), ctx ); - CATCH(); - } -}; - -//! Uses parallel_for body invoking a nested parallel_for (with default bound context) inside a try-block. -/** Since exception(s) thrown from the nested parallel_for are handled by the caller - in this test, they do not affect neither other tasks of the the root parallel_for - nor sibling nested algorithms. **/ -void Test4 () { - ResetGlobals( true, true ); - intptr_t nestedCalls = NumSubranges(NESTED_RANGE, NESTED_GRAIN), - nestingCalls = NumSubranges(NESTING_RANGE, NESTING_GRAIN), - maxExecuted = nestingCalls * nestedCalls; - TRY(); - tbb::parallel_for( range_type(0, NESTING_RANGE, NESTING_GRAIN), NestingParForExceptionSafeBody() ); - CATCH(); - ASSERT (!exceptionCaught, "All exceptions must have been handled in the parallel_for body"); - intptr_t minExecuted = 0; - if ( g_SolitaryException ) { - minExecuted = maxExecuted - nestedCalls; - ASSERT (g_Exceptions == 1, "No exception registered"); - ASSERT (g_CurExecuted >= minExecuted, "Too few tasks executed"); - ASSERT (g_CurExecuted <= minExecuted + g_NumThreads, "Too many tasks survived exception"); - } - else { - minExecuted = g_Exceptions; - ASSERT (g_Exceptions > 1 && g_Exceptions <= nestingCalls, "Unexpected actual number of exceptions"); - ASSERT (g_CurExecuted >= minExecuted, "Too many executed tasks reported"); - ASSERT (g_CurExecuted <= g_ExecutedAtCatch + g_NumThreads, "Too many tasks survived multiple exceptions"); - ASSERT (g_CurExecuted <= nestingCalls * (1 + g_NumThreads), "Too many tasks survived exception"); - } -} // void Test4 () - -#endif /* TBB_USE_EXCEPTIONS */ - -class ParForBodyToCancel { -public: - void operator()( const range_type& ) const { - ++g_CurExecuted; - CancellatorTask::WaitUntilReady(); - } -}; - -template -class ParForLauncherTask : public tbb::task { - tbb::task_group_context &my_ctx; - - tbb::task* execute () { - tbb::parallel_for( range_type(0, FLAT_RANGE, FLAT_GRAIN), B(), tbb::simple_partitioner(), my_ctx ); - return NULL; - } -public: - ParForLauncherTask ( tbb::task_group_context& ctx ) : my_ctx(ctx) {} -}; - -//! Test for cancelling an algorithm from outside (from a task running in parallel with the algorithm). -void TestCancelation1 () { - ResetGlobals( false ); - RunCancellationTest, CancellatorTask>( NumSubranges(FLAT_RANGE, FLAT_GRAIN) / 4 ); - ASSERT (g_CurExecuted < g_ExecutedAtCatch + g_NumThreads, "Too many tasks were executed after cancellation"); -} - -class CancellatorTask2 : public tbb::task { - tbb::task_group_context &m_GroupToCancel; - - tbb::task* execute () { - Harness::ConcurrencyTracker ct; - WaitUntilConcurrencyPeaks(); - m_GroupToCancel.cancel_group_execution(); - g_ExecutedAtCatch = g_CurExecuted; - return NULL; - } -public: - CancellatorTask2 ( tbb::task_group_context& ctx, intptr_t ) : m_GroupToCancel(ctx) {} -}; - -class ParForBodyToCancel2 { -public: - void operator()( const range_type& ) const { - ++g_CurExecuted; - Harness::ConcurrencyTracker ct; - // The test will hang (and be timed out by the test system) if is_cancelled() is broken - while( !tbb::task::self().is_cancelled() ) - __TBB_Yield(); - } -}; - -//! Test for cancelling an algorithm from outside (from a task running in parallel with the algorithm). -/** This version also tests task::is_cancelled() method. **/ -void TestCancelation2 () { - ResetGlobals(); - RunCancellationTest, CancellatorTask2>(); - ASSERT (g_ExecutedAtCatch < g_NumThreads, "Somehow worker tasks started their execution before the cancellator task"); - ASSERT (g_CurExecuted <= g_ExecutedAtCatch + g_NumThreads, "Some tasks were executed after cancellation"); -} - -//////////////////////////////////////////////////////////////////////////////// -// Regression test based on the contribution by the author of the following forum post: -// http://softwarecommunity.intel.com/isn/Community/en-US/forums/thread/30254959.aspx - -#define LOOP_COUNT 16 -#define MAX_NESTING 3 -#define REDUCE_RANGE 1024 -#define REDUCE_GRAIN 256 - -class Worker { -public: - void DoWork (int & result, int nest); -}; - -class RecursiveParReduceBodyWithSharedWorker { - Worker * m_SharedWorker; - int m_NestingLevel; - int m_Result; -public: - RecursiveParReduceBodyWithSharedWorker ( RecursiveParReduceBodyWithSharedWorker& src, tbb::split ) - : m_SharedWorker(src.m_SharedWorker) - , m_NestingLevel(src.m_NestingLevel) - , m_Result(0) - {} - RecursiveParReduceBodyWithSharedWorker ( Worker *w, int nesting ) - : m_SharedWorker(w) - , m_NestingLevel(nesting) - , m_Result(0) - {} - - void operator() ( const tbb::blocked_range& r ) { - for (size_t i = r.begin (); i != r.end (); ++i) { - int subtotal = 0; - m_SharedWorker->DoWork (subtotal, m_NestingLevel); - m_Result += subtotal; - } - } - void join (const RecursiveParReduceBodyWithSharedWorker & x) { - m_Result += x.m_Result; - } - int result () { return m_Result; } -}; - -void Worker::DoWork ( int& result, int nest ) { - ++nest; - if ( nest < MAX_NESTING ) { - RecursiveParReduceBodyWithSharedWorker rt (this, nest); - tbb::parallel_reduce (tbb::blocked_range(0, REDUCE_RANGE, REDUCE_GRAIN), rt); - result = rt.result (); - } - else - ++result; -} - -//! Regression test for hanging that occurred with the first version of cancellation propagation -void TestCancelation3 () { - Worker w; - int result = 0; - w.DoWork (result, 0); - ASSERT ( result == 1048576, "Wrong calculation result"); -} - -void RunParForAndReduceTests () { - REMARK( "parallel for and reduce tests\n" ); - tbb::task_scheduler_init init (g_NumThreads); - g_Master = Harness::CurrentTid(); - -#if TBB_USE_EXCEPTIONS && !__TBB_THROW_ACROSS_MODULE_BOUNDARY_BROKEN - Test0(); - Test1(); - Test2(); - Test3(); - Test4(); -#endif /* TBB_USE_EXCEPTIONS && !__TBB_THROW_ACROSS_MODULE_BOUNDARY_BROKEN */ - TestCancelation1(); - TestCancelation2(); - TestCancelation3(); -} - -//////////////////////////////////////////////////////////////////////////////// -// Tests for tbb::parallel_do - -#define ITER_RANGE 1000 -#define ITEMS_TO_FEED 50 -#define NESTED_ITER_RANGE 100 -#define NESTING_ITER_RANGE 50 - -#define PREPARE_RANGE(Iterator, rangeSize) \ - size_t test_vector[rangeSize + 1]; \ - for (int i =0; i < rangeSize; i++) \ - test_vector[i] = i; \ - Iterator begin(&test_vector[0]); \ - Iterator end(&test_vector[rangeSize]) - -void Feed ( tbb::parallel_do_feeder &feeder, size_t val ) { - if (g_FedTasksCount < ITEMS_TO_FEED) { - ++g_FedTasksCount; - feeder.add(val); - } -} - -#include "harness_iterator.h" - -#if TBB_USE_EXCEPTIONS - -// Simple functor object with exception -class SimpleParDoBody { -public: - void operator() ( size_t &value ) const { - ++g_CurExecuted; - Harness::ConcurrencyTracker ct; - value += 1000; - WaitUntilConcurrencyPeaks(); - ThrowTestException(1); - } -}; - -// Simple functor object with exception and feeder -class SimpleParDoBodyWithFeeder : SimpleParDoBody { -public: - void operator() ( size_t &value, tbb::parallel_do_feeder &feeder ) const { - Feed(feeder, 0); - SimpleParDoBody::operator()(value); - } -}; - -// Tests exceptions without nesting -template -void Test1_parallel_do () { - ResetGlobals(); - PREPARE_RANGE(Iterator, ITER_RANGE); - TRY(); - tbb::parallel_do(begin, end, simple_body() ); - CATCH_AND_ASSERT(); - ASSERT (g_CurExecuted <= g_ExecutedAtCatch + g_NumThreads, "Too many tasks survived exception"); - ASSERT (g_Exceptions == 1, "No try_blocks in any body expected in this test"); - if ( !g_SolitaryException ) - ASSERT (g_CurExecuted <= g_ExecutedAtCatch + g_NumThreads, "Too many tasks survived exception"); - -} // void Test1_parallel_do () - -template -class NestingParDoBody { -public: - void operator()( size_t& /*value*/ ) const { - ++g_CurExecuted; - PREPARE_RANGE(Iterator, NESTED_ITER_RANGE); - tbb::parallel_do(begin, end, SimpleParDoBody()); - } -}; - -template -class NestingParDoBodyWithFeeder : NestingParDoBody { -public: - void operator()( size_t& value, tbb::parallel_do_feeder& feeder ) const { - Feed(feeder, 0); - NestingParDoBody::operator()(value); - } -}; - -//! Uses parallel_do body containing a nested parallel_do with the default context not wrapped by a try-block. -/** Nested algorithms are spawned inside the new bound context by default. Since - exceptions thrown from the nested parallel_do are not handled by the caller - (nesting parallel_do body) in this test, they will cancel all the sibling nested - algorithms. **/ -template -void Test2_parallel_do () { - ResetGlobals(); - PREPARE_RANGE(Iterator, ITER_RANGE); - TRY(); - tbb::parallel_do(begin, end, nesting_body() ); - CATCH_AND_ASSERT(); - ASSERT (exceptionCaught, "No exception thrown from the nesting parallel_for"); - //if ( g_SolitaryException ) - ASSERT (g_CurExecuted <= g_ExecutedAtCatch + g_NumThreads, "Too many tasks survived exception"); - ASSERT (g_Exceptions == 1, "No try_blocks in any body expected in this test"); - if ( !g_SolitaryException ) - ASSERT (g_CurExecuted <= g_ExecutedAtCatch + g_NumThreads, "Too many tasks survived exception"); -} // void Test2_parallel_do () - -template -class NestingParDoBodyWithIsolatedCtx { -public: - void operator()( size_t& /*value*/ ) const { - tbb::task_group_context ctx(tbb::task_group_context::isolated); - ++g_CurExecuted; - PREPARE_RANGE(Iterator, NESTED_ITER_RANGE); - tbb::parallel_do(begin, end, SimpleParDoBody(), ctx); - } -}; - -template -class NestingParDoBodyWithIsolatedCtxWithFeeder : NestingParDoBodyWithIsolatedCtx { -public: - void operator()( size_t& value, tbb::parallel_do_feeder &feeder ) const { - Feed(feeder, 0); - NestingParDoBodyWithIsolatedCtx::operator()(value); - } -}; - -//! Uses parallel_do body invoking a nested parallel_do with an isolated context without a try-block. -/** Even though exceptions thrown from the nested parallel_do are not handled - by the caller in this test, they will not affect sibling nested algorithms - already running because of the isolated contexts. However because the first - exception cancels the root parallel_do only the first g_NumThreads subranges - will be processed (which launch nested parallel_dos) **/ -template -void Test3_parallel_do () { - ResetGlobals(); - PREPARE_RANGE(Iterator, NESTING_ITER_RANGE); - intptr_t nestedCalls = NESTED_ITER_RANGE, - minExecuted = (g_NumThreads - 1) * nestedCalls; - TRY(); - tbb::parallel_do(begin, end, nesting_body()); - CATCH_AND_ASSERT(); - ASSERT (exceptionCaught, "No exception thrown from the nesting parallel_for"); - if ( g_SolitaryException ) { - ASSERT (g_CurExecuted > minExecuted, "Too few tasks survived exception"); - ASSERT (g_CurExecuted <= minExecuted + (g_ExecutedAtCatch + g_NumThreads), "Too many tasks survived exception"); - } - ASSERT (g_Exceptions == 1, "No try_blocks in any body expected in this test"); - if ( !g_SolitaryException ) - ASSERT (g_CurExecuted <= g_ExecutedAtCatch + g_NumThreads, "Too many tasks survived exception"); -} // void Test3_parallel_do () - -template -class NestingParDoWithEhBody { -public: - void operator()( size_t& /*value*/ ) const { - tbb::task_group_context ctx(tbb::task_group_context::isolated); - PREPARE_RANGE(Iterator, NESTED_ITER_RANGE); - TRY(); - tbb::parallel_do(begin, end, SimpleParDoBody(), ctx); - CATCH(); - } -}; - -template -class NestingParDoWithEhBodyWithFeeder : NoAssign, NestingParDoWithEhBody { -public: - void operator()( size_t &value, tbb::parallel_do_feeder &feeder ) const { - Feed(feeder, 0); - NestingParDoWithEhBody::operator()(value); - } -}; - -//! Uses parallel_for body invoking a nested parallel_for (with default bound context) inside a try-block. -/** Since exception(s) thrown from the nested parallel_for are handled by the caller - in this test, they do not affect neither other tasks of the the root parallel_for - nor sibling nested algorithms. **/ -template -void Test4_parallel_do () { - ResetGlobals( true, true ); - PREPARE_RANGE(Iterator, NESTING_ITER_RANGE); - TRY(); - tbb::parallel_do(begin, end, nesting_body_with_eh()); - CATCH(); - ASSERT (!exceptionCaught, "All exceptions must have been handled in the parallel_do body"); - intptr_t nestedCalls = NESTED_ITER_RANGE, - nestingCalls = NESTING_ITER_RANGE + g_FedTasksCount, - maxExecuted = nestingCalls * nestedCalls, - minExecuted = 0; - if ( g_SolitaryException ) { - minExecuted = maxExecuted - nestedCalls; - ASSERT (g_Exceptions == 1, "No exception registered"); - ASSERT (g_CurExecuted >= minExecuted, "Too few tasks executed"); - ASSERT (g_CurExecuted <= minExecuted + g_NumThreads, "Too many tasks survived exception"); - } - else { - minExecuted = g_Exceptions; - ASSERT (g_Exceptions > 1 && g_Exceptions <= nestingCalls, "Unexpected actual number of exceptions"); - ASSERT (g_CurExecuted >= minExecuted, "Too many executed tasks reported"); - ASSERT (g_CurExecuted < g_ExecutedAtCatch + g_NumThreads + nestingCalls, "Too many tasks survived multiple exceptions"); - ASSERT (g_CurExecuted <= nestingCalls * (1 + g_NumThreads), "Too many tasks survived exception"); - } -} // void Test4_parallel_do () - -// This body throws an exception only if the task was added by feeder -class ParDoBodyWithThrowingFeederTasks { -public: - //! This form of the function call operator can be used when the body needs to add more work during the processing - void operator() ( size_t &value, tbb::parallel_do_feeder &feeder ) const { - ++g_CurExecuted; - Feed(feeder, 1); - if (value == 1) - ThrowTestException(1); - } -}; // class ParDoBodyWithThrowingFeederTasks - -// Test exception in task, which was added by feeder. -template -void Test5_parallel_do () { - ResetGlobals(); - PREPARE_RANGE(Iterator, ITER_RANGE); - TRY(); - tbb::parallel_do(begin, end, ParDoBodyWithThrowingFeederTasks()); - CATCH(); - if (g_SolitaryException) - ASSERT (exceptionCaught, "At least one exception should occur"); -} // void Test5_parallel_do () - -#endif /* TBB_USE_EXCEPTIONS */ - -class ParDoBodyToCancel { -public: - void operator()( size_t& /*value*/ ) const { - ++g_CurExecuted; - CancellatorTask::WaitUntilReady(); - } -}; - -class ParDoBodyToCancelWithFeeder : ParDoBodyToCancel { -public: - void operator()( size_t& value, tbb::parallel_do_feeder &feeder ) const { - Feed(feeder, 0); - ParDoBodyToCancel::operator()(value); - } -}; - -template -class ParDoWorkerTask : public tbb::task { - tbb::task_group_context &my_ctx; - - tbb::task* execute () { - PREPARE_RANGE(Iterator, NESTED_ITER_RANGE); - tbb::parallel_do( begin, end, B(), my_ctx ); - return NULL; - } -public: - ParDoWorkerTask ( tbb::task_group_context& ctx ) : my_ctx(ctx) {} -}; - -//! Test for cancelling an algorithm from outside (from a task running in parallel with the algorithm). -template -void TestCancelation1_parallel_do () { - ResetGlobals( false ); - intptr_t threshold = 10; - tbb::task_group_context ctx; - ctx.reset(); - tbb::empty_task &r = *new( tbb::task::allocate_root() ) tbb::empty_task; - r.set_ref_count(3); - r.spawn( *new( r.allocate_child() ) CancellatorTask(ctx, threshold) ); - __TBB_Yield(); - r.spawn( *new( r.allocate_child() ) ParDoWorkerTask(ctx) ); - TRY(); - r.wait_for_all(); - CATCH_AND_FAIL(); - ASSERT (g_CurExecuted < g_ExecutedAtCatch + g_NumThreads, "Too many tasks were executed after cancellation"); - r.destroy(r); -} - -class ParDoBodyToCancel2 { -public: - void operator()( size_t& /*value*/ ) const { - ++g_CurExecuted; - Harness::ConcurrencyTracker ct; - // The test will hang (and be timed out by the test system) if is_cancelled() is broken - while( !tbb::task::self().is_cancelled() ) - __TBB_Yield(); - } -}; - -class ParDoBodyToCancel2WithFeeder : ParDoBodyToCancel2 { -public: - void operator()( size_t& value, tbb::parallel_do_feeder &feeder ) const { - Feed(feeder, 0); - ParDoBodyToCancel2::operator()(value); - } -}; - -//! Test for cancelling an algorithm from outside (from a task running in parallel with the algorithm). -/** This version also tests task::is_cancelled() method. **/ -template -void TestCancelation2_parallel_do () { - ResetGlobals(); - RunCancellationTest, CancellatorTask2>(); - ASSERT (g_CurExecuted <= g_ExecutedAtCatch + g_NumThreads, "Some tasks were executed after cancellation"); -} - -#define RunWithSimpleBody(func, body) \ - func, body>(); \ - func, body##WithFeeder>(); \ - func, body>(); \ - func, body##WithFeeder>() - -#define RunWithTemplatedBody(func, body) \ - func, body > >(); \ - func, body##WithFeeder > >(); \ - func, body > >(); \ - func, body##WithFeeder > >() - -void RunParDoTests() { - REMARK( "parallel do tests\n" ); - tbb::task_scheduler_init init (g_NumThreads); - g_Master = Harness::CurrentTid(); -#if TBB_USE_EXCEPTIONS && !__TBB_THROW_ACROSS_MODULE_BOUNDARY_BROKEN - RunWithSimpleBody(Test1_parallel_do, SimpleParDoBody); - RunWithTemplatedBody(Test2_parallel_do, NestingParDoBody); - RunWithTemplatedBody(Test3_parallel_do, NestingParDoBodyWithIsolatedCtx); - RunWithTemplatedBody(Test4_parallel_do, NestingParDoWithEhBody); - Test5_parallel_do >(); - Test5_parallel_do >(); -#endif /* TBB_USE_EXCEPTIONS && !__TBB_THROW_ACROSS_MODULE_BOUNDARY_BROKEN */ - RunWithSimpleBody(TestCancelation1_parallel_do, ParDoBodyToCancel); - RunWithSimpleBody(TestCancelation2_parallel_do, ParDoBodyToCancel2); -} - -//////////////////////////////////////////////////////////////////////////////// -// Tests for tbb::pipeline - -#define NUM_ITEMS 100 - -const size_t c_DataEndTag = size_t(~0); - -int g_NumTokens = 0; - -// Simple input filter class, it assigns 1 to all array members -// It stops when it receives item equal to -1 -class InputFilter: public tbb::filter { - tbb::atomic m_Item; - size_t m_Buffer[NUM_ITEMS + 1]; -public: - InputFilter() : tbb::filter(parallel) { - m_Item = 0; - for (size_t i = 0; i < NUM_ITEMS; ++i ) - m_Buffer[i] = 1; - m_Buffer[NUM_ITEMS] = c_DataEndTag; - } - - void* operator()( void* ) { - size_t item = m_Item.fetch_and_increment(); - if ( item >= NUM_ITEMS ) - return NULL; - m_Buffer[item] = 1; - return &m_Buffer[item]; - } - - size_t* buffer() { return m_Buffer; } -}; // class InputFilter - -// Pipeline filter, without exceptions throwing -class NoThrowFilter : public tbb::filter { - size_t m_Value; -public: - enum operation { - addition, - subtraction, - multiplication - } m_Operation; - - NoThrowFilter(operation _operation, size_t value, bool is_parallel) - : filter(is_parallel? tbb::filter::parallel : tbb::filter::serial_in_order), - m_Value(value), m_Operation(_operation) - {} - void* operator()(void* item) { - size_t &value = *(size_t*)item; - ASSERT(value != c_DataEndTag, "terminator element is being processed"); - switch (m_Operation){ - case addition: - value += m_Value; - break; - case subtraction: - value -= m_Value; - break; - case multiplication: - value *= m_Value; - break; - default: - ASSERT(0, "Wrong operation parameter passed to NoThrowFilter"); - } // switch (m_Operation) - return item; - } -}; - -// Test pipeline without exceptions throwing -void Test0_pipeline () { - ResetGlobals(); - // Run test when serial filter is the first non-input filter - InputFilter inputFilter; - NoThrowFilter filter1(NoThrowFilter::addition, 99, false); - NoThrowFilter filter2(NoThrowFilter::subtraction, 90, true); - NoThrowFilter filter3(NoThrowFilter::multiplication, 5, false); - // Result should be 50 for all items except the last - tbb::pipeline p; - p.add_filter(inputFilter); - p.add_filter(filter1); - p.add_filter(filter2); - p.add_filter(filter3); - p.run(8); - for (size_t i = 0; i < NUM_ITEMS; ++i) - ASSERT(inputFilter.buffer()[i] == 50, "pipeline didn't process items properly"); -} // void Test0_pipeline () - -#if TBB_USE_EXCEPTIONS - -// Simple filter with exception throwing -class SimpleFilter : public tbb::filter { - bool m_canThrow; -public: - SimpleFilter (tbb::filter::mode _mode, bool canThrow ) : filter (_mode), m_canThrow(canThrow) {} - - void* operator()(void* item) { - ++g_CurExecuted; - if ( m_canThrow ) { - if ( !is_serial() ) { - Harness::ConcurrencyTracker ct; - WaitUntilConcurrencyPeaks( min(g_NumTokens, g_NumThreads) ); - } - ThrowTestException(1); - } - return item; - } -}; // class SimpleFilter - -// This enumeration represents filters order in pipeline -struct FilterSet { - tbb::filter::mode mode1, - mode2; - bool throw1, - throw2; - - FilterSet( tbb::filter::mode m1, tbb::filter::mode m2, bool t1, bool t2 ) - : mode1(m1), mode2(m2), throw1(t1), throw2(t2) - {} -}; // struct FilterSet - -FilterSet serial_parallel( tbb::filter::serial, tbb::filter::parallel, false, true ); - -template -class CustomPipeline : protected tbb::pipeline { - InFilter inputFilter; - Filter filter1; - Filter filter2; -public: - CustomPipeline( const FilterSet& filters ) - : filter1(filters.mode1, filters.throw1), filter2(filters.mode2, filters.throw2) - { - add_filter(inputFilter); - add_filter(filter1); - add_filter(filter2); - } - void run () { tbb::pipeline::run(g_NumTokens); } - void run ( tbb::task_group_context& ctx ) { tbb::pipeline::run(g_NumTokens, ctx); } - - using tbb::pipeline::add_filter; -}; - -typedef CustomPipeline SimplePipeline; - -// Tests exceptions without nesting -void Test1_pipeline ( const FilterSet& filters ) { - ResetGlobals(); - SimplePipeline testPipeline(filters); - TRY(); - testPipeline.run(); - if ( g_CurExecuted == 2 * NUM_ITEMS ) { - // In case of all serial filters they might be all executed in the thread(s) - // where exceptions are not allowed by the common test logic. So we just quit. - return; - } - CATCH_AND_ASSERT(); - ASSERT (g_CurExecuted <= g_ExecutedAtCatch + g_NumThreads, "Too many tasks survived exception"); - ASSERT (g_Exceptions == 1, "No try_blocks in any body expected in this test"); - if ( !g_SolitaryException ) - ASSERT (g_CurExecuted <= g_ExecutedAtCatch + g_NumThreads, "Too many tasks survived exception"); - -} // void Test1_pipeline () - -// Filter with nesting -class NestingFilter : public tbb::filter { -public: - NestingFilter (tbb::filter::mode _mode, bool ) : filter (_mode) {} - - void* operator()(void* item) { - ++g_CurExecuted; - SimplePipeline testPipeline(serial_parallel); - testPipeline.run(); - return item; - } -}; // class NestingFilter - -//! Uses pipeline containing a nested pipeline with the default context not wrapped by a try-block. -/** Nested algorithms are spawned inside the new bound context by default. Since - exceptions thrown from the nested pipeline are not handled by the caller - (nesting pipeline body) in this test, they will cancel all the sibling nested - algorithms. **/ -void Test2_pipeline ( const FilterSet& filters ) { - ResetGlobals(); - CustomPipeline testPipeline(filters); - TRY(); - testPipeline.run(); - CATCH_AND_ASSERT(); - ASSERT (exceptionCaught, "No exception thrown from the nesting pipeline"); - ASSERT (g_CurExecuted <= g_ExecutedAtCatch + g_NumThreads, "Too many tasks survived exception"); - ASSERT (g_Exceptions == 1, "No try_blocks in any body expected in this test"); - if ( !g_SolitaryException ) - ASSERT (g_CurExecuted <= g_ExecutedAtCatch + g_NumThreads, "Too many tasks survived exception"); -} // void Test2_pipeline () - -class NestingFilterWithIsolatedCtx : public tbb::filter { -public: - NestingFilterWithIsolatedCtx(tbb::filter::mode m, bool ) : filter(m) {} - - void* operator()(void* item) { - ++g_CurExecuted; - tbb::task_group_context ctx(tbb::task_group_context::isolated); - SimplePipeline testPipeline(serial_parallel); - testPipeline.run(ctx); - return item; - } -}; // class NestingFilterWithIsolatedCtx - -//! Uses pipeline invoking a nested pipeline with an isolated context without a try-block. -/** Even though exceptions thrown from the nested pipeline are not handled - by the caller in this test, they will not affect sibling nested algorithms - already running because of the isolated contexts. However because the first - exception cancels the root parallel_do only the first g_NumThreads subranges - will be processed (which launch nested pipelines) **/ -void Test3_pipeline ( const FilterSet& filters ) { - ResetGlobals(); - intptr_t nestedCalls = 100, - minExecuted = (g_NumThreads - 1) * nestedCalls; - CustomPipeline testPipeline(filters); - TRY(); - testPipeline.run(); - CATCH_AND_ASSERT(); - ASSERT (exceptionCaught, "No exception thrown from the nesting parallel_for"); - if ( g_SolitaryException ) { - ASSERT (g_CurExecuted > minExecuted, "Too few tasks survived exception"); - ASSERT (g_CurExecuted <= minExecuted + (g_ExecutedAtCatch + g_NumThreads), "Too many tasks survived exception"); - } - ASSERT (g_Exceptions == 1, "No try_blocks in any body expected in this test"); - if ( !g_SolitaryException ) - ASSERT (g_CurExecuted <= g_ExecutedAtCatch + g_NumThreads, "Too many tasks survived exception"); -} // void Test3_pipeline () - -class NestingFilterWithEhBody : public tbb::filter { -public: - NestingFilterWithEhBody(tbb::filter::mode m, bool ) : filter(m) {} - - void* operator()(void* item) { - tbb::task_group_context ctx(tbb::task_group_context::isolated); - SimplePipeline testPipeline(serial_parallel); - TRY(); - testPipeline.run(ctx); - CATCH(); - return item; - } -}; // class NestingFilterWithEhBody - -//! Uses pipeline body invoking a nested pipeline (with default bound context) inside a try-block. -/** Since exception(s) thrown from the nested pipeline are handled by the caller - in this test, they do not affect neither other tasks of the the root pipeline - nor sibling nested algorithms. **/ -void Test4_pipeline ( const FilterSet& filters ) { -#if __GNUC__ && !__INTEL_COMPILER - if ( strncmp(__VERSION__, "4.1.0", 5) == 0 ) { - REMARK_ONCE("Known issue: one of exception handling tests is skipped.\n"); - return; - } -#endif - ResetGlobals( true, true ); - intptr_t nestedCalls = NUM_ITEMS + 1, - nestingCalls = 2 * (NUM_ITEMS + 1), - maxExecuted = nestingCalls * nestedCalls; - CustomPipeline testPipeline(filters); - TRY(); - testPipeline.run(); - CATCH_AND_ASSERT(); - ASSERT (!exceptionCaught, "All exceptions must have been handled in the parallel_do body"); - intptr_t minExecuted = 0; - if ( g_SolitaryException ) { - minExecuted = maxExecuted - nestedCalls; - ASSERT (g_Exceptions != 0, "No exception registered"); - ASSERT (g_CurExecuted <= minExecuted + g_NumThreads, "Too many tasks survived exception"); - } - else { - minExecuted = g_Exceptions; - ASSERT (g_Exceptions > 1 && g_Exceptions <= nestingCalls, "Unexpected actual number of exceptions"); - ASSERT (g_CurExecuted >= minExecuted, "Too many executed tasks reported"); - ASSERT (g_CurExecuted <= g_ExecutedAtCatch + g_NumThreads, "Too many tasks survived multiple exceptions"); - } -} // void Test4_pipeline () - -//! Testing filter::finalize method -#define BUFFER_SIZE 32 -#define NUM_BUFFERS 1024 - -tbb::atomic g_AllocatedCount; // Number of currently allocated buffers -tbb::atomic g_TotalCount; // Total number of allocated buffers - -//! Base class for all filters involved in finalize method testing -class FinalizationBaseFilter : public tbb::filter { -public: - FinalizationBaseFilter ( tbb::filter::mode m ) : filter(m) {} - - // Deletes buffers if exception occured - virtual void finalize( void* item ) { - size_t* m_Item = (size_t*)item; - delete[] m_Item; - --g_AllocatedCount; - } -}; - -//! Input filter to test finalize method -class InputFilterWithFinalization: public FinalizationBaseFilter { -public: - InputFilterWithFinalization() : FinalizationBaseFilter(tbb::filter::serial) { - g_TotalCount = 0; - } - void* operator()( void* ){ - if (g_TotalCount == NUM_BUFFERS) - return NULL; - size_t* item = new size_t[BUFFER_SIZE]; - for (int i = 0; i < BUFFER_SIZE; i++) - item[i] = 1; - ++g_TotalCount; - ++g_AllocatedCount; - return item; - } -}; - -// The filter multiplies each buffer item by 10. -class ProcessingFilterWithFinalization : public FinalizationBaseFilter { -public: - ProcessingFilterWithFinalization (tbb::filter::mode _mode, bool) : FinalizationBaseFilter (_mode) {} - - void* operator()( void* item) { - if (g_TotalCount > NUM_BUFFERS / 2) - ThrowTestException(1); - size_t* m_Item = (size_t*)item; - for (int i = 0; i < BUFFER_SIZE; i++) - m_Item[i] *= 10; - return item; - } -}; - -// Output filter deletes previously allocated buffer -class OutputFilterWithFinalization : public FinalizationBaseFilter { -public: - OutputFilterWithFinalization (tbb::filter::mode m) : FinalizationBaseFilter (m) {} - - void* operator()( void* item){ - size_t* m_Item = (size_t*)item; - delete[] m_Item; - --g_AllocatedCount; - return NULL; - } -}; - -//! Tests filter::finalize method -void Test5_pipeline ( const FilterSet& filters ) { - ResetGlobals(); - g_AllocatedCount = 0; - CustomPipeline testPipeline(filters); - OutputFilterWithFinalization my_output_filter(tbb::filter::parallel); - - testPipeline.add_filter(my_output_filter); - TRY(); - testPipeline.run(); - CATCH(); - ASSERT (g_AllocatedCount == 0, "Memory leak: Some my_object weren't destroyed"); -} // void Test5_pipeline () - -//! Tests pipeline function passed with different combination of filters -template -void TestWithDifferentFilters() { - const int NumFilterTypes = 3; - const tbb::filter::mode modes[NumFilterTypes] = { - tbb::filter::parallel, - tbb::filter::serial, - tbb::filter::serial_out_of_order - }; - for ( int i = 0; i < NumFilterTypes; ++i ) { - for ( int j = 0; j < NumFilterTypes; ++j ) { - for ( int k = 0; k < 2; ++k ) - testFunc( FilterSet(modes[i], modes[j], k == 0, k != 0) ); - } - } -} - -#endif /* TBB_USE_EXCEPTIONS */ - -class FilterToCancel : public tbb::filter { -public: - FilterToCancel(bool is_parallel) - : filter( is_parallel ? tbb::filter::parallel : tbb::filter::serial_in_order ) - {} - void* operator()(void* item) { - ++g_CurExecuted; - CancellatorTask::WaitUntilReady(); - return item; - } -}; // class FilterToCancel - -template -class PipelineLauncherTask : public tbb::task { - tbb::task_group_context &my_ctx; -public: - PipelineLauncherTask ( tbb::task_group_context& ctx ) : my_ctx(ctx) {} - - tbb::task* execute () { - // Run test when serial filter is the first non-input filter - InputFilter inputFilter; - Filter_to_cancel filterToCancel(true); - tbb::pipeline p; - p.add_filter(inputFilter); - p.add_filter(filterToCancel); - p.run(g_NumTokens, my_ctx); - return NULL; - } -}; - -//! Test for cancelling an algorithm from outside (from a task running in parallel with the algorithm). -void TestCancelation1_pipeline () { - ResetGlobals(); - g_ThrowException = false; - intptr_t threshold = 10; - tbb::task_group_context ctx; - ctx.reset(); - tbb::empty_task &r = *new( tbb::task::allocate_root() ) tbb::empty_task; - r.set_ref_count(3); - r.spawn( *new( r.allocate_child() ) CancellatorTask(ctx, threshold) ); - __TBB_Yield(); - r.spawn( *new( r.allocate_child() ) PipelineLauncherTask(ctx) ); - TRY(); - r.wait_for_all(); - CATCH_AND_FAIL(); - r.destroy(r); - ASSERT (g_CurExecuted < g_ExecutedAtCatch + g_NumThreads, "Too many tasks were executed after cancellation"); -} - -class FilterToCancel2 : public tbb::filter { -public: - FilterToCancel2(bool is_parallel) - : filter ( is_parallel ? tbb::filter::parallel : tbb::filter::serial_in_order) - {} - - void* operator()(void* item) { - ++g_CurExecuted; - Harness::ConcurrencyTracker ct; - // The test will hang (and be timed out by the tesst system) if is_cancelled() is broken - while( !tbb::task::self().is_cancelled() ) - __TBB_Yield(); - return item; - } -}; - -//! Test for cancelling an algorithm from outside (from a task running in parallel with the algorithm). -/** This version also tests task::is_cancelled() method. **/ -void TestCancelation2_pipeline () { - ResetGlobals(); - RunCancellationTest, CancellatorTask2>(); - ASSERT (g_CurExecuted <= g_ExecutedAtCatch, "Some tasks were executed after cancellation"); -} - -void RunPipelineTests() { - REMARK( "pipeline tests\n" ); - tbb::task_scheduler_init init (g_NumThreads); - g_Master = Harness::CurrentTid(); - g_NumTokens = 2 * g_NumThreads; - - Test0_pipeline(); -#if TBB_USE_EXCEPTIONS && !__TBB_THROW_ACROSS_MODULE_BOUNDARY_BROKEN - TestWithDifferentFilters(); - TestWithDifferentFilters(); - TestWithDifferentFilters(); - TestWithDifferentFilters(); - TestWithDifferentFilters(); -#endif /* TBB_USE_EXCEPTIONS && !__TBB_THROW_ACROSS_MODULE_BOUNDARY_BROKEN */ - TestCancelation1_pipeline(); - TestCancelation2_pipeline(); -} - -#endif /* __TBB_TASK_GROUP_CONTEXT */ - -#if TBB_USE_EXCEPTIONS - -class MyCapturedException : public tbb::captured_exception { -public: - static int m_refCount; - - MyCapturedException () : tbb::captured_exception("MyCapturedException", "test") { ++m_refCount; } - ~MyCapturedException () throw() { --m_refCount; } - - MyCapturedException* move () throw() { - MyCapturedException* movee = (MyCapturedException*)malloc(sizeof(MyCapturedException)); - return ::new (movee) MyCapturedException; - } - void destroy () throw() { - this->~MyCapturedException(); - free(this); - } - void operator delete ( void* p ) { free(p); } -}; - -int MyCapturedException::m_refCount = 0; - -void DeleteTbbException ( volatile tbb::tbb_exception* pe ) { - delete pe; -} - -void TestTbbExceptionAPI () { - const char *name = "Test captured exception", - *reason = "Unit testing"; - tbb::captured_exception e(name, reason); - ASSERT (strcmp(e.name(), name) == 0, "Setting captured exception name failed"); - ASSERT (strcmp(e.what(), reason) == 0, "Setting captured exception reason failed"); - tbb::captured_exception c(e); - ASSERT (strcmp(c.name(), e.name()) == 0, "Copying captured exception name failed"); - ASSERT (strcmp(c.what(), e.what()) == 0, "Copying captured exception reason failed"); - tbb::captured_exception *m = e.move(); - ASSERT (strcmp(m->name(), name) == 0, "Moving captured exception name failed"); - ASSERT (strcmp(m->what(), reason) == 0, "Moving captured exception reason failed"); - ASSERT (!e.name() && !e.what(), "Moving semantics broken"); - m->destroy(); - - MyCapturedException mce; - MyCapturedException *mmce = mce.move(); - ASSERT( MyCapturedException::m_refCount == 2, NULL ); - DeleteTbbException(mmce); - ASSERT( MyCapturedException::m_refCount == 1, NULL ); -} - -#endif /* TBB_USE_EXCEPTIONS */ - -/** If min and max thread numbers specified on the command line are different, - the test is run only for 2 sizes of the thread pool (MinThread and MaxThread) - to be able to test the high and low contention modes while keeping the test reasonably fast **/ -int TestMain () { - REMARK ("Using %s\n", TBB_USE_CAPTURED_EXCEPTION ? "tbb:captured_exception" : "exact exception propagation"); - MinThread = min(tbb::task_scheduler_init::default_num_threads(), max(2, MinThread)); - MaxThread = max(MinThread, min(tbb::task_scheduler_init::default_num_threads(), MaxThread)); - ASSERT (FLAT_RANGE >= FLAT_GRAIN * MaxThread, "Fix defines"); -#if __TBB_TASK_GROUP_CONTEXT - int step = max((MaxThread - MinThread + 1)/2, 1); - for ( g_NumThreads = MinThread; g_NumThreads <= MaxThread; g_NumThreads += step ) { - REMARK ("Number of threads %d\n", g_NumThreads); - // Execute in all the possible modes - for ( size_t j = 0; j < 4; ++j ) { - g_ExceptionInMaster = (j & 1) == 1; - g_SolitaryException = (j & 2) == 1; - RunParForAndReduceTests(); - RunParDoTests(); - RunPipelineTests(); - } - } -#if TBB_USE_EXCEPTIONS - TestTbbExceptionAPI(); -#endif -#if __TBB_THROW_ACROSS_MODULE_BOUNDARY_BROKEN - REPORT("Known issue: exception handling tests are skipped.\n"); -#endif - return Harness::Done; -#else /* !__TBB_TASK_GROUP_CONTEXT */ - return Harness::Skipped; -#endif /* !__TBB_TASK_GROUP_CONTEXT */ -} diff --git a/deal.II/contrib/tbb/tbb30_104oss/src/test/test_eh_tasks.cpp b/deal.II/contrib/tbb/tbb30_104oss/src/test/test_eh_tasks.cpp deleted file mode 100644 index 44ed1f3056..0000000000 --- a/deal.II/contrib/tbb/tbb30_104oss/src/test/test_eh_tasks.cpp +++ /dev/null @@ -1,763 +0,0 @@ -/* - Copyright 2005-2010 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. -*/ - -#define __TBB_COUNT_TASK_NODES 1 -#include "harness_inject_scheduler.h" - -#if __TBB_TASK_GROUP_CONTEXT - -#define __TBB_ATOMICS_CODEGEN_BROKEN __SUNPRO_CC - -#include "tbb/task_scheduler_init.h" -#include "tbb/spin_mutex.h" -#include "tbb/tick_count.h" - -#if !TBB_USE_EXCEPTIONS && _MSC_VER - // Suppress "C++ exception handler used, but unwind semantics are not enabled" warning in STL headers - #pragma warning (push) - #pragma warning (disable: 4530) -#endif - -#include - -#if !TBB_USE_EXCEPTIONS && _MSC_VER - #pragma warning (pop) -#endif - -#define NUM_CHILD_TASKS 256 -#define NUM_ROOT_TASKS 32 -#define NUM_ROOTS_IN_GROUP 8 - -//! Statistics about number of tasks in different states -class TaskStats { - typedef tbb::spin_mutex::scoped_lock lock_t; - //! Number of tasks allocated that was ever allocated - volatile intptr_t m_Existed; - //! Number of tasks executed to the moment - volatile intptr_t m_Executed; - //! Number of tasks allocated but not yet destroyed to the moment - volatile intptr_t m_Existing; - - mutable tbb::spin_mutex m_Mutex; -public: - //! Assumes that assignment is noncontended for the left-hand operand - const TaskStats& operator= ( const TaskStats& rhs ) { - if ( this != &rhs ) { - lock_t lock(rhs.m_Mutex); - m_Existed = rhs.m_Existed; - m_Executed = rhs.m_Executed; - m_Existing = rhs.m_Existing; - } - return *this; - } - intptr_t Existed() const { return m_Existed; } - intptr_t Executed() const { return m_Executed; } - intptr_t Existing() const { return m_Existing; } - void IncExisted() { lock_t lock(m_Mutex); ++m_Existed; ++m_Existing; } - void IncExecuted() { lock_t lock(m_Mutex); ++m_Executed; } - void DecExisting() { lock_t lock(m_Mutex); --m_Existing; } - //! Assumed to be used in uncontended manner only - void Reset() { m_Executed = m_Existing = m_Existed = 0; } -}; - -TaskStats g_CurStat; - -inline intptr_t Existed () { return g_CurStat.Existed(); } - -#include "harness_eh.h" - -bool g_BoostExecutedCount = true; -volatile bool g_TaskWasCancelled = false; - -inline void ResetGlobals () { - ResetEhGlobals(); - g_BoostExecutedCount = true; - g_TaskWasCancelled = false; - g_CurStat.Reset(); -} - -#define ASSERT_TEST_POSTCOND() \ - ASSERT (g_CurStat.Existed() >= g_CurStat.Executed(), "Total number of tasks is less than executed"); \ - ASSERT (!g_CurStat.Existing(), "Not all task objects have been destroyed"); \ - ASSERT (!tbb::task::self().is_cancelled(), "Scheduler's default context has not been cleaned up properly"); - -inline void WaitForException () { - int n = 0; - while ( ++n < c_Timeout && !__TBB_load_with_acquire(g_ExceptionCaught) ) - __TBB_Yield(); - ASSERT_WARNING( n < c_Timeout, "WaitForException failed" ); -} - -class TaskBase : public tbb::task { - tbb::task* execute () { - tbb::task* t = NULL; - __TBB_TRY { - t = do_execute(); - } __TBB_CATCH( ... ) { - g_CurStat.IncExecuted(); - __TBB_RETHROW(); - } - g_CurStat.IncExecuted(); - return t; - } -protected: - TaskBase ( bool throwException = true ) : m_Throw(throwException) { g_CurStat.IncExisted(); } - ~TaskBase () { g_CurStat.DecExisting(); } - - virtual tbb::task* do_execute () = 0; - - bool m_Throw; -}; // class TaskBase - -class LeafTask : public TaskBase { - tbb::task* do_execute () { - Harness::ConcurrencyTracker ct; - WaitUntilConcurrencyPeaks(); - if ( g_BoostExecutedCount ) - ++g_CurExecuted; - if ( m_Throw ) - ThrowTestException(NUM_CHILD_TASKS/2); - if ( !g_ThrowException ) - __TBB_Yield(); - return NULL; - } -public: - LeafTask ( bool throw_exception = true ) : TaskBase(throw_exception) {} -}; - -class SimpleRootTask : public TaskBase { - tbb::task* do_execute () { - set_ref_count(NUM_CHILD_TASKS + 1); - for ( size_t i = 0; i < NUM_CHILD_TASKS; ++i ) - spawn( *new( allocate_child() ) LeafTask(m_Throw) ); - wait_for_all(); - return NULL; - } -public: - SimpleRootTask ( bool throw_exception = true ) : TaskBase(throw_exception) {} -}; - -#if TBB_USE_EXCEPTIONS - -class SimpleThrowingTask : public tbb::task { -public: - tbb::task* execute () { throw 0; } - ~SimpleThrowingTask() {} -}; - -//! Checks if innermost running task information is updated correctly during cancellation processing -void Test0 () { - tbb::task_scheduler_init init (1); - tbb::empty_task &r = *new( tbb::task::allocate_root() ) tbb::empty_task; - tbb::task_list tl; - tl.push_back( *new( r.allocate_child() ) SimpleThrowingTask ); - tl.push_back( *new( r.allocate_child() ) SimpleThrowingTask ); - r.set_ref_count( 3 ); - try { - r.spawn_and_wait_for_all( tl ); - } - catch (...) {} - r.destroy( r ); -} - -//! Default exception behavior test. -/** Allocates a root task that spawns a bunch of children, one or several of which throw - a test exception in a worker or master thread (depending on the global setting). **/ -void Test1 () { - ResetGlobals(); - tbb::empty_task &r = *new( tbb::task::allocate_root() ) tbb::empty_task; - ASSERT (!g_CurStat.Existing() && !g_CurStat.Existed() && !g_CurStat.Executed(), - "something wrong with the task accounting"); - r.set_ref_count(NUM_CHILD_TASKS + 1); - for ( int i = 0; i < NUM_CHILD_TASKS; ++i ) - r.spawn( *new( r.allocate_child() ) LeafTask ); - TRY(); - r.wait_for_all(); - CATCH_AND_ASSERT(); - r.destroy(r); - ASSERT_TEST_POSTCOND(); -} // void Test1 () - -//! Default exception behavior test. -/** Allocates and spawns root task that runs a bunch of children, one of which throws - a test exception in a worker thread. (Similar to Test1, except that the root task - is spawned by the test function, and children are created by the root task instead - of the test function body.) **/ -void Test2 () { - ResetGlobals(); - SimpleRootTask &r = *new( tbb::task::allocate_root() ) SimpleRootTask; - ASSERT (g_CurStat.Existing() == 1 && g_CurStat.Existed() == 1 && !g_CurStat.Executed(), - "something wrong with the task accounting"); - TRY(); - tbb::task::spawn_root_and_wait(r); - CATCH_AND_ASSERT(); - ASSERT (g_ExceptionCaught, "no exception occurred"); - ASSERT_TEST_POSTCOND(); -} // void Test2 () - -//! The same as Test2() except the root task has explicit context. -/** The context is initialized as bound in order to check correctness of its associating - with a root task. **/ -void Test3 () { - ResetGlobals(); - tbb::task_group_context ctx(tbb::task_group_context::bound); - SimpleRootTask &r = *new( tbb::task::allocate_root(ctx) ) SimpleRootTask; - ASSERT (g_CurStat.Existing() == 1 && g_CurStat.Existed() == 1 && !g_CurStat.Executed(), - "something wrong with the task accounting"); - TRY(); - tbb::task::spawn_root_and_wait(r); - CATCH_AND_ASSERT(); - ASSERT (g_ExceptionCaught, "no exception occurred"); - ASSERT_TEST_POSTCOND(); -} // void Test2 () - -class RootLauncherTask : public TaskBase { - tbb::task_group_context::kind_type m_CtxKind; - - tbb::task* do_execute () { - tbb::task_group_context ctx(m_CtxKind); - SimpleRootTask &r = *new( allocate_root(ctx) ) SimpleRootTask; - TRY(); - spawn_root_and_wait(r); - // Give a child of our siblings a chance to throw the test exception - WaitForException(); - CATCH(); - ASSERT (__TBB_EXCEPTION_TYPE_INFO_BROKEN || !g_UnknownException, "unknown exception was caught"); - return NULL; - } -public: - RootLauncherTask ( tbb::task_group_context::kind_type ctx_kind = tbb::task_group_context::isolated ) : m_CtxKind(ctx_kind) {} -}; - -/** Allocates and spawns a bunch of roots, which allocate and spawn new root with - isolated context, which at last spawns a bunch of children each, one of which - throws a test exception in a worker thread. **/ -void Test4 () { - ResetGlobals(); - tbb::task_list tl; - for ( size_t i = 0; i < NUM_ROOT_TASKS; ++i ) - tl.push_back( *new( tbb::task::allocate_root() ) RootLauncherTask ); - TRY(); - tbb::task::spawn_root_and_wait(tl); - CATCH_AND_ASSERT(); - ASSERT (!exceptionCaught, "exception in this scope is unexpected"); - intptr_t num_tasks_expected = NUM_ROOT_TASKS * (NUM_CHILD_TASKS + 2); - ASSERT (g_CurStat.Existed() == num_tasks_expected, "Wrong total number of tasks"); - if ( g_SolitaryException ) - ASSERT (g_CurStat.Executed() >= num_tasks_expected - NUM_CHILD_TASKS, "Unexpected number of executed tasks"); - ASSERT_TEST_POSTCOND(); -} // void Test4 () - -class RootsGroupLauncherTask : public TaskBase { - tbb::task* do_execute () { - tbb::task_group_context ctx (tbb::task_group_context::isolated); - tbb::task_list tl; - for ( size_t i = 0; i < NUM_ROOT_TASKS; ++i ) - tl.push_back( *new( allocate_root(ctx) ) SimpleRootTask ); - TRY(); - spawn_root_and_wait(tl); - // Give worker a chance to throw exception - WaitForException(); - CATCH_AND_ASSERT(); - return NULL; - } -}; - -/** Allocates and spawns a bunch of roots, which allocate and spawn groups of roots - with an isolated context shared by all group members, which at last spawn a bunch - of children each, one of which throws a test exception in a worker thread. **/ -void Test5 () { - ResetGlobals(); - tbb::task_list tl; - for ( size_t i = 0; i < NUM_ROOTS_IN_GROUP; ++i ) - tl.push_back( *new( tbb::task::allocate_root() ) RootsGroupLauncherTask ); - TRY(); - tbb::task::spawn_root_and_wait(tl); - CATCH_AND_ASSERT(); - ASSERT (!exceptionCaught, "unexpected exception intercepted"); - if ( g_SolitaryException ) { - intptr_t num_tasks_expected = NUM_ROOTS_IN_GROUP * (1 + NUM_ROOT_TASKS * (1 + NUM_CHILD_TASKS)); - intptr_t min_num_tasks_executed = num_tasks_expected - NUM_ROOT_TASKS * (NUM_CHILD_TASKS + 1); - ASSERT (g_CurStat.Executed() >= min_num_tasks_executed, "Too few tasks executed"); - } - ASSERT_TEST_POSTCOND(); -} // void Test5 () - -class ThrowingRootLauncherTask : public TaskBase { - tbb::task* do_execute () { - tbb::task_group_context ctx (tbb::task_group_context::bound); - SimpleRootTask &r = *new( allocate_root(ctx) ) SimpleRootTask(false); - TRY(); - spawn_root_and_wait(r); - CATCH(); - ASSERT (!exceptionCaught, "unexpected exception intercepted"); - ThrowTestException(NUM_CHILD_TASKS); - g_TaskWasCancelled |= is_cancelled(); - return NULL; - } -}; - -class BoundHierarchyLauncherTask : public TaskBase { - bool m_Recover; - - void alloc_roots ( tbb::task_group_context& ctx, tbb::task_list& tl ) { - for ( size_t i = 0; i < NUM_ROOT_TASKS; ++i ) - tl.push_back( *new( allocate_root(ctx) ) ThrowingRootLauncherTask ); - } - - tbb::task* do_execute () { - tbb::task_group_context ctx (tbb::task_group_context::isolated); - tbb::task_list tl; - alloc_roots(ctx, tl); - TRY(); - spawn_root_and_wait(tl); - CATCH_AND_ASSERT(); - ASSERT (exceptionCaught, "no exception occurred"); - ASSERT (!tl.empty(), "task list was cleared somehow"); - if ( g_SolitaryException ) - ASSERT (g_TaskWasCancelled, "No tasks were cancelled despite of exception"); - if ( m_Recover ) { - // Test task_group_context::unbind and task_group_context::reset methods - g_ThrowException = false; - exceptionCaught = false; - tl.clear(); - alloc_roots(ctx, tl); - ctx.reset(); - try { - spawn_root_and_wait(tl); - } - catch (...) { - exceptionCaught = true; - } - ASSERT (!exceptionCaught, "unexpected exception occurred"); - } - return NULL; - } -public: - BoundHierarchyLauncherTask ( bool recover = false ) : m_Recover(recover) {} - -}; // class BoundHierarchyLauncherTask - -//! Test for bound contexts forming 2 level tree. Exception is thrown on the 1st (root) level. -/** Allocates and spawns a root that spawns a bunch of 2nd level roots sharing - the same isolated context, each of which in their turn spawns a single 3rd level - root with the bound context, and these 3rd level roots spawn bunches of leaves - in the end. Leaves do not generate exceptions. The test exception is generated - by one of the 2nd level roots. **/ -void Test6 () { - ResetGlobals(); - BoundHierarchyLauncherTask &r = *new( tbb::task::allocate_root() ) BoundHierarchyLauncherTask; - TRY(); - tbb::task::spawn_root_and_wait(r); - CATCH_AND_ASSERT(); - ASSERT (!exceptionCaught, "unexpected exception intercepted"); - // After the first of the branches (ThrowingRootLauncherTask) completes, - // the rest of the task tree may be collapsed before having a chance to execute leaves. - // A number of branches running concurrently with the first one will be able to spawn leaves though. - /// \todo: If additional checkpoints are added to scheduler the following assertion must weaken - intptr_t num_tasks_expected = 1 + NUM_ROOT_TASKS * (2 + NUM_CHILD_TASKS); - intptr_t min_num_tasks_created = 1 + g_NumThreads * 2 + NUM_CHILD_TASKS; - // 2 stands for BoundHierarchyLauncherTask and SimpleRootTask - // 1 corresponds to BoundHierarchyLauncherTask - intptr_t min_num_tasks_executed = 2 + 1 + NUM_CHILD_TASKS; - ASSERT (g_CurStat.Existed() <= num_tasks_expected, "Number of expected tasks is calculated incorrectly"); - ASSERT (g_CurStat.Existed() >= min_num_tasks_created, "Too few tasks created"); - ASSERT (g_CurStat.Executed() >= min_num_tasks_executed, "Too few tasks executed"); - ASSERT_TEST_POSTCOND(); -} // void Test6 () - -//! Tests task_group_context::unbind and task_group_context::reset methods. -/** Allocates and spawns a root that spawns a bunch of 2nd level roots sharing - the same isolated context, each of which in their turn spawns a single 3rd level - root with the bound context, and these 3rd level roots spawn bunches of leaves - in the end. Leaves do not generate exceptions. The test exception is generated - by one of the 2nd level roots. **/ -void Test7 () { - ResetGlobals(); - BoundHierarchyLauncherTask &r = *new( tbb::task::allocate_root() ) BoundHierarchyLauncherTask; - TRY(); - tbb::task::spawn_root_and_wait(r); - CATCH_AND_ASSERT(); - ASSERT (!exceptionCaught, "unexpected exception intercepted"); - ASSERT_TEST_POSTCOND(); -} // void Test6 () - -class BoundHierarchyLauncherTask2 : public TaskBase { - tbb::task* do_execute () { - tbb::task_group_context ctx; - tbb::task_list tl; - for ( size_t i = 0; i < NUM_ROOT_TASKS; ++i ) - tl.push_back( *new( allocate_root(ctx) ) RootLauncherTask(tbb::task_group_context::bound) ); - TRY(); - spawn_root_and_wait(tl); - CATCH_AND_ASSERT(); - // Exception must be intercepted by RootLauncherTask - ASSERT (!exceptionCaught, "no exception occurred"); - return NULL; - } -}; // class BoundHierarchyLauncherTask2 - -//! Test for bound contexts forming 2 level tree. Exception is thrown in the 2nd (outer) level. -/** Allocates and spawns a root that spawns a bunch of 2nd level roots sharing - the same isolated context, each of which in their turn spawns a single 3rd level - root with the bound context, and these 3rd level roots spawn bunches of leaves - in the end. The test exception is generated by one of the leaves. **/ -void Test8 () { - ResetGlobals(); - BoundHierarchyLauncherTask2 &r = *new( tbb::task::allocate_root() ) BoundHierarchyLauncherTask2; - TRY(); - tbb::task::spawn_root_and_wait(r); - CATCH_AND_ASSERT(); - ASSERT (!exceptionCaught, "unexpected exception intercepted"); - if ( g_SolitaryException ) { - intptr_t num_tasks_expected = 1 + NUM_ROOT_TASKS * (2 + NUM_CHILD_TASKS); - intptr_t min_num_tasks_created = 1 + g_NumThreads * (2 + NUM_CHILD_TASKS); - intptr_t min_num_tasks_executed = num_tasks_expected - (NUM_CHILD_TASKS + 1); - ASSERT (g_CurStat.Existed() <= num_tasks_expected, "Number of expected tasks is calculated incorrectly"); - ASSERT (g_CurStat.Existed() >= min_num_tasks_created, "Too few tasks created"); - ASSERT (g_CurStat.Executed() >= min_num_tasks_executed, "Too few tasks executed"); - } - ASSERT_TEST_POSTCOND(); -} // void Test8 () - -template -void ThrowMovableException ( intptr_t threshold, const T& data ) { - if ( !IsThrowingThread() ) - return; - if ( !g_SolitaryException ) { -#if __TBB_ATOMICS_CODEGEN_BROKEN - g_ExceptionsThrown = g_ExceptionsThrown + 1; -#else - ++g_ExceptionsThrown; -#endif - throw tbb::movable_exception(data); - } - while ( g_CurStat.Existed() < threshold ) - __TBB_Yield(); - if ( g_ExceptionsThrown.compare_and_swap(1, 0) == 0 ) - throw tbb::movable_exception(data); -} - -const int g_IntExceptionData = -375; -const std::string g_StringExceptionData = "My test string"; - -// Exception data class implementing minimal requirements of tbb::movable_exception -class ExceptionData { - const ExceptionData& operator = ( const ExceptionData& src ); - explicit ExceptionData ( int n ) : m_Int(n), m_String(g_StringExceptionData) {} -public: - ExceptionData ( const ExceptionData& src ) : m_Int(src.m_Int), m_String(src.m_String) {} - ~ExceptionData () {} - - int m_Int; - std::string m_String; - - // Simple way to provide an instance when all initializing constructors are private - // and to avoid memory reclamation problems. - static ExceptionData s_data; -}; - -ExceptionData ExceptionData::s_data(g_IntExceptionData); - -typedef tbb::movable_exception SolitaryMovableException; -typedef tbb::movable_exception MultipleMovableException; - -class LeafTaskWithMovableExceptions : public TaskBase { - bool m_IntAsData; - - tbb::task* do_execute () { - Harness::ConcurrencyTracker ct; - WaitUntilConcurrencyPeaks(); - if ( g_SolitaryException ) - ThrowMovableException(NUM_CHILD_TASKS/2, g_IntExceptionData); - else - ThrowMovableException(NUM_CHILD_TASKS/2, ExceptionData::s_data); - return NULL; - } -}; - -void CheckException ( tbb::tbb_exception& e ) { - ASSERT (strcmp(e.name(), (g_SolitaryException ? typeid(SolitaryMovableException) - : typeid(MultipleMovableException)).name() ) == 0, - "Unexpected original exception name"); - ASSERT (strcmp(e.what(), "tbb::movable_exception") == 0, "Unexpected original exception info "); - if ( g_SolitaryException ) { - SolitaryMovableException& me = dynamic_cast(e); - ASSERT (me.data() == g_IntExceptionData, "Unexpected solitary movable_exception data"); - } - else { - MultipleMovableException& me = dynamic_cast(e); - ASSERT (me.data().m_Int == g_IntExceptionData, "Unexpected multiple movable_exception int data"); - ASSERT (me.data().m_String == g_StringExceptionData, "Unexpected multiple movable_exception string data"); - } -} - -void CheckException () { - try { - throw; - } catch ( tbb::tbb_exception& e ) { - CheckException(e); - } - catch ( ... ) { - } -} - -//! Test for movable_exception behavior, and external exception recording. -/** Allocates a root task that spawns a bunch of children, one or several of which throw - a movable exception in a worker or master thread (depending on the global settings). - The test also checks the correctness of multiple rethrowing of the pending exception. **/ -void TestMovableException () { - ResetGlobals(); - tbb::task_group_context ctx; - tbb::empty_task *r = new( tbb::task::allocate_root() ) tbb::empty_task; - ASSERT (!g_CurStat.Existing() && !g_CurStat.Existed() && !g_CurStat.Executed(), - "something wrong with the task accounting"); - r->set_ref_count(NUM_CHILD_TASKS + 1); - for ( int i = 0; i < NUM_CHILD_TASKS; ++i ) - r->spawn( *new( r->allocate_child() ) LeafTaskWithMovableExceptions ); - TRY() - r->wait_for_all(); - } catch ( ... ) { - ASSERT (!ctx.is_group_execution_cancelled(), ""); - CheckException(); - try { - throw; - } catch ( tbb::tbb_exception& e ) { - CheckException(e); - g_ExceptionCaught = exceptionCaught = true; - } - catch ( ... ) { - g_ExceptionCaught = true; - g_UnknownException = unknownException = true; - } - ctx.register_pending_exception(); - ASSERT (ctx.is_group_execution_cancelled(), "After exception registration the context must be in the cancelled state"); - } - r->destroy(*r); - ASSERT_EXCEPTION(); - ASSERT_TEST_POSTCOND(); - - r = new( tbb::task::allocate_root(ctx) ) tbb::empty_task; - r->set_ref_count(1); - g_ExceptionCaught = g_UnknownException = false; - try { - r->wait_for_all(); - } catch ( tbb::tbb_exception& e ) { - CheckException(e); - g_ExceptionCaught = true; - } - catch ( ... ) { - g_ExceptionCaught = true; - g_UnknownException = true; - } - ASSERT (g_ExceptionCaught, "no exception occurred"); - ASSERT (__TBB_EXCEPTION_TYPE_INFO_BROKEN || !g_UnknownException, "unknown exception was caught"); - r->destroy(*r); -} // void Test10 () - -#endif /* TBB_USE_EXCEPTIONS */ - -template -class CtxLauncherTask : public tbb::task { - tbb::task_group_context &m_Ctx; - - tbb::task* execute () { - tbb::task::spawn_root_and_wait( *new( tbb::task::allocate_root(m_Ctx) ) T ); - return NULL; - } -public: - CtxLauncherTask ( tbb::task_group_context& ctx ) : m_Ctx(ctx) {} -}; - -//! Test for cancelling a task hierarchy from outside (from a task running in parallel with it). -void TestCancelation () { - ResetGlobals(); - g_ThrowException = false; - tbb::task_group_context ctx; - tbb::task_list tl; - tl.push_back( *new( tbb::task::allocate_root() ) CtxLauncherTask(ctx) ); - tl.push_back( *new( tbb::task::allocate_root() ) CancellatorTask(ctx, NUM_CHILD_TASKS / 4) ); - TRY(); - tbb::task::spawn_root_and_wait(tl); - CATCH_AND_FAIL(); - ASSERT (g_CurStat.Executed() <= g_ExecutedAtCatch + g_NumThreads, "Too many tasks were executed after cancellation"); - ASSERT_TEST_POSTCOND(); -} // void Test9 () - -class CtxDestroyerTask : public tbb::task { - int m_nestingLevel; - - tbb::task* execute () { - ASSERT ( m_nestingLevel >= 0 && m_nestingLevel < MaxNestingDepth, "Wrong nesting level. The test is broken" ); - tbb::task_group_context ctx; - tbb::task *t = new( tbb::task::allocate_root(ctx) ) tbb::empty_task; - int level = ++m_nestingLevel; - if ( level < MaxNestingDepth ) { - execute(); - } - else { - if ( !CancellatorTask::WaitUntilReady() ) - REPORT( "Warning: missing wakeup\n" ); - ++g_CurExecuted; - } - if ( ctx.is_group_execution_cancelled() ) - ++s_numCancelled; - t->destroy(*t); - return NULL; - } -public: - CtxDestroyerTask () : m_nestingLevel(0) { s_numCancelled = 0; } - - static const int MaxNestingDepth = 256; - static int s_numCancelled; -}; - -int CtxDestroyerTask::s_numCancelled = 0; - -//! Test for data race between cancellation propagation and context destruction. -/** If the data race ever occurs, an assertion inside TBB will be triggered. **/ -void TestCtxDestruction () { - for ( size_t i = 0; i < 10; ++i ) { - tbb::task_group_context ctx; - tbb::task_list tl; - ResetGlobals(); - g_BoostExecutedCount = false; - g_ThrowException = false; - CancellatorTask::Reset(); - - tl.push_back( *new( tbb::task::allocate_root() ) CtxLauncherTask(ctx) ); - tl.push_back( *new( tbb::task::allocate_root() ) CancellatorTask(ctx, 1) ); - tbb::task::spawn_root_and_wait(tl); - ASSERT( g_CurExecuted == 1, "Test is broken" ); - ASSERT( CtxDestroyerTask::s_numCancelled <= CtxDestroyerTask::MaxNestingDepth, "Test is broken" ); - } -} // void TestCtxDestruction() - -#include -#include "harness_barrier.h" - -class CtxConcurrentDestroyer : NoAssign, Harness::NoAfterlife { - static const int ContextsPerThread = 512; - - static int s_Concurrency; - static int s_NumContexts; - static tbb::task_group_context** s_Contexts; - static char* s_Buffer; - static Harness::SpinBarrier s_Barrier; - static Harness::SpinBarrier s_ExitBarrier; - - struct Shuffler { - void operator() () const { std::random_shuffle(s_Contexts, s_Contexts + s_NumContexts); } - }; -public: - static void Init ( int p ) { - s_Concurrency = p; - s_NumContexts = p * ContextsPerThread; - s_Contexts = new tbb::task_group_context*[s_NumContexts]; - s_Buffer = new char[s_NumContexts * sizeof(tbb::task_group_context)]; - s_Barrier.initialize( p ); - s_ExitBarrier.initialize( p ); - } - static void Uninit () { - for ( int i = 0; i < s_NumContexts; ++i ) { - tbb::internal::context_list_node_t &node = s_Contexts[i]->my_node; - ASSERT( !node.my_next && !node.my_prev, "Destroyed context was written to during context chain update" ); - } - delete s_Contexts; - delete s_Buffer; - } - - void operator() ( int id ) const { - int begin = ContextsPerThread * id, - end = begin + ContextsPerThread; - for ( int i = begin; i < end; ++i ) - s_Contexts[i] = new( s_Buffer + i * sizeof(tbb::task_group_context) ) tbb::task_group_context; - s_Barrier.wait( Shuffler() ); - for ( int i = begin; i < end; ++i ) { - s_Contexts[i]->tbb::task_group_context::~task_group_context(); - memset( s_Contexts[i], 0, sizeof(tbb::task_group_context) ); - } - s_ExitBarrier.wait(); - } -}; // class CtxConcurrentDestroyer - -int CtxConcurrentDestroyer::s_Concurrency; -int CtxConcurrentDestroyer::s_NumContexts; -tbb::task_group_context** CtxConcurrentDestroyer::s_Contexts; -char* CtxConcurrentDestroyer::s_Buffer; -Harness::SpinBarrier CtxConcurrentDestroyer::s_Barrier; -Harness::SpinBarrier CtxConcurrentDestroyer::s_ExitBarrier; - -void TestConcurrentCtxDestruction () { - REMARK( "TestConcurrentCtxDestruction\n" ); - CtxConcurrentDestroyer::Init(g_NumThreads); - NativeParallelFor( g_NumThreads, CtxConcurrentDestroyer() ); - CtxConcurrentDestroyer::Uninit(); -} - -void RunTests () { - REMARK ("Number of threads %d\n", g_NumThreads); - tbb::task_scheduler_init init (g_NumThreads); - g_Master = Harness::CurrentTid(); -#if TBB_USE_EXCEPTIONS - Test1(); - Test2(); - Test3(); - Test4(); - Test5(); - Test6(); - Test7(); - Test8(); - TestMovableException(); -#endif /* TBB_USE_EXCEPTIONS */ - TestCancelation(); - TestCtxDestruction(); -#if !RML_USE_WCRM - TestConcurrentCtxDestruction(); -#endif -} -#endif /* __TBB_TASK_GROUP_CONTEXT */ - -int TestMain () { - REMARK ("Using %s", TBB_USE_CAPTURED_EXCEPTION ? "tbb:captured_exception" : "exact exception propagation"); - MinThread = min(NUM_ROOTS_IN_GROUP, min(tbb::task_scheduler_init::default_num_threads(), max(2, MinThread))); - MaxThread = min(NUM_ROOTS_IN_GROUP, max(MinThread, min(tbb::task_scheduler_init::default_num_threads(), MaxThread))); - ASSERT (NUM_ROOTS_IN_GROUP < NUM_ROOT_TASKS, "Fix defines"); -#if __TBB_TASK_GROUP_CONTEXT -#if TBB_USE_EXCEPTIONS - // Test0 always runs on one thread - Test0(); -#endif /* TBB_USE_EXCEPTIONS */ - g_SolitaryException = 0; - for ( g_NumThreads = MinThread; g_NumThreads <= MaxThread; ++g_NumThreads ) - RunTests(); - return Harness::Done; -#else - return Harness::Skipped; -#endif /* __TBB_TASK_GROUP_CONTEXT */ -} diff --git a/deal.II/contrib/tbb/tbb30_104oss/src/test/test_enumerable_thread_specific.cpp b/deal.II/contrib/tbb/tbb30_104oss/src/test/test_enumerable_thread_specific.cpp deleted file mode 100644 index 5d1921fe8e..0000000000 --- a/deal.II/contrib/tbb/tbb30_104oss/src/test/test_enumerable_thread_specific.cpp +++ /dev/null @@ -1,1021 +0,0 @@ -/* - Copyright 2005-2010 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. -*/ - -#include "tbb/enumerable_thread_specific.h" -#include "tbb/task_scheduler_init.h" -#include "tbb/parallel_for.h" -#include "tbb/parallel_reduce.h" -#include "tbb/blocked_range.h" -#include "tbb/tick_count.h" -#include "tbb/tbb_allocator.h" -#include "tbb/tbb_thread.h" -#include "tbb/atomic.h" - -#if !TBB_USE_EXCEPTIONS && _MSC_VER - // Suppress "C++ exception handler used, but unwind semantics are not enabled" warning in STL headers - #pragma warning (push) - #pragma warning (disable: 4530) -#endif - -#include -#include -#include -#include -#include -#include - -#if !TBB_USE_EXCEPTIONS && _MSC_VER - #pragma warning (pop) -#endif - -#include "harness_assert.h" -#include "harness.h" - -#if __TBB_GCC_WARNING_SUPPRESSION_ENABLED -#pragma GCC diagnostic ignored "-Wuninitialized" -#endif - -static tbb::atomic construction_counter; -static tbb::atomic destruction_counter; - -const int REPETITIONS = 10; -const int N = 100000; -const int VALID_NUMBER_OF_KEYS = 100; -const double EXPECTED_SUM = (REPETITIONS + 1) * N; - -//! A minimal class that occupies N bytes. -/** Defines default and copy constructor, and allows implicit operator&. - Hides operator=. */ -template -class minimal: NoAssign { -private: - int my_value; - bool is_constructed; - char pad[N-sizeof(int) - sizeof(bool)]; -public: - minimal() : NoAssign(), my_value(0) { ++construction_counter; is_constructed = true; } - minimal( const minimal &m ) : NoAssign(), my_value(m.my_value) { ++construction_counter; is_constructed = true; } - ~minimal() { ++destruction_counter; ASSERT(is_constructed, NULL); is_constructed = false; } - void set_value( const int i ) { ASSERT(is_constructed, NULL); my_value = i; } - int value( ) const { ASSERT(is_constructed, NULL); return my_value; } -}; - -// -// A helper class that simplifies writing the tests since minimal does not -// define = or + operators. -// - -template< typename T > -struct test_helper { - static inline void init(T &e) { e = static_cast(0); } - static inline void sum(T &e, const int addend ) { e += static_cast(addend); } - static inline void sum(T &e, const double addend ) { e += static_cast(addend); } - static inline void set(T &e, const int value ) { e = static_cast(value); } - static inline double get(const T &e ) { return static_cast(e); } -}; - -template -struct test_helper > { - static inline void init(minimal &sum) { sum.set_value( 0 ); } - static inline void sum(minimal &sum, const int addend ) { sum.set_value( sum.value() + addend); } - static inline void sum(minimal &sum, const double addend ) { sum.set_value( sum.value() + static_cast(addend)); } - static inline void sum(minimal &sum, const minimal &addend ) { sum.set_value( sum.value() + addend.value()); } - static inline void set(minimal &v, const int value ) { v.set_value( static_cast(value) ); } - static inline double get(const minimal &sum ) { return static_cast(sum.value()); } -}; - -//! Tag class used to make certain constructors hard to invoke accidentally. -struct SecretTagType {} SecretTag; - -//// functors and routines for initialization and combine - -// Addition - -template -struct FunctorAddCombineRef { - T operator()(const T& left, const T& right) const { - return left+right; - } -}; - -template -struct FunctorAddCombineRef > { - minimal operator()(const minimal& left, const minimal& right) const { - minimal result; - result.set_value( left.value() + right.value() ); - return result; - } -}; - -//! Counts instances of FunctorFinit -static tbb::atomic FinitCounter; - -template -struct FunctorFinit { - FunctorFinit( const FunctorFinit& ) {++FinitCounter;} - FunctorFinit( SecretTagType ) {++FinitCounter;} - ~FunctorFinit() {--FinitCounter;} - T operator()() { return Value; } -}; - -template -struct FunctorFinit,Value> { - FunctorFinit( const FunctorFinit& ) {++FinitCounter;} - FunctorFinit( SecretTagType ) {++FinitCounter;} - ~FunctorFinit() {--FinitCounter;} - minimal operator()() { - minimal result; - result.set_value( Value ); - return result; - } -}; - -template -struct FunctorAddCombine { - T operator()(T left, T right ) const { - return FunctorAddCombineRef()( left, right ); - } -}; - -template -T my_combine_ref( const T &left, const T &right) { - return FunctorAddCombineRef()( left, right ); -} - -template -T my_combine( T left, T right) { return my_combine_ref(left,right); } - -template -class combine_one_helper { -public: - combine_one_helper(T& _result) : my_result(_result) {} - void operator()(const T& new_bit) { test_helper::sum(my_result, new_bit); } - combine_one_helper& operator=(const combine_one_helper& other) { - test_helper::set(my_result, test_helper::get(other)); - return *this; - } -private: - T& my_result; -}; - -//// end functors and routines - -template< typename T > -void run_serial_scalar_tests(const char *test_name) { - tbb::tick_count t0; - T sum; - test_helper::init(sum); - - REMARK("Testing serial %s... ", test_name); - for (int t = -1; t < REPETITIONS; ++t) { - if (Verbose && t == 0) t0 = tbb::tick_count::now(); - for (int i = 0; i < N; ++i) { - test_helper::sum(sum,1); - } - } - - double result_value = test_helper::get(sum); - ASSERT( EXPECTED_SUM == result_value, NULL); - REMARK("done\nserial %s, 0, %g, %g\n", test_name, result_value, ( tbb::tick_count::now() - t0).seconds()); -} - - -template -class parallel_scalar_body: NoAssign { - - tbb::enumerable_thread_specific &sums; - -public: - - parallel_scalar_body ( tbb::enumerable_thread_specific &_sums ) : sums(_sums) { } - - void operator()( const tbb::blocked_range &r ) const { - for (int i = r.begin(); i != r.end(); ++i) - test_helper::sum( sums.local(), 1 ); - } - -}; - -template< typename T > -void run_parallel_scalar_tests_nocombine(const char *test_name) { - - typedef tbb::enumerable_thread_specific ets_type; - - // We assume that static_sums zero-initialized or has a default constructor that zeros it. - static ets_type static_sums = ets_type( T() ); - - T exemplar; - test_helper::init(exemplar); - T exemplar23; - test_helper::set(exemplar23,23); - - for (int p = MinThread; p <= MaxThread; ++p) { - REMARK("Testing parallel %s on %d thread(s)... ", test_name, p); - tbb::task_scheduler_init init(p); - tbb::tick_count t0; - - T iterator_sum; - test_helper::init(iterator_sum); - - T finit_ets_sum; - test_helper::init(finit_ets_sum); - - T const_iterator_sum; - test_helper::init(const_iterator_sum); - - T range_sum; - test_helper::init(range_sum); - - T const_range_sum; - test_helper::init(const_range_sum); - - T cconst_sum; - test_helper::init(cconst_sum); - - T assign_sum; - test_helper::init(assign_sum); - - T cassgn_sum; - test_helper::init(cassgn_sum); - T non_cassgn_sum; - test_helper::init(non_cassgn_sum); - - T static_sum; - test_helper::init(static_sum); - - for (int t = -1; t < REPETITIONS; ++t) { - if (Verbose && t == 0) t0 = tbb::tick_count::now(); - - static_sums.clear(); - - ets_type sums(exemplar); - FunctorFinit my_finit(SecretTag); - ets_type finit_ets(my_finit); - - ASSERT( sums.empty(), NULL); - tbb::parallel_for( tbb::blocked_range( 0, N, 10000 ), parallel_scalar_body( sums ) ); - ASSERT( !sums.empty(), NULL); - - ASSERT( finit_ets.empty(), NULL); - tbb::parallel_for( tbb::blocked_range( 0, N, 10000 ), parallel_scalar_body( finit_ets ) ); - ASSERT( !finit_ets.empty(), NULL); - - ASSERT(static_sums.empty(), NULL); - tbb::parallel_for( tbb::blocked_range( 0, N, 10000 ), parallel_scalar_body( static_sums ) ); - ASSERT( !static_sums.empty(), NULL); - - // use iterator - typename ets_type::size_type size = 0; - for ( typename ets_type::iterator i = sums.begin(); i != sums.end(); ++i ) { - ++size; - test_helper::sum(iterator_sum, *i); - } - ASSERT( sums.size() == size, NULL); - - // use const_iterator - for ( typename ets_type::const_iterator i = sums.begin(); i != sums.end(); ++i ) { - test_helper::sum(const_iterator_sum, *i); - } - - // use range_type - typename ets_type::range_type r = sums.range(); - for ( typename ets_type::range_type::const_iterator i = r.begin(); i != r.end(); ++i ) { - test_helper::sum(range_sum, *i); - } - - // use const_range_type - typename ets_type::const_range_type cr = sums.range(); - for ( typename ets_type::const_range_type::iterator i = cr.begin(); i != cr.end(); ++i ) { - test_helper::sum(const_range_sum, *i); - } - - // test copy constructor, with TLS-cached locals - typedef typename tbb::enumerable_thread_specific, tbb::ets_key_per_instance> cached_ets_type; - - cached_ets_type cconst(sums); - - for ( typename cached_ets_type::const_iterator i = cconst.begin(); i != cconst.end(); ++i ) { - test_helper::sum(cconst_sum, *i); - } - - // test assignment - ets_type assigned; - assigned = sums; - - for ( typename ets_type::const_iterator i = assigned.begin(); i != assigned.end(); ++i ) { - test_helper::sum(assign_sum, *i); - } - - // test assign to and from cached locals - cached_ets_type cassgn; - cassgn = sums; - for ( typename cached_ets_type::const_iterator i = cassgn.begin(); i != cassgn.end(); ++i ) { - test_helper::sum(cassgn_sum, *i); - } - - ets_type non_cassgn; - non_cassgn = cassgn; - for ( typename ets_type::const_iterator i = non_cassgn.begin(); i != non_cassgn.end(); ++i ) { - test_helper::sum(non_cassgn_sum, *i); - } - - // test finit-initialized ets - for(typename ets_type::const_iterator i = finit_ets.begin(); i != finit_ets.end(); ++i) { - test_helper::sum(finit_ets_sum, *i); - } - - // test static ets - for(typename ets_type::const_iterator i = static_sums.begin(); i != static_sums.end(); ++i) { - test_helper::sum(static_sum, *i); - } - - } - - ASSERT( EXPECTED_SUM == test_helper::get(iterator_sum), NULL); - ASSERT( EXPECTED_SUM == test_helper::get(const_iterator_sum), NULL); - ASSERT( EXPECTED_SUM == test_helper::get(range_sum), NULL); - ASSERT( EXPECTED_SUM == test_helper::get(const_range_sum), NULL); - - ASSERT( EXPECTED_SUM == test_helper::get(cconst_sum), NULL); - ASSERT( EXPECTED_SUM == test_helper::get(assign_sum), NULL); - ASSERT( EXPECTED_SUM == test_helper::get(cassgn_sum), NULL); - ASSERT( EXPECTED_SUM == test_helper::get(non_cassgn_sum), NULL); - ASSERT( EXPECTED_SUM == test_helper::get(finit_ets_sum), NULL); - ASSERT( EXPECTED_SUM == test_helper::get(static_sum), NULL); - - REMARK("done\nparallel %s, %d, %g, %g\n", test_name, p, test_helper::get(iterator_sum), - ( tbb::tick_count::now() - t0).seconds()); - } -} - -template< typename T > -void run_parallel_scalar_tests(const char *test_name) { - - typedef tbb::enumerable_thread_specific ets_type; - - // We assume that static_sums zero-initialized or has a default constructor that zeros it. - static ets_type static_sums = ets_type( T() ); - - T exemplar; - test_helper::init(exemplar); - - run_parallel_scalar_tests_nocombine(test_name); - - for (int p = MinThread; p <= MaxThread; ++p) { - REMARK("Testing parallel %s on %d thread(s)... ", test_name, p); - tbb::task_scheduler_init init(p); - tbb::tick_count t0; - - T combine_sum; - test_helper::init(combine_sum); - - T combine_ref_sum; - test_helper::init(combine_ref_sum); - - T combine_one_sum; - test_helper::init(combine_one_sum); - - T static_sum; - test_helper::init(static_sum); - - for (int t = -1; t < REPETITIONS; ++t) { - if (Verbose && t == 0) t0 = tbb::tick_count::now(); - - static_sums.clear(); - - ets_type sums(exemplar); - - ASSERT( sums.empty(), NULL); - tbb::parallel_for( tbb::blocked_range( 0, N, 10000 ), parallel_scalar_body( sums ) ); - ASSERT( !sums.empty(), NULL); - - ASSERT(static_sums.empty(), NULL); - tbb::parallel_for( tbb::blocked_range( 0, N, 10000 ), parallel_scalar_body( static_sums ) ); - ASSERT( !static_sums.empty(), NULL); - - - // Use combine - test_helper::sum(combine_sum, sums.combine(my_combine)); - test_helper::sum(combine_ref_sum, sums.combine(my_combine_ref)); - test_helper::sum(static_sum, static_sums.combine(my_combine)); - - combine_one_helper my_helper(combine_one_sum); - sums.combine_each(my_helper); - } - - - ASSERT( EXPECTED_SUM == test_helper::get(combine_sum), NULL); - ASSERT( EXPECTED_SUM == test_helper::get(combine_ref_sum), NULL); - ASSERT( EXPECTED_SUM == test_helper::get(static_sum), NULL); - - REMARK("done\nparallel combine %s, %d, %g, %g\n", test_name, p, test_helper::get(combine_sum), - ( tbb::tick_count::now() - t0).seconds()); - } -} - -template -class parallel_vector_for_body: NoAssign { - - tbb::enumerable_thread_specific< std::vector > > &locals; - -public: - - parallel_vector_for_body ( tbb::enumerable_thread_specific< std::vector > > &_locals ) : locals(_locals) { } - - void operator()( const tbb::blocked_range &r ) const { - T one; - test_helper::set(one, 1); - - for (int i = r.begin(); i < r.end(); ++i) { - locals.local().push_back( one ); - } - } - -}; - -template -struct parallel_vector_reduce_body { - - T sum; - size_t count; - - parallel_vector_reduce_body ( ) : count(0) { test_helper::init(sum); } - parallel_vector_reduce_body ( parallel_vector_reduce_body &, tbb::split ) : count(0) { test_helper::init(sum); } - - void operator()( const R &r ) { - for (typename R::iterator ri = r.begin(); ri != r.end(); ++ri) { - const std::vector< T, tbb::tbb_allocator > &v = *ri; - ++count; - for (typename std::vector >::const_iterator vi = v.begin(); vi != v.end(); ++vi) { - test_helper::sum(sum, *vi); - } - } - } - - void join( const parallel_vector_reduce_body &b ) { - test_helper::sum(sum,b.sum); - count += b.count; - } - -}; - -template< typename T > -void run_parallel_vector_tests(const char *test_name) { - tbb::tick_count t0; - typedef std::vector > container_type; - - for (int p = MinThread; p <= MaxThread; ++p) { - REMARK("Testing parallel %s on %d thread(s)... ", test_name, p); - tbb::task_scheduler_init init(p); - - T sum; - test_helper::init(sum); - - for (int t = -1; t < REPETITIONS; ++t) { - if (Verbose && t == 0) t0 = tbb::tick_count::now(); - typedef typename tbb::enumerable_thread_specific< container_type > ets_type; - ets_type vs; - - ASSERT( vs.empty(), NULL); - tbb::parallel_for ( tbb::blocked_range (0, N, 10000), parallel_vector_for_body( vs ) ); - ASSERT( !vs.empty(), NULL); - - // copy construct - ets_type vs2(vs); // this causes an assertion failure, related to allocators... - - // assign - ets_type vs3; - vs3 = vs; - - parallel_vector_reduce_body< typename tbb::enumerable_thread_specific< std::vector< T, tbb::tbb_allocator > >::const_range_type, T > pvrb; - tbb::parallel_reduce ( vs.range(1), pvrb ); - - test_helper::sum(sum, pvrb.sum); - - ASSERT( vs.size() == pvrb.count, NULL); - - tbb::flattened2d fvs = flatten2d(vs); - size_t ccount = fvs.size(); - size_t elem_cnt = 0; - for(typename tbb::flattened2d::const_iterator i = fvs.begin(); i != fvs.end(); ++i) { - ++elem_cnt; - }; - ASSERT(ccount == elem_cnt, NULL); - - elem_cnt = 0; - for(typename tbb::flattened2d::iterator i = fvs.begin(); i != fvs.end(); ++i) { - ++elem_cnt; - }; - ASSERT(ccount == elem_cnt, NULL); - } - - double result_value = test_helper::get(sum); - ASSERT( EXPECTED_SUM == result_value, NULL); - REMARK("done\nparallel %s, %d, %g, %g\n", test_name, p, result_value, ( tbb::tick_count::now() - t0).seconds()); - } -} - -template -void run_cross_type_vector_tests(const char *test_name) { - tbb::tick_count t0; - typedef std::vector > container_type; - - for (int p = MinThread; p <= MaxThread; ++p) { - REMARK("Testing parallel %s on %d thread(s)... ", test_name, p); - tbb::task_scheduler_init init(p); - - T sum; - test_helper::init(sum); - - for (int t = -1; t < REPETITIONS; ++t) { - if (Verbose && t == 0) t0 = tbb::tick_count::now(); - typedef typename tbb::enumerable_thread_specific< container_type, tbb::cache_aligned_allocator, tbb::ets_no_key > ets_nokey_type; - typedef typename tbb::enumerable_thread_specific< container_type, tbb::cache_aligned_allocator, tbb::ets_key_per_instance > ets_tlskey_type; - ets_nokey_type vs; - - ASSERT( vs.empty(), NULL); - tbb::parallel_for ( tbb::blocked_range (0, N, 10000), parallel_vector_for_body( vs ) ); - ASSERT( !vs.empty(), NULL); - - // copy construct - ets_tlskey_type vs2(vs); - - // assign - ets_nokey_type vs3; - vs3 = vs2; - - parallel_vector_reduce_body< typename tbb::enumerable_thread_specific< std::vector< T, tbb::tbb_allocator > >::const_range_type, T > pvrb; - tbb::parallel_reduce ( vs3.range(1), pvrb ); - - test_helper::sum(sum, pvrb.sum); - - ASSERT( vs3.size() == pvrb.count, NULL); - - tbb::flattened2d fvs = flatten2d(vs3); - size_t ccount = fvs.size(); - size_t elem_cnt = 0; - for(typename tbb::flattened2d::const_iterator i = fvs.begin(); i != fvs.end(); ++i) { - ++elem_cnt; - }; - ASSERT(ccount == elem_cnt, NULL); - - elem_cnt = 0; - for(typename tbb::flattened2d::iterator i = fvs.begin(); i != fvs.end(); ++i) { - ++elem_cnt; - }; - ASSERT(ccount == elem_cnt, NULL); - } - - double result_value = test_helper::get(sum); - ASSERT( EXPECTED_SUM == result_value, NULL); - REMARK("done\nparallel %s, %d, %g, %g\n", test_name, p, result_value, ( tbb::tick_count::now() - t0).seconds()); - } -} - -template< typename T > -void run_serial_vector_tests(const char *test_name) { - tbb::tick_count t0; - T sum; - test_helper::init(sum); - T one; - test_helper::set(one, 1); - - REMARK("Testing serial %s... ", test_name); - for (int t = -1; t < REPETITIONS; ++t) { - if (Verbose && t == 0) t0 = tbb::tick_count::now(); - std::vector > v; - for (int i = 0; i < N; ++i) { - v.push_back( one ); - } - for (typename std::vector >::const_iterator i = v.begin(); i != v.end(); ++i) - test_helper::sum(sum, *i); - } - - double result_value = test_helper::get(sum); - ASSERT( EXPECTED_SUM == result_value, NULL); - REMARK("done\nserial %s, 0, %g, %g\n", test_name, result_value, ( tbb::tick_count::now() - t0).seconds()); -} - -const size_t line_size = tbb::internal::NFS_MaxLineSize; - -void -run_serial_tests() { - run_serial_scalar_tests("int"); - run_serial_scalar_tests("double"); - run_serial_scalar_tests >("minimal<>"); - run_serial_vector_tests("std::vector >"); - run_serial_vector_tests("std::vector >"); -} - -void -run_parallel_tests() { - run_parallel_scalar_tests("int"); - run_parallel_scalar_tests("double"); - run_parallel_scalar_tests_nocombine >("minimal<>"); - run_parallel_vector_tests("std::vector >"); - run_parallel_vector_tests("std::vector >"); -} - -void -run_cross_type_tests() { - // cross-type scalar tests are part of run_serial_scalar_tests - run_cross_type_vector_tests("std::vector >"); - run_parallel_vector_tests("std::vector >"); -} - -typedef tbb::enumerable_thread_specific > flogged_ets; - -class set_body { - flogged_ets *a; - -public: - set_body( flogged_ets*_a ) : a(_a) { } - - void operator() ( ) const { - for (int i = 0; i < VALID_NUMBER_OF_KEYS; ++i) { - a[i].local().set_value(i + 1); - } - } - -}; - -void do_tbb_threads( int max_threads, flogged_ets a[] ) { - std::vector< tbb::tbb_thread * > threads; - - for (int p = 0; p < max_threads; ++p) { - threads.push_back( new tbb::tbb_thread ( set_body( a ) ) ); - } - - for (int p = 0; p < max_threads; ++p) { - threads[p]->join(); - } - - for(int p = 0; p < max_threads; ++p) { - delete threads[p]; - } -} - -void -flog_key_creation_and_deletion() { - const int FLOG_REPETITIONS = 100; - - for (int p = MinThread; p <= MaxThread; ++p) { - REMARK("Testing repeated deletes on %d threads... ", p); - - for (int j = 0; j < FLOG_REPETITIONS; ++j) { - construction_counter = 0; - destruction_counter = 0; - - // causes VALID_NUMER_OF_KEYS exemplar instances to be constructed - flogged_ets* a = new flogged_ets[VALID_NUMBER_OF_KEYS]; - ASSERT(int(construction_counter) == 0, NULL); // no exemplars or actual locals have been constructed - ASSERT(int(destruction_counter) == 0, NULL); // and none have been destroyed - - // causes p * VALID_NUMBER_OF_KEYS minimals to be created - do_tbb_threads(p, a); - - for (int i = 0; i < VALID_NUMBER_OF_KEYS; ++i) { - int pcnt = 0; - for ( flogged_ets::iterator tli = a[i].begin(); tli != a[i].end(); ++tli ) { - ASSERT( (*tli).value() == i+1, NULL ); - ++pcnt; - } - ASSERT( pcnt == p, NULL); // should be one local per thread. - } - delete[] a; - } - - ASSERT( int(construction_counter) == (p)*VALID_NUMBER_OF_KEYS, NULL ); - ASSERT( int(destruction_counter) == (p)*VALID_NUMBER_OF_KEYS, NULL ); - - REMARK("done\nTesting repeated clears on %d threads... ", p); - - construction_counter = 0; - destruction_counter = 0; - - // causes VALID_NUMER_OF_KEYS exemplar instances to be constructed - flogged_ets* a = new flogged_ets[VALID_NUMBER_OF_KEYS]; - - for (int j = 0; j < FLOG_REPETITIONS; ++j) { - - // causes p * VALID_NUMBER_OF_KEYS minimals to be created - do_tbb_threads(p, a); - - for (int i = 0; i < VALID_NUMBER_OF_KEYS; ++i) { - for ( flogged_ets::iterator tli = a[i].begin(); tli != a[i].end(); ++tli ) { - ASSERT( (*tli).value() == i+1, NULL ); - } - a[i].clear(); - ASSERT( static_cast(a[i].end() - a[i].begin()) == 0, NULL ); - } - - } - - delete[] a; - - ASSERT( int(construction_counter) == (FLOG_REPETITIONS*p)*VALID_NUMBER_OF_KEYS, NULL ); - ASSERT( int(destruction_counter) == (FLOG_REPETITIONS*p)*VALID_NUMBER_OF_KEYS, NULL ); - - REMARK("done\n"); - } - -} - -template -void -flog_segmented_interator() { - - bool found_error = false; - typedef typename inner_container::value_type T; - typedef std::vector< inner_container > nested_vec; - inner_container my_inner_container; - my_inner_container.clear(); - nested_vec my_vec; - - // simple nested vector (neither level empty) - const int maxval = 10; - for(int i=0; i < maxval; i++) { - my_vec.push_back(my_inner_container); - for(int j = 0; j < maxval; j++) { - my_vec.at(i).push_back((T)(maxval * i + j)); - } - } - - tbb::internal::segmented_iterator my_si(my_vec); - - T ii; - for(my_si=my_vec.begin(), ii=0; my_si != my_vec.end(); ++my_si, ++ii) { - if((*my_si) != ii) { - found_error = true; - REMARK( "*my_si=%d\n", int(*my_si)); - } - } - - // outer level empty - my_vec.clear(); - for(my_si=my_vec.begin(); my_si != my_vec.end(); ++my_si) { - found_error = true; - } - - // inner levels empty - my_vec.clear(); - for(int i =0; i < maxval; ++i) { - my_vec.push_back(my_inner_container); - } - for(my_si = my_vec.begin(); my_si != my_vec.end(); ++my_si) { - found_error = true; - } - - // every other inner container is empty - my_vec.clear(); - for(int i=0; i < maxval; ++i) { - my_vec.push_back(my_inner_container); - if(i%2) { - for(int j = 0; j < maxval; ++j) { - my_vec.at(i).push_back((T)(maxval * (i/2) + j)); - } - } - } - for(my_si = my_vec.begin(), ii=0; my_si != my_vec.end(); ++my_si, ++ii) { - if((*my_si) != ii) { - found_error = true; - REMARK("*my_si=%d, ii=%d\n", (int)(*my_si), (int)ii); - } - } - - tbb::internal::segmented_iterator my_csi(my_vec); - for(my_csi=my_vec.begin(), ii=0; my_csi != my_vec.end(); ++my_csi, ++ii) { - if((*my_csi) != ii) { - found_error = true; - REMARK( "*my_csi=%d\n", int(*my_csi)); - } - } - - // outer level empty - my_vec.clear(); - for(my_csi=my_vec.begin(); my_csi != my_vec.end(); ++my_csi) { - found_error = true; - } - - // inner levels empty - my_vec.clear(); - for(int i =0; i < maxval; ++i) { - my_vec.push_back(my_inner_container); - } - for(my_csi = my_vec.begin(); my_csi != my_vec.end(); ++my_csi) { - found_error = true; - } - - // every other inner container is empty - my_vec.clear(); - for(int i=0; i < maxval; ++i) { - my_vec.push_back(my_inner_container); - if(i%2) { - for(int j = 0; j < maxval; ++j) { - my_vec.at(i).push_back((T)(maxval * (i/2) + j)); - } - } - } - for(my_csi = my_vec.begin(), ii=0; my_csi != my_vec.end(); ++my_csi, ++ii) { - if((*my_csi) != ii) { - found_error = true; - REMARK("*my_csi=%d, ii=%d\n", (int)(*my_csi), (int)ii); - } - } - - - if(found_error) REPORT("segmented_iterator failed\n"); -} - -template -void -flog_segmented_iterator_map() { - typedef typename std::map my_map; - typedef std::vector< my_map > nested_vec; - my_map my_inner_container; - my_inner_container.clear(); - nested_vec my_vec; - my_vec.clear(); - bool found_error = false; - - // simple nested vector (neither level empty) - const int maxval = 4; - for(int i=0; i < maxval; i++) { - my_vec.push_back(my_inner_container); - for(int j = 0; j < maxval; j++) { - my_vec.at(i).insert(std::make_pair(maxval * i + j, 2*(maxval*i + j))); - } - } - - tbb::internal::segmented_iterator > my_si(my_vec); - Key ii; - for(my_si=my_vec.begin(), ii=0; my_si != my_vec.end(); ++my_si, ++ii) { - if(((*my_si).first != ii) || ((*my_si).second != 2*ii)) { - found_error = true; - REMARK( "ii=%d, (*my_si).first=%d, second=%d\n",ii, int((*my_si).first), int((*my_si).second)); - } - } - - tbb::internal::segmented_iterator > my_csi(my_vec); - for(my_csi=my_vec.begin(), ii=0; my_csi != my_vec.end(); ++my_csi, ++ii) { - if(((*my_csi).first != ii) || ((*my_csi).second != 2*ii)) { - found_error = true; - REMARK( "ii=%d, (*my_csi).first=%d, second=%d\n",ii, int((*my_csi).first), int((*my_csi).second)); - } - } -} - -void -run_segmented_iterator_tests() { - // only the following containers can be used with the segmented iterator. - REMARK("Running Segmented Iterator Tests\n"); - flog_segmented_interator >(); - flog_segmented_interator >(); - flog_segmented_interator >(); - flog_segmented_interator >(); - flog_segmented_interator >(); - flog_segmented_interator >(); - - flog_segmented_iterator_map(); - flog_segmented_iterator_map(); -} - -template -void -run_assign_and_copy_constructor_test(const char *test_name) { - REMARK("Testing assignment and copy construction for %s\n", test_name); - - // test initializer with exemplar - T initializer0; - test_helper::init(initializer0); - T initializer7; - test_helper::set(initializer7,7); - tbb::enumerable_thread_specific create1(initializer7); - (void) create1.local(); // create an initialized value - ASSERT(7 == test_helper::get(create1.local()), NULL); - - // test copy construction with exemplar initializer - create1.clear(); - tbb::enumerable_thread_specific copy1(create1); - (void) copy1.local(); - ASSERT(7 == test_helper::get(copy1.local()), NULL); - - // test copy assignment with exemplar initializer - create1.clear(); - tbb::enumerable_thread_specific assign1(initializer0); - assign1 = create1; - (void) assign1.local(); - ASSERT(7 == test_helper::get(assign1.local()), NULL); - - // test creation with finit function - FunctorFinit my_finit7(SecretTag); - tbb::enumerable_thread_specific create2(my_finit7); - (void) create2.local(); - ASSERT(7 == test_helper::get(create2.local()), NULL); - - // test copy construction with function initializer - create2.clear(); - tbb::enumerable_thread_specific copy2(create2); - (void) copy2.local(); - ASSERT(7 == test_helper::get(copy2.local()), NULL); - - // test copy assignment with function initializer - create2.clear(); - FunctorFinit my_finit(SecretTag); - tbb::enumerable_thread_specific assign2(my_finit); - assign2 = create2; - (void) assign2.local(); - ASSERT(7 == test_helper::get(assign2.local()), NULL); -} - -void -run_assignment_and_copy_constructor_tests() { - REMARK("Running assignment and copy constructor tests\n"); - run_assign_and_copy_constructor_test("int"); - run_assign_and_copy_constructor_test("double"); - // Try class sizes that are close to a cache line in size, in order to check padding calculations. - run_assign_and_copy_constructor_test >("minimal"); - run_assign_and_copy_constructor_test >("minimal"); - run_assign_and_copy_constructor_test >("minimal"); - ASSERT(FinitCounter==0, NULL); -} - -// Class with no default constructor -class HasNoDefaultConstructor { - HasNoDefaultConstructor(); -public: - HasNoDefaultConstructor( SecretTagType ) {} -}; - -// Initialization functor for a HasNoDefaultConstructor -struct HasNoDefaultConstructorFinit { - HasNoDefaultConstructor operator()() { - return HasNoDefaultConstructor(SecretTag); - } -}; - -struct HasNoDefaultConstructorCombine { - HasNoDefaultConstructor operator()( HasNoDefaultConstructor, HasNoDefaultConstructor ) { - return HasNoDefaultConstructor(SecretTag); - } -}; - -//! Test situations where only default constructor or copy constructor is required. -void TestInstantiation() { - // Test instantiation is possible when copy constructor is not required. - tbb::enumerable_thread_specific ets1; - - // Test instantiation when default constructor is not required, because exemplar is provided. - HasNoDefaultConstructor x(SecretTag); - tbb::enumerable_thread_specific ets2(x); - ets2.combine(HasNoDefaultConstructorCombine()); - - // Test instantiation when default constructor is not required, because init function is provided. - HasNoDefaultConstructorFinit f; - tbb::enumerable_thread_specific ets3(f); - ets3.combine(HasNoDefaultConstructorCombine()); -} - -int TestMain () { - TestInstantiation(); - run_segmented_iterator_tests(); - flog_key_creation_and_deletion(); - - if (MinThread == 0) { - run_serial_tests(); - MinThread = 1; - } - if (MaxThread > 0) { - run_parallel_tests(); - run_cross_type_tests(); - } - - run_assignment_and_copy_constructor_tests(); - - return Harness::Done; -} diff --git a/deal.II/contrib/tbb/tbb30_104oss/src/test/test_fast_random.cpp b/deal.II/contrib/tbb/tbb30_104oss/src/test/test_fast_random.cpp deleted file mode 100644 index fbece772b1..0000000000 --- a/deal.II/contrib/tbb/tbb30_104oss/src/test/test_fast_random.cpp +++ /dev/null @@ -1,162 +0,0 @@ -/* - Copyright 2005-2010 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. -*/ - -/** - The test checks that for different ranges of random numbers (from 0 to - [MinThread, MaxThread]) generated with different seeds the probability - of each number in the range deviates from the ideal random distribution - by no more than AcceptableDeviation percent. -**/ - -#include "harness_inject_scheduler.h" - -#define HARNESS_DEFAULT_MIN_THREADS 2 -#define HARNESS_DEFAULT_MAX_THREADS 32 - -#define TEST_TOTAL_SEQUENCE 0 - -#include "harness.h" -#include "tbb/atomic.h" - -//! Coefficient defining tolerable deviation from ideal random distribution -const double AcceptableDeviation = 2.1; -//! Tolerable probability of failure to achieve tolerable distribution -const double AcceptableProbabilityOfOutliers = 1e-6; -//! Coefficient defining the length of random numbers series used to estimate the distribution -/** Number of random values generated per each range element. I.e. the larger is - the range, the longer is the series of random values. **/ -const uintptr_t SeriesBaseLen = 100; -//! Number of random numbers series to generate -const uintptr_t NumSeries = 100; -//! Number of random number generation series with different seeds -const uintptr_t NumSeeds = 100; - -tbb::atomic NumHighOutliers; -tbb::atomic NumLowOutliers; - -inline void CheckProbability ( double probability, double expectedProbability, int index, int numIndices ) { - double lowerBound = expectedProbability / AcceptableDeviation, - upperBound = expectedProbability * AcceptableDeviation; - if ( probability < lowerBound ) { - if ( !NumLowOutliers ) - REMARK( "Warning: Probability %.3f of hitting index %d among %d elements is out of acceptable range (%.3f - %.3f)\n", - probability, index, numIndices, lowerBound, upperBound ); - ++NumLowOutliers; - } - else if ( probability > upperBound ) { - if ( !NumHighOutliers ) - REMARK( "Warning: Probability %.3f of hitting index %d among %d elements is out of acceptable range (%.3f - %.3f)\n", - probability, index, numIndices, lowerBound, upperBound ); - ++NumHighOutliers; - } -} - -struct CheckDistributionBody { - void operator() ( int id ) const { - uintptr_t randomRange = id + MinThread; - uintptr_t *curHits = new uintptr_t[randomRange] -#if TEST_TOTAL_SEQUENCE - , *totalHits = new uintptr_t[randomRange] -#endif - ; - double expectedProbability = 1./randomRange; - // Loop through different seeds - for ( uintptr_t i = 0; i < NumSeeds; ++i ) { - // Seed value is selected in two ways, the first of which mimics - // the one used by the TBB task scheduler - void* seed = i % 2 ? (char*)&curHits + i * 16 : (void*)(i * 8); - tbb::internal::FastRandom random( (unsigned)(uintptr_t)seed ); - memset( curHits, 0, randomRange * sizeof(uintptr_t) ); -#if TEST_TOTAL_SEQUENCE - memset( totalHits, 0, randomRange * sizeof(uintptr_t) ); -#endif - const uintptr_t seriesLen = randomRange * SeriesBaseLen, - experimentLen = NumSeries * seriesLen; - uintptr_t *curSeries = new uintptr_t[seriesLen], // circular buffer - randsGenerated = 0; - // Initialize statistics - while ( randsGenerated < seriesLen ) { - uintptr_t idx = random.get() % randomRange; - ++curHits[idx]; -#if TEST_TOTAL_SEQUENCE - ++totalHits[idx]; -#endif - curSeries[randsGenerated++] = idx; - } - while ( randsGenerated < experimentLen ) { - for ( uintptr_t j = 0; j < randomRange; ++j ) { - CheckProbability( double(curHits[j])/seriesLen, expectedProbability, j, randomRange ); -#if TEST_TOTAL_SEQUENCE - CheckProbability( double(totalHits[j])/randsGenerated, expectedProbability, j, randomRange ); -#endif - } - --curHits[curSeries[randsGenerated % seriesLen]]; - int idx = random.get() % randomRange; - ++curHits[idx]; -#if TEST_TOTAL_SEQUENCE - ++totalHits[idx]; -#endif - curSeries[randsGenerated++ % seriesLen] = idx; - } - delete [] curSeries; - } - delete [] curHits; -#if TEST_TOTAL_SEQUENCE - delete [] totalHits; -#endif - } -}; - -#include "tbb/tbb_thread.h" - -int TestMain () { - ASSERT( AcceptableDeviation < 100, NULL ); - MinThread = max(MinThread, 2); - MaxThread = max(MinThread, MaxThread); - double NumChecks = double(NumSeeds) * (MaxThread - MinThread + 1) * (MaxThread + MinThread) / 2.0 * (SeriesBaseLen * NumSeries - SeriesBaseLen); - REMARK( "Number of distribution quality checks %g\n", NumChecks ); - NumLowOutliers = NumHighOutliers = 0; - // Parallelism is used in this test only to speed up the long serial checks - // Essentially it is a loop over random number ranges - // Ideally tbb::parallel_for could be used to parallelize the outermost loop - // in CheckDistributionBody, but it is not used to avoid unit test contamination. - int P = tbb::tbb_thread::hardware_concurrency(); - while ( MinThread <= MaxThread ) { - NativeParallelFor( min(P, MaxThread - MinThread + 1), CheckDistributionBody() ); - MinThread += P; - } - double observedProbabilityOfOutliers = (NumLowOutliers + NumHighOutliers) / NumChecks; - if ( observedProbabilityOfOutliers > AcceptableProbabilityOfOutliers ) { - if ( NumLowOutliers ) - REPORT( "Warning: %d cases of too low probability of a given number detected\n", (int)NumLowOutliers ); - if ( NumHighOutliers ) - REPORT( "Warning: %d cases of too high probability of a given number detected\n", (int)NumHighOutliers ); - ASSERT( observedProbabilityOfOutliers <= AcceptableProbabilityOfOutliers, NULL ); - } - return Harness::Done; -} diff --git a/deal.II/contrib/tbb/tbb30_104oss/src/test/test_halt.cpp b/deal.II/contrib/tbb/tbb30_104oss/src/test/test_halt.cpp deleted file mode 100644 index 511d215427..0000000000 --- a/deal.II/contrib/tbb/tbb30_104oss/src/test/test_halt.cpp +++ /dev/null @@ -1,117 +0,0 @@ -/* - Copyright 2005-2010 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. -*/ - -#include -#include -#include -#include -#include "tbb/task.h" -#include "tbb/task_scheduler_init.h" -#include "tbb/tick_count.h" -#include "tbb/parallel_for.h" -#include "tbb/blocked_range.h" -#include "tbb/mutex.h" -#include "tbb/spin_mutex.h" -#include "tbb/queuing_mutex.h" -#include "harness.h" - -using namespace std; -using namespace tbb; - -///////////////////// Parallel methods //////////////////////// - -// *** Serial shared by mutexes *** // -int SharedI = 1, SharedN; -template -class SharedSerialFibBody: NoAssign { - M &mutex; -public: - SharedSerialFibBody( M &m ) : mutex( m ) {} - //! main loop - void operator()( const blocked_range& /*range*/ ) const { - for(;;) { - typename M::scoped_lock lock( mutex ); - if(SharedI >= SharedN) break; - volatile double sum = 7.3; - sum *= 11.17; - ++SharedI; - } - } -}; - -//! Root function -template -void SharedSerialFib(int n) -{ - SharedI = 1; - SharedN = n; - M mutex; - parallel_for( blocked_range(0,4,1), SharedSerialFibBody( mutex ) ); -} - -/////////////////////////// Main //////////////////////////////////////////////////// - -double Tsum = 0; int Tnum = 0; - -typedef void (*MeasureFunc)(int); -//! Measure ticks count in loop [2..n] -void Measure(const char *name, MeasureFunc func, int n) -{ - tick_count t0; - tick_count::interval_t T; - REMARK("%s",name); - t0 = tick_count::now(); - for(int number = 2; number <= n; number++) - func(number); - T = tick_count::now() - t0; - double avg = Tnum? Tsum/Tnum : 1; - if (avg == 0.0) avg = 1; - if(avg * 100 < T.seconds()) { - REPORT("Warning: halting detected (%g sec, av: %g)\n", T.seconds(), avg); - ASSERT(avg * 1000 > T.seconds(), "Too long halting period"); - } else { - Tsum += T.seconds(); Tnum++; - } - REMARK("\t- in %f msec\n", T.seconds()*1000); -} - -int TestMain () { - MinThread = max(2, MinThread); - int NumbersCount = 100; - short recycle = 100; - do { - for(int threads = MinThread; threads <= MaxThread; threads++) { - task_scheduler_init scheduler_init(threads); - REMARK("Threads number is %d\t", threads); - Measure("Shared serial (wrapper mutex)\t", SharedSerialFib, NumbersCount); - //sum = Measure("Shared serial (spin_mutex)", SharedSerialFib, NumbersCount); - //sum = Measure("Shared serial (queuing_mutex)", SharedSerialFib, NumbersCount); - } - } while(--recycle); - return Harness::Done; -} diff --git a/deal.II/contrib/tbb/tbb30_104oss/src/test/test_handle_perror.cpp b/deal.II/contrib/tbb/tbb30_104oss/src/test/test_handle_perror.cpp deleted file mode 100644 index 60a047deac..0000000000 --- a/deal.II/contrib/tbb/tbb30_104oss/src/test/test_handle_perror.cpp +++ /dev/null @@ -1,77 +0,0 @@ -/* - Copyright 2005-2010 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. -*/ - -// Program for basic correctness of handle_perror, which is internal -// to the TBB shared library. - -#include - -#if !TBB_USE_EXCEPTIONS && _MSC_VER - // Suppress "C++ exception handler used, but unwind semantics are not enabled" warning in STL headers - #pragma warning (push) - #pragma warning (disable: 4530) -#endif - -#include - -#if !TBB_USE_EXCEPTIONS && _MSC_VER - #pragma warning (pop) -#endif - -#include "../tbb/tbb_misc.h" -#include "harness.h" - -#if TBB_USE_EXCEPTIONS - -static void TestHandlePerror() { - bool caught = false; - try { - tbb::internal::handle_perror( EAGAIN, "apple" ); - } catch( std::runtime_error& e ) { -#if TBB_USE_EXCEPTIONS - REMARK("caught runtime_exception('%s')\n",e.what()); - ASSERT( memcmp(e.what(),"apple: ",7)==0, NULL ); - ASSERT( strstr(e.what(),"unavailable")!=NULL, "bad error message?" ); -#endif /* TBB_USE_EXCEPTIONS */ - caught = true; - } - ASSERT(caught,NULL); -} - -int TestMain () { - TestHandlePerror(); - return Harness::Done; -} - -#else /* !TBB_USE_EXCEPTIONS */ - -int TestMain () { - return Harness::Skipped; -} - -#endif /* TBB_USE_EXCEPTIONS */ diff --git a/deal.II/contrib/tbb/tbb30_104oss/src/test/test_inits_loop.cpp b/deal.II/contrib/tbb/tbb30_104oss/src/test/test_inits_loop.cpp deleted file mode 100644 index 1836ee2d6a..0000000000 --- a/deal.II/contrib/tbb/tbb30_104oss/src/test/test_inits_loop.cpp +++ /dev/null @@ -1,102 +0,0 @@ -/* - Copyright 2005-2010 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. -*/ - -#if __APPLE__ - -#define HARNESS_CUSTOM_MAIN 1 -#include "harness.h" -#include -#include "tbb/task_scheduler_init.h" - -#include -#include -#include -#include -#include - -bool exec_test(const char *self) { - int status = 1; - pid_t p = fork(); - if(p < 0) { - REPORT("fork error: errno=%d: %s\n", errno, strerror(errno)); - return true; - } - else if(p) { // parent - if(waitpid(p, &status, 0) != p) { - REPORT("wait error: errno=%d: %s\n", errno, strerror(errno)); - return true; - } - if(WIFEXITED(status)) { - if(!WEXITSTATUS(status)) return false; // ok - else REPORT("child has exited with return code 0x%x\n", WEXITSTATUS(status)); - } else { - REPORT("child error 0x%x:%s%s ", status, WIFSIGNALED(status)?" signalled":"", - WIFSTOPPED(status)?" stopped":""); - if(WIFSIGNALED(status)) - REPORT("%s%s", sys_siglist[WTERMSIG(status)], WCOREDUMP(status)?" core dumped":""); - if(WIFSTOPPED(status)) - REPORT("with %d stop-code", WSTOPSIG(status)); - REPORT("\n"); - } - } - else { // child - // reproduces error much often - execl(self, self, "0", NULL); - REPORT("exec fails %s: %d: %s\n", self, errno, strerror(errno)); - exit(2); - } - return true; -} - -HARNESS_EXPORT -int main( int argc, char * argv[] ) { - MinThread = 3000; - ParseCommandLine( argc, argv ); - if( MinThread <= 0 ) { - tbb::task_scheduler_init init( 2 ); // even number required for an error - } else { - for(int i = 0; i; -public: - DataItemWithInheritedNode ( int value ) : DataItemWithInheritedNodeBase(value) {} -}; - -struct DataItemWithMemberNodeBase { - int m_Data; -public: - // Cannot be used by member_intrusive_list to form lists of objects derived from DataItemBase - intrusive_list_node m_BaseNode; - - DataItemWithMemberNodeBase ( int value ) : m_Data(value) {} - - int Data() const { return m_Data; } -}; - -class DataItemWithMemberNodes : public VerificationBase, public DataItemWithMemberNodeBase { -public: - intrusive_list_node m_Node; - - DataItemWithMemberNodes ( int value ) : DataItemWithMemberNodeBase(value) {} -}; - -typedef tbb::internal::intrusive_list IntrusiveList1; -typedef tbb::internal::memptr_intrusive_list IntrusiveList2; -typedef tbb::internal::memptr_intrusive_list IntrusiveList3; - -const int NumElements = 256 * 1024; - -//! Iterates through the list forward and backward checking the validity of values stored by the list nodes -template -void CheckListNodes ( List& il, int valueStep ) { - int i; - Iterator it = il.begin(); - for ( i = valueStep - 1; it != il.end(); ++it, i += valueStep ) { - ASSERT( it->Data() == i, "Unexpected node value while iterating forward" ); - ASSERT( (*it).m_Canary == NoliMeTangere, "Memory corruption" ); - } - ASSERT( i == NumElements + valueStep - 1, "Wrong number of list elements while iterating forward" ); - it = il.end(); - for ( i = NumElements - 1, it--; it != il.end(); --it, i -= valueStep ) { - ASSERT( (*it).Data() == i, "Unexpected node value while iterating backward" ); - ASSERT( it->m_Canary == NoliMeTangere, "Memory corruption" ); - } - ASSERT( i == -1, "Wrong number of list elements while iterating backward" ); -} - -template -void TestListOperations () { - typedef typename List::iterator iterator; - List il; - for ( int i = NumElements - 1; i >= 0; --i ) - il.push_front( *new Item(i) ); - CheckListNodes( il, 1 ); - iterator it = il.begin(); - for ( ; it != il.end(); ++it ) { - Item &item = *it; - it = il.erase( it ); - delete &item; - } - CheckListNodes( il, 2 ); - for ( it = il.begin(); it != il.end(); ++it ) { - Item &item = *it; - il.remove( *it++ ); - delete &item; - } - CheckListNodes( il, 4 ); -} - -#include "harness_bad_expr.h" - -template -void TestListAssertions () { -#if TRY_BAD_EXPR_ENABLED - tbb::set_assertion_handler( AssertionFailureHandler ); - List il1, il2; - Item n1(1), n2(2), n3(3); - il1.push_front(n1); - TRY_BAD_EXPR( il2.push_front(n1), "only one intrusive list" ); - TRY_BAD_EXPR( il1.push_front(n1), "only one intrusive list" ); - il2.push_front(n2); - TRY_BAD_EXPR( il1.remove(n3), "not in the list" ); - tbb::set_assertion_handler( NULL ); -#endif /* TRY_BAD_EXPR_ENABLED */ -} -#endif /* __TBB_ARENA_PER_MASTER */ - -int TestMain () { -#if __TBB_ARENA_PER_MASTER - TestListOperations(); - TestListOperations(); - TestListOperations(); - TestListAssertions(); - TestListAssertions(); - TestListAssertions(); - return Harness::Done; -#else - return Harness::Skipped; -#endif /* __TBB_ARENA_PER_MASTER */ -} diff --git a/deal.II/contrib/tbb/tbb30_104oss/src/test/test_ittnotify.cpp b/deal.II/contrib/tbb/tbb30_104oss/src/test/test_ittnotify.cpp deleted file mode 100644 index c92e45b704..0000000000 --- a/deal.II/contrib/tbb/tbb30_104oss/src/test/test_ittnotify.cpp +++ /dev/null @@ -1,98 +0,0 @@ -/* - Copyright 2005-2010 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. -*/ - -#if !TBB_USE_THREADING_TOOLS - #define TBB_USE_THREADING_TOOLS 1 -#endif - -#include "harness.h" - -#if DO_ITT_NOTIFY - -#include "tbb/spin_mutex.h" -#include "tbb/spin_rw_mutex.h" -#include "tbb/queuing_rw_mutex.h" -#include "tbb/queuing_mutex.h" -#include "tbb/mutex.h" -#include "tbb/recursive_mutex.h" -#include "tbb/parallel_for.h" -#include "tbb/blocked_range.h" -#include "tbb/task_scheduler_init.h" - - -#include "../tbb/itt_notify.h" - - -template -class WorkEmulator: NoAssign { - M& m_mutex; - static volatile size_t s_anchor; -public: - void operator()( tbb::blocked_range& range ) const { - for( size_t i=range.begin(); i!=range.end(); ++i ) { - typename M::scoped_lock lock(m_mutex); - for ( size_t j = 0; j!=range.end(); ++j ) - s_anchor = (s_anchor - i) / 2 + (s_anchor + j) / 2; - } - } - WorkEmulator( M& mutex ) : m_mutex(mutex) {} -}; - -template -volatile size_t WorkEmulator::s_anchor = 0; - - -template -void Test( const char * name ) { - REMARK("%s time = ",name); - M mtx; - tbb::profiling::set_name(mtx, name); - - const int n = 10000; - tbb::parallel_for( tbb::blocked_range(0,n,n/100), WorkEmulator(mtx) ); -} - - #define TEST_MUTEX(type, name) Test( name ) - -#endif /* !DO_ITT_NOTIFY */ - -int TestMain () { -#if DO_ITT_NOTIFY - for( int p=MinThread; p<=MaxThread; ++p ) { - REMARK( "testing with %d workers\n", p ); - tbb::task_scheduler_init init( p ); - TEST_MUTEX( spin_mutex, "Spin Mutex" ); - TEST_MUTEX( queuing_mutex, "Queuing Mutex" ); - TEST_MUTEX( queuing_rw_mutex, "Queuing RW Mutex" ); - TEST_MUTEX( spin_rw_mutex, "Spin RW Mutex" ); - } - return Harness::Done; -#else /* !DO_ITT_NOTIFY */ - return Harness::Skipped; -#endif /* !DO_ITT_NOTIFY */ -} diff --git a/deal.II/contrib/tbb/tbb30_104oss/src/test/test_lambda.cpp b/deal.II/contrib/tbb/tbb30_104oss/src/test/test_lambda.cpp deleted file mode 100644 index 895887781b..0000000000 --- a/deal.II/contrib/tbb/tbb30_104oss/src/test/test_lambda.cpp +++ /dev/null @@ -1,240 +0,0 @@ -/* - Copyright 2005-2010 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. -*/ - -#define NOMINMAX -#include "tbb/tbb.h" -#include "tbb/combinable.h" -#include - -#if !TBB_USE_EXCEPTIONS && _MSC_VER - // Suppress "C++ exception handler used, but unwind semantics are not enabled" warning in STL headers - #pragma warning (push) - #pragma warning (disable: 4530) -#endif - -#include - -#if !TBB_USE_EXCEPTIONS && _MSC_VER - #pragma warning (pop) -#endif - -using namespace std; -using namespace tbb; - -typedef pair max_element_t; - -void f(int val, int *arr, int start, int stop) { - for (int i=start; i<=stop; ++i) { - arr[i] = val; - } -} - -#include "harness.h" - -int Fib(int n) { - if( n<2 ) { - return n; - } else { - int x=0, y=0; - task_group g; -#if __TBB_LAMBDAS_PRESENT - g.run( [&]{x=Fib(n-1);} ); // spawn a task - g.run( [&]{y=Fib(n-2);} ); // spawn another task - g.wait(); // wait for both tasks to complete -#endif - return x+y; - } -} - -#include "harness_report.h" -#include "harness_assert.h" - -int TestMain () { -#if __TBB_LAMBDAS_PRESENT - const int N = 1000; - const int Grainsize = N/1000; - int a[N]; - ASSERT( MinThread>=1, "Error: Number of threads must be positive.\n"); - - for(int p=MinThread; p<=MaxThread; ++p) { - task_scheduler_init init(p); - - REMARK("Running lambda expression tests on %d threads...\n", p); - - //test parallel_for - REMARK("Testing parallel_for... "); - parallel_for(blocked_range(0,N,Grainsize), - [&] (blocked_range& r) { - for (int i=r.begin(); i!=r.end(); ++i) a[i] = i; - }); - ASSERT(a[0]==0 && a[N-1]==N-1, "parallel_for w/lambdas failed.\n"); - REMARK("passed.\n"); - - //test parallel_reduce - REMARK("Testing parallel_reduce... "); - int sum = parallel_reduce(blocked_range(0,N,Grainsize), int(0), - [&] (blocked_range& r, int current_sum) -> int { - for (int i=r.begin(); i!=r.end(); ++i) - current_sum += a[i]*(1000-i); - return current_sum; - }, - [] (const int x1, const int x2) { - return x1+x2; - } ); - - max_element_t max_el = - parallel_reduce(blocked_range(0,N,Grainsize), make_pair(a[0], 0), - [&] (blocked_range& r, max_element_t current_max) - -> max_element_t { - for (int i=r.begin(); i!=r.end(); ++i) - if (a[i]>current_max.first) - current_max = make_pair(a[i], i); - return current_max; - }, - [] (const max_element_t x1, const max_element_t x2) { - return (x1.first>x2.first)?x1:x2; - }); - ASSERT(sum==166666500 && max_el.first==999 && max_el.second==999, - "parallel_reduce w/lambdas failed.\n"); - REMARK("passed.\n"); - - //test parallel_do - REMARK("Testing parallel_do... "); - list s; - s.push_back(0); - - parallel_do(s.begin(), s.end(), - [&](int foo, parallel_do_feeder& feeder) { - if (foo == 42) return; - else if (foo>42) { - s.push_back(foo-3); - feeder.add(foo-3); - } else { - s.push_back(foo+5); - feeder.add(foo+5); - } - }); - ASSERT(s.back()==42, "parallel_do w/lambda failed.\n"); - REMARK("passed.\n"); - - //test parallel_invoke - REMARK("Testing parallel_invoke... "); - parallel_invoke([&]{ f(2, a, 0, N/3); }, - [&]{ f(1, a, N/3+1, 2*(N/3)); }, - [&]{ f(0, a, 2*(N/3)+1, N-1); }); - ASSERT(a[0]==2.0 && a[N-1]==0.0, "parallel_invoke w/lambda failed.\n"); - REMARK("passed.\n"); - - //test tbb_thread - REMARK("Testing tbb_thread... "); - tbb_thread::id myId; - tbb_thread myThread([](int x, int y) { - ASSERT(x==42 && y==64, "tbb_thread w/lambda failed.\n"); - REMARK("passed.\n"); - }, 42, 64); - myThread.join(); - - // test task_group - REMARK("Testing task_group... "); - int result; - result = Fib(32); - ASSERT(result==2178309, "task_group w/lambda failed.\n"); - REMARK("passed.\n"); - - // Reset array a to index values - parallel_for(blocked_range(0,N,Grainsize), - [&] (blocked_range& r) { - for (int i=r.begin(); i!=r.end(); ++i) a[i] = i; - }); - // test parallel_sort - REMARK("Testing parallel_sort... "); - int pivot = 42; - - // sort nearest by increasing distance from pivot - parallel_sort(a, a+N, - [&](int x, int y) { return(abs(pivot-x) < abs(pivot-y)); }); - ASSERT(a[0]==42 && a[N-1]==N-1, "parallel_sort w/lambda failed.\n"); - REMARK("passed.\n"); - - //test combinable - REMARK("Testing combinable... "); - combinable > minmax_c([&]() { return std::make_pair(a[0], a[0]); } ); - - parallel_for(blocked_range(0,N), - [&] (const blocked_range &r) { - std::pair& mmr = minmax_c.local(); - for(int i=r.begin(); i!=r.end(); ++i) { - if (mmr.first > a[i]) mmr.first = a[i]; - if (mmr.second < a[i]) mmr.second = a[i]; - } - }); - minmax_c.combine_each([](std::pair x) { - int sum; - sum = x.first + x.second; - }); - std::pair minmax_result_c; - minmax_result_c = - minmax_c.combine([](std::pair x, std::pair y) { - return std::make_pair(x.firsty.second?x.second:y.second); - }); - ASSERT(minmax_result_c.first==0 && minmax_result_c.second==999, - "combinable w/lambda failed.\n"); - REMARK("passed.\n"); - - //test enumerable_thread_specific - REMARK("Testing enumerable_thread_specific... "); - enumerable_thread_specific< std::pair > minmax_ets([&]() { return std::make_pair(a[0], a[0]); } ); - - parallel_for(blocked_range(0,N), - [&] (const blocked_range &r) { - std::pair& mmr = minmax_ets.local(); - for(int i=r.begin(); i!=r.end(); ++i) { - if (mmr.first > a[i]) mmr.first = a[i]; - if (mmr.second < a[i]) mmr.second = a[i]; - } - }); - minmax_ets.combine_each([](std::pair x) { - int sum; - sum = x.first + x.second; - }); - std::pair minmax_result_ets; - minmax_result_ets = - minmax_ets.combine([](std::pair x, std::pair y) { - return std::make_pair(x.firsty.second?x.second:y.second); - }); - ASSERT(minmax_result_ets.first==0 && minmax_result_ets.second==999, - "enumerable_thread_specific w/lambda failed.\n"); - REMARK("passed.\n"); - } - return Harness::Done; -#else - return Harness::Skipped; -#endif /* !__TBB_LAMBDAS_PRESENT */ -} diff --git a/deal.II/contrib/tbb/tbb30_104oss/src/test/test_malloc_atexit.cpp b/deal.II/contrib/tbb/tbb30_104oss/src/test/test_malloc_atexit.cpp deleted file mode 100644 index ad742e25cd..0000000000 --- a/deal.II/contrib/tbb/tbb30_104oss/src/test/test_malloc_atexit.cpp +++ /dev/null @@ -1,94 +0,0 @@ -/* - Copyright 2005-2010 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. -*/ - -/* Regression test against bug in TBB allocator, manifested when - dynamic library calls atexit or register dtors of static objects. - If the allocator is not initialized yet, we can got deadlock, - because allocator library has static object dtors as well, they - registred during allocator initialization, and atexit is protected - by non-recursive mutex in some GLIBCs. - */ - -#if _USRDLL - -#include - -#if _WIN32||_WIN64 -// isMallocOverloaded must be defined in DLL to linker not drop the dependence -// to the DLL. -extern __declspec(dllexport) bool isMallocOverloaded(); - -bool isMallocOverloaded() -{ - return true; -} - -#else - -#include - -bool isMallocOverloaded() -{ - return dlsym(RTLD_DEFAULT, "__TBB_malloc_proxy"); -} - -#endif - -#ifndef _PGO_INSTRUMENT -void dummyFunction() {} - -class Foo { -public: - Foo() { - // add a lot of exit handlers to cause memory allocation - for (int i=0; i<1024; i++) - atexit(dummyFunction); - } -}; - -static Foo f; -#endif - -#else // _USRDLL -#include "harness.h" - -#if _WIN32||_WIN64 -extern __declspec(dllimport) -#endif -bool isMallocOverloaded(); - -int TestMain () { -#ifdef _PGO_INSTRUMENT - REPORT("Known issue: test_malloc_atexit hangs if compiled with -prof-genx\n"); - return Harness::Skipped; -#else - return isMallocOverloaded()? Harness::Done : Harness::Skipped; -#endif -} - -#endif // _USRDLL diff --git a/deal.II/contrib/tbb/tbb30_104oss/src/test/test_malloc_compliance.cpp b/deal.II/contrib/tbb/tbb30_104oss/src/test/test_malloc_compliance.cpp deleted file mode 100644 index e91643bba5..0000000000 --- a/deal.II/contrib/tbb/tbb30_104oss/src/test/test_malloc_compliance.cpp +++ /dev/null @@ -1,1015 +0,0 @@ -/* - Copyright 2005-2010 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. -*/ - -const int MByte = 1048576; //1MB -bool __tbb_test_errno = false; - -/* _WIN32_WINNT should be defined at the very beginning, - because other headers might include -*/ - -#if _WIN32 || _WIN64 && !__MINGW64__ -#undef _WIN32_WINNT -#define _WIN32_WINNT 0x0500 -#include "tbb/machine/windows_api.h" -#include -#include "harness_report.h" - -void limitMem( int limit ) -{ - static HANDLE hJob = NULL; - JOBOBJECT_EXTENDED_LIMIT_INFORMATION jobInfo; - - jobInfo.BasicLimitInformation.LimitFlags = JOB_OBJECT_LIMIT_PROCESS_MEMORY; - jobInfo.ProcessMemoryLimit = limit? limit*MByte : 2*1024LL*MByte; - if (NULL == hJob) { - if (NULL == (hJob = CreateJobObject(NULL, NULL))) { - REPORT("Can't assign create job object: %ld\n", GetLastError()); - exit(1); - } - if (0 == AssignProcessToJobObject(hJob, GetCurrentProcess())) { - REPORT("Can't assign process to job object: %ld\n", GetLastError()); - exit(1); - } - } - if (0 == SetInformationJobObject(hJob, JobObjectExtendedLimitInformation, - &jobInfo, sizeof(jobInfo))) { - REPORT("Can't set limits: %ld\n", GetLastError()); - exit(1); - } -} -// Do not test errno with static VC runtime -#else -#include -#include -#include -#include -#include // uint64_t on FreeBSD, needed for rlim_t -#include "harness_report.h" - -void limitMem( int limit ) -{ - rlimit rlim; - rlim.rlim_cur = limit? limit*MByte : (rlim_t)RLIM_INFINITY; - rlim.rlim_max = (rlim_t)RLIM_INFINITY; - int ret = setrlimit(RLIMIT_AS,&rlim); - if (0 != ret) { - REPORT("Can't set limits: errno %d\n", errno); - exit(1); - } -} -#endif - -#define ASSERT_ERRNO(cond, msg) ASSERT( !__tbb_test_errno || (cond), msg ) -#define CHECK_ERRNO(cond) (__tbb_test_errno && (cond)) - -#include -#include -#define __TBB_NO_IMPLICIT_LINKAGE 1 -#include "tbb/scalable_allocator.h" -#include "tbb/tbb_machine.h" - -#define HARNESS_CUSTOM_MAIN 1 -#include "harness.h" -#include "harness_barrier.h" -#if __linux__ -#include // uintptr_t -#endif -#if _WIN32 || _WIN64 -#include // _aligned_(malloc|free|realloc) -#endif - -#if !TBB_USE_EXCEPTIONS && _MSC_VER - // Suppress "C++ exception handler used, but unwind semantics are not enabled" warning in STL headers - #pragma warning (push) - #pragma warning (disable: 4530) -#endif - -#include - -#if !TBB_USE_EXCEPTIONS && _MSC_VER - #pragma warning (pop) -#endif - -const size_t COUNT_ELEM_CALLOC = 2; -const int COUNT_TESTS = 1000; -const int COUNT_ELEM = 25000; -const size_t MAX_SIZE = 1000; -const int COUNTEXPERIMENT = 10000; - -const char strError[]="failed"; -const char strOk[]="done"; - -typedef unsigned int UINT; -typedef unsigned char UCHAR; -typedef unsigned long DWORD; -typedef unsigned char BYTE; - - -typedef void* TestMalloc(size_t size); -typedef void* TestCalloc(size_t num, size_t size); -typedef void* TestRealloc(void* memblock, size_t size); -typedef void TestFree(void* memblock); -typedef int TestPosixMemalign(void **memptr, size_t alignment, size_t size); -typedef void* TestAlignedMalloc(size_t size, size_t alignment); -typedef void* TestAlignedRealloc(void* memblock, size_t size, size_t alignment); -typedef void TestAlignedFree(void* memblock); - -TestMalloc* Tmalloc; -TestCalloc* Tcalloc; -TestRealloc* Trealloc; -TestFree* Tfree; -TestAlignedFree* Taligned_free; -// call alignment-related function via pointer and check result's alignment -int Tposix_memalign(void **memptr, size_t alignment, size_t size); -void* Taligned_malloc(size_t size, size_t alignment); -void* Taligned_realloc(void* memblock, size_t size, size_t alignment); - -// pointers to alignment-related functions used while testing -TestPosixMemalign* Rposix_memalign; -TestAlignedMalloc* Raligned_malloc; -TestAlignedRealloc* Raligned_realloc; - -bool error_occurred = false; - -#if __APPLE__ -// Tests that use the variable are skipped on Mac OS* X -#else -static bool perProcessLimits = true; -#endif - -const size_t POWERS_OF_2 = 20; - -#if __linux__ && __ia64__ -/* Can't use Intel compiler intrinsic due to internal error reported by - 10.1 compiler */ -pthread_mutex_t counter_mutex = PTHREAD_MUTEX_INITIALIZER; - -int32_t __TBB_machine_fetchadd4__TBB_full_fence (volatile void *ptr, int32_t value) -{ - pthread_mutex_lock(&counter_mutex); - int32_t result = *(int32_t*)ptr; - *(int32_t*)ptr = result + value; - pthread_mutex_unlock(&counter_mutex); - return result; -} - -void __TBB_machine_pause(int32_t /*delay*/) {} - -#elif (_WIN32||_WIN64) && defined(_M_AMD64) && !__MINGW64__ - -void __TBB_machine_pause(__int32 /*delay*/ ) {} - -#endif - -struct MemStruct -{ - void* Pointer; - UINT Size; - - MemStruct() : Pointer(NULL), Size(0) {} - MemStruct(void* Pointer, UINT Size) : Pointer(Pointer), Size(Size) {} -}; - -class CMemTest: NoAssign -{ - UINT CountErrors; - bool FullLog; - Harness::SpinBarrier *limitBarrier; - static bool firstTime; - -public: - CMemTest(Harness::SpinBarrier *limitBarrier, bool isVerbose=false) : - CountErrors(0), limitBarrier(limitBarrier) - { - srand((UINT)time(NULL)); - FullLog=isVerbose; - rand(); - } - void InvariantDataRealloc(bool aligned); //realloc does not change data - void NULLReturn(UINT MinSize, UINT MaxSize, int total_threads); // NULL pointer + check errno - void UniquePointer(); // unique pointer - check with padding - void AddrArifm(); // unique pointer - check with pointer arithmetic - bool ShouldReportError(); - void Free_NULL(); // - void Zerofilling(); // check if arrays are zero-filled - void TestAlignedParameters(); - void RunAllTests(int total_threads); - ~CMemTest() {} -}; - -class Limit { - int limit; -public: - Limit(int limit) : limit(limit) {} - void operator() () const { - limitMem(limit); - } -}; - -int argC; -char** argV; - -struct RoundRobin: NoAssign { - const long number_of_threads; - mutable CMemTest test; - - RoundRobin( long p, Harness::SpinBarrier *limitBarrier, bool verbose ) : - number_of_threads(p), test(limitBarrier, verbose) {} - void operator()( int /*id*/ ) const - { - test.RunAllTests(number_of_threads); - } -}; - -bool CMemTest::firstTime = true; - -static void setSystemAllocs() -{ - Tmalloc=malloc; - Trealloc=realloc; - Tcalloc=calloc; - Tfree=free; -#if (_WIN32 || _WIN64) && !__MINGW64__ && !__MINGW32__ - Raligned_malloc=_aligned_malloc; - Raligned_realloc=_aligned_realloc; - Taligned_free=_aligned_free; - Rposix_memalign=0; -#elif __APPLE__ || __sun || __MINGW64__ || __MINGW32__ // Max OS X MinGW and Solaris don't have posix_memalign - Raligned_malloc=0; - Raligned_realloc=0; - Taligned_free=0; - Rposix_memalign=0; -#else - Raligned_malloc=0; - Raligned_realloc=0; - Taligned_free=0; - Rposix_memalign=posix_memalign; -#endif -} - -// check that realloc works as free and as malloc -void ReallocParam() -{ - const int ITERS = 1000; - int i; - void *bufs[ITERS]; - - bufs[0] = Trealloc(NULL, 30*MByte); - ASSERT(bufs[0], "Can't get memory to start the test."); - - for (i=1; i=MinThread; --p ) { - REMARK("testing with %d threads\n", p ); - Harness::SpinBarrier *barrier = new Harness::SpinBarrier(p); - NativeParallelFor( p, RoundRobin(p, barrier, Verbose) ); - delete barrier; - } - if( !error_occurred ) - REPORT("done\n"); - return 0; -} - -struct TestStruct -{ - DWORD field1:2; - DWORD field2:6; - double field3; - UCHAR field4[100]; - TestStruct* field5; -// std::string field6; - std::vector field7; - double field8; - bool IsZero() { - int wordSz = sizeof(TestStruct) / sizeof(intptr_t); - int tailSz = sizeof(TestStruct) % sizeof(intptr_t); - - intptr_t *buf =(intptr_t*)this; - char *bufTail =(char*) (buf+wordSz); - - for (int i=0; i0 ) ; - //REPORT("end check\n"); -} - -struct PtrSize { - void *ptr; - size_t size; -}; - -static int cmpAddrs(const void *p1, const void *p2) -{ - const PtrSize *a = (const PtrSize *)p1; - const PtrSize *b = (const PtrSize *)p2; - - return a->ptr < b->ptr ? -1 : ( a->ptr == b->ptr ? 0 : 1); -} - -void CMemTest::AddrArifm() -{ - PtrSize *arr = (PtrSize*)Tmalloc(COUNT_ELEM*sizeof(PtrSize)); - - if (FullLog) REPORT("\nUnique pointer using Address arithmetics\n"); - if (FullLog) REPORT("malloc...."); - ASSERT(arr, NULL); - for (int i=0; iIsZero()) - { - CountErrors++; - if (ShouldReportError()) REPORT("detect nonzero element at TestStruct\n"); - } - } - Tfree(TSMas); - } - if (CountErrors) REPORT("%s\n",strError); - else if (FullLog) REPORT("%s\n",strOk); - error_occurred |= ( CountErrors>0 ) ; -} - -#if !__APPLE__ -void CMemTest::NULLReturn(UINT MinSize, UINT MaxSize, int total_threads) -{ - // find size to guarantee getting NULL for 1024 B allocations - const int MAXNUM_1024 = (200+50)*1024; - - std::vector PointerList; - void *tmp; - CountErrors=0; - int CountNULL, num_1024; - if (FullLog) REPORT("\nNULL return & check errno:\n"); - UINT Size; - Limit limit_200M(200*total_threads), no_limit(0); - void **buf_1024 = (void**)Tmalloc(MAXNUM_1024*sizeof(void*)); - - ASSERT(buf_1024, NULL); - /* We must have space for pointers when memory limit is hit. - Reserve enough for the worst case. - */ - PointerList.reserve(200*MByte/MinSize); - - /* There is a bug in the specific verion of GLIBC (2.5-12) shipped - with RHEL5 that leads to erroneous working of the test - on Intel64 and IPF systems when setrlimit-related part is enabled. - Switching to GLIBC 2.5-18 from RHEL5.1 resolved the issue. - */ - if (perProcessLimits) - limitBarrier->wait(limit_200M); - else - limitMem(200); - - /* regression test against the bug in allocator when it dereference NULL - while lack of memory - */ - for (num_1024=0; num_10240 ) ; - - CountErrors=0; - //calloc - if (FullLog) REPORT("calloc...."); - CountNULL = 0; - while (CountNULL==0) - for (int j=0; j0 ) ; - CountErrors=0; - if (FullLog) REPORT("realloc...."); - CountNULL = 0; - if (PointerList.size() > 0) - while (CountNULL==0) - for (size_t i=0; i<(size_t)COUNT_TESTS && i0 ) ; - for (UINT i=0; iwait(no_limit); - else - limitMem(0); -} -#endif /* #if __APPLE__ */ - -void CMemTest::UniquePointer() -{ - CountErrors=0; - int **MasPointer = (int **)Tmalloc(sizeof(int*)*COUNT_ELEM); - size_t *MasCountElem = (size_t*)Tmalloc(sizeof(size_t)*COUNT_ELEM); - if (FullLog) REPORT("\nUnique pointer using 0\n"); - ASSERT(MasCountElem && MasPointer, NULL); - // - //------------------------------------------------------- - //malloc - for (int i=0; i0 ) ; - //---------------------------------------------------------- - //calloc - for (int i=0; i0 ) ; - //--------------------------------------------------------- - //realloc - CountErrors=0; - for (int i=0; i0 ) ; - for (int i=0; i0 ) ; -} - -void CMemTest::TestAlignedParameters() -{ - void *memptr; - int ret; - - if (Rposix_memalign) { - // alignment isn't power of 2 - for (int bad_align=3; bad_align<16; bad_align++) - if (bad_align&(bad_align-1)) { - ret = Tposix_memalign(NULL, bad_align, 100); - ASSERT(EINVAL==ret, NULL); - } - - memptr = &ret; - ret = Tposix_memalign(&memptr, 5*sizeof(void*), 100); - ASSERT(memptr == &ret, - "memptr should not be changed after unsuccesful call"); - ASSERT(EINVAL==ret, NULL); - - // alignment is power of 2, but not a multiple of sizeof(void *), - // we expect that sizeof(void*) > 2 - ret = Tposix_memalign(NULL, 2, 100); - ASSERT(EINVAL==ret, NULL); - } - if (Raligned_malloc) { - // alignment isn't power of 2 - for (int bad_align=3; bad_align<16; bad_align++) - if (bad_align&(bad_align-1)) { - memptr = Taligned_malloc(100, bad_align); - ASSERT(NULL==memptr, NULL); - ASSERT_ERRNO(EINVAL==errno, NULL); - } - - // size is zero - memptr = Taligned_malloc(0, 16); - ASSERT(NULL==memptr, "size is zero, so must return NULL"); - ASSERT_ERRNO(EINVAL==errno, NULL); - } - if (Taligned_free) { - // NULL pointer is OK to free - errno = 0; - Taligned_free(NULL); - /* As there is no return value for free, strictly speaking we can't - check errno here. But checked implementations obey the assertion. - */ - ASSERT_ERRNO(0==errno, NULL); - } - if (Raligned_realloc) { - for (int i=1; i<20; i++) { - // checks that calls work correctly in presence of non-zero errno - errno = i; - void *ptr = Taligned_malloc(i*10, 128); - ASSERT(NULL!=ptr, NULL); - ASSERT_ERRNO(0!=errno, NULL); - // if size is zero and pointer is not NULL, works like free - memptr = Taligned_realloc(ptr, 0, 64); - ASSERT(NULL==memptr, NULL); - ASSERT_ERRNO(0!=errno, NULL); - } - // alignment isn't power of 2 - for (int bad_align=3; bad_align<16; bad_align++) - if (bad_align&(bad_align-1)) { - void *ptr = &bad_align; - memptr = Taligned_realloc(&ptr, 100, bad_align); - ASSERT(NULL==memptr, NULL); - ASSERT(&bad_align==ptr, NULL); - ASSERT_ERRNO(EINVAL==errno, NULL); - } - } -} - -void CMemTest::RunAllTests(int total_threads) -{ - Zerofilling(); - Free_NULL(); - InvariantDataRealloc(/*aligned=*/false); - if (Raligned_realloc) - InvariantDataRealloc(/*aligned=*/true); - TestAlignedParameters(); -#if __APPLE__ - REPORT("Known issue: some tests are skipped on Mac OS* X\n"); -#else - UniquePointer(); - AddrArifm(); -#if !__TBB_MIC_NATIVE - NULLReturn(1*MByte,100*MByte,total_threads); -#endif -#endif - if (FullLog) REPORT("All tests ended\nclearing memory..."); -} diff --git a/deal.II/contrib/tbb/tbb30_104oss/src/test/test_malloc_init_shutdown.cpp b/deal.II/contrib/tbb/tbb30_104oss/src/test/test_malloc_init_shutdown.cpp deleted file mode 100644 index 92a69bcbe6..0000000000 --- a/deal.II/contrib/tbb/tbb30_104oss/src/test/test_malloc_init_shutdown.cpp +++ /dev/null @@ -1,150 +0,0 @@ -/* - Copyright 2005-2010 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. -*/ - -#include "tbb/scalable_allocator.h" -#include "tbb/atomic.h" -#include "tbb/aligned_space.h" -#include "../tbb/tbb_assert_impl.h" - -#if _WIN64 && defined(_M_AMD64) && !__MINGW64__ -void __TBB_machine_pause(__int32 /*delay*/ ) {} -#elif __linux__ && __ia64__ -#include - -pthread_mutex_t counter_mutex = PTHREAD_MUTEX_INITIALIZER; - -int32_t __TBB_machine_fetchadd4__TBB_full_fence (volatile void *ptr, int32_t value) -{ - pthread_mutex_lock(&counter_mutex); - int32_t result = *(int32_t*)ptr; - *(int32_t*)ptr = result + value; - pthread_mutex_unlock(&counter_mutex); - return result; -} - -void __TBB_machine_pause(int32_t /*delay*/) {} -#endif - -#include "harness.h" -#include "harness_barrier.h" - -tbb::atomic FinishedTasks; -const int MaxTasks = 16; - -/*--------------------------------------------------------------------*/ -// The regression test against a bug triggered when malloc initialization -// and thread shutdown were called simultaneously, in which case -// Windows dynamic loader lock and allocator initialization/termination lock -// were taken in different order. - -class TestFunc1 { - Harness::SpinBarrier* my_barr; -public: - TestFunc1 (Harness::SpinBarrier& barr) : my_barr(&barr) {} - void operator() (bool do_malloc) const { - my_barr->wait(); - if (do_malloc) scalable_malloc(10); - ++FinishedTasks; - } -}; - -typedef NativeParallelForTask TestTask1; - -void Test1 () { - int NTasks = min(MaxTasks, max(2, MaxThread)); - Harness::SpinBarrier barr(NTasks); - TestFunc1 tf(barr); - FinishedTasks = 0; - tbb::aligned_space tasks; - - for(int i=0; istart(); - } - - Harness::Sleep(1000); // wait a second :) - ASSERT( FinishedTasks==NTasks, "Some threads appear to deadlock" ); - - for(int i=0; iwait_to_finish(); - t->~TestTask1(); - } -} - -/*--------------------------------------------------------------------*/ -// The regression test against a bug when cross-thread deallocation -// caused livelock at thread shutdown. - -void* ptr = NULL; - -class TestFunc2a { - Harness::SpinBarrier* my_barr; -public: - TestFunc2a (Harness::SpinBarrier& barr) : my_barr(&barr) {} - void operator() (int) const { - ptr = scalable_malloc(8); - my_barr->wait(); - ++FinishedTasks; - } -}; - -typedef NativeParallelForTask TestTask2a; - -class TestFunc2b: NoAssign { - Harness::SpinBarrier* my_barr; - TestTask2a& my_ward; -public: - TestFunc2b (Harness::SpinBarrier& barr, TestTask2a& t) : my_barr(&barr), my_ward(t) {} - void operator() (int) const { - tbb::internal::spin_wait_while_eq(ptr, (void*)NULL); - scalable_free(ptr); - my_barr->wait(); - my_ward.wait_to_finish(); - ++FinishedTasks; - } -}; -void Test2() { - Harness::SpinBarrier barr(2); - TestFunc2a func2a(barr); - TestTask2a t2a(0, func2a); - TestFunc2b func2b(barr, t2a); - NativeParallelForTask t2b(1, func2b); - FinishedTasks = 0; - t2a.start(); t2b.start(); - Harness::Sleep(1000); // wait a second :) - ASSERT( FinishedTasks==2, "Threads appear to deadlock" ); - t2b.wait_to_finish(); // t2a is monitored by t2b -} - -int TestMain () { - Test1(); // requires malloc initialization so should be first - Test2(); - return Harness::Done; -} diff --git a/deal.II/contrib/tbb/tbb30_104oss/src/test/test_malloc_lib_unload.cpp b/deal.II/contrib/tbb/tbb30_104oss/src/test/test_malloc_lib_unload.cpp deleted file mode 100644 index fb8bc00826..0000000000 --- a/deal.II/contrib/tbb/tbb30_104oss/src/test/test_malloc_lib_unload.cpp +++ /dev/null @@ -1,150 +0,0 @@ -/* - Copyright 2005-2010 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. -*/ - - -#include -#if _WIN32 || _WIN64 -#include "tbb/machine/windows_api.h" -#else -#include -#endif -#include "tbb/tbb_stddef.h" -#define HARNESS_NO_PARSE_COMMAND_LINE 1 -#include "harness.h" -#include "harness_memory.h" - -#if TBB_USE_DEBUG -#define SUFFIX1 "_debug" -#define SUFFIX2 -#else -#define SUFFIX1 -#define SUFFIX2 "_debug" -#endif /* TBB_USE_DEBUG */ - -#if _WIN32||_WIN64 -#define PREFIX -#define EXT ".dll" -#else -#define PREFIX "lib" -#if __APPLE__ -#define EXT ".dylib" -#elif __linux__ -#define EXT __TBB_STRING(.so.TBB_COMPATIBLE_INTERFACE_VERSION) -#elif __FreeBSD__ || __sun || _AIX -#define EXT ".so" -#else -#error Unknown OS -#endif -#endif - -// Form the names of the TBB memory allocator binaries. -#define MALLOCLIB_NAME1 PREFIX "tbbmalloc" SUFFIX1 EXT -#define MALLOCLIB_NAME2 PREFIX "tbbmalloc" SUFFIX2 EXT - -#if _WIN32 || _WIN64 -#define LIBRARY_HANDLE HMODULE -#define LOAD_LIBRARY(name) LoadLibrary((name)) -#else -#define LIBRARY_HANDLE void* -#define LOAD_LIBRARY(name) dlopen((name), RTLD_NOW|RTLD_GLOBAL) -#endif - -struct Run { - void operator()( int /*id*/ ) const { - void* (*malloc_ptr)(std::size_t); - void (*free_ptr)(void*); - - const char* actual_name; - LIBRARY_HANDLE lib = LOAD_LIBRARY(actual_name = MALLOCLIB_NAME1); - if (!lib) lib = LOAD_LIBRARY(actual_name = MALLOCLIB_NAME2); - if (!lib) { - REPORT("Can't load " MALLOCLIB_NAME1 " or " MALLOCLIB_NAME2 "\n"); - exit(1); - } -#if _WIN32 || _WIN64 - // casts at both sides are to soothe MinGW compiler - (void *&)malloc_ptr = (void*)GetProcAddress(lib, "scalable_malloc"); - (void *&)free_ptr = (void*)GetProcAddress(lib, "scalable_free"); -#else - (void *&)malloc_ptr = dlsym(lib, "scalable_malloc"); - (void *&)free_ptr = dlsym(lib, "scalable_free"); -#endif - if (!malloc_ptr || !free_ptr) { - REPORT("Can't find scalable_(malloc|free) in %s \n", actual_name); - exit(1); - } - - void *p = malloc_ptr(100); - memset(p, 1, 100); - free_ptr(p); - -#if _WIN32 || _WIN64 - BOOL ret = FreeLibrary(lib); - ASSERT(ret, "FreeLibrary must be successful"); - ASSERT(GetModuleHandle(actual_name), - "allocator library must not be unloaded"); -#else - int ret = dlclose(lib); - ASSERT(ret == 0, "dlclose must be successful"); - ASSERT(dlsym(RTLD_DEFAULT, "scalable_malloc"), - "allocator library must not be unloaded"); -#endif - } -}; - -int TestMain () { - int i; - std::ptrdiff_t memory_leak; - - // warm-up run - NativeParallelFor( 1, Run() ); - /* 1st call to GetMemoryUsage() allocate some memory, - but it seems memory consumption stabilized after this. - */ - GetMemoryUsage(); - std::size_t memory_in_use = GetMemoryUsage(); - ASSERT(memory_in_use == GetMemoryUsage(), - "Memory consumption should not increase after 1st GetMemoryUsage() call"); - - // expect that memory consumption stabilized after several runs - for (i=0; i<3; i++) { - std::size_t memory_in_use = GetMemoryUsage(); - for (int j=0; j<10; j++) - NativeParallelFor( 1, Run() ); - memory_leak = GetMemoryUsage() - memory_in_use; - if (memory_leak == 0) // possibly too strong? - break; - } - if(3==i) { - // not stabilized, could be leak - REPORT( "Error: memory leak of up to %ld bytes\n", static_cast(memory_leak)); - exit(1); - } - - return Harness::Done; -} diff --git a/deal.II/contrib/tbb/tbb30_104oss/src/test/test_malloc_overload.cpp b/deal.II/contrib/tbb/tbb30_104oss/src/test/test_malloc_overload.cpp deleted file mode 100644 index 8b1d68c732..0000000000 --- a/deal.II/contrib/tbb/tbb30_104oss/src/test/test_malloc_overload.cpp +++ /dev/null @@ -1,276 +0,0 @@ -/* - Copyright 2005-2010 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. -*/ - - -#if __linux__ -#define MALLOC_REPLACEMENT_AVAILABLE 1 -#elif _WIN32 && !__MINGW32__ && !__MINGW64__ -#define MALLOC_REPLACEMENT_AVAILABLE 2 -#include "tbb/tbbmalloc_proxy.h" -#endif - -#if MALLOC_REPLACEMENT_AVAILABLE - -#if _WIN32 || _WIN64 -// As the test is intentionally build with /EHs-, suppress multiple VS2005's -// warnings like C4530: C++ exception handler used, but unwind semantics are not enabled -#if defined(_MSC_VER) && !__INTEL_COMPILER -/* ICC 10.1 and 11.0 generates code that uses std::_Raise_handler, - but it's only defined in libcpmt(d), which the test doesn't linked with. - */ -#define _HAS_EXCEPTIONS 0 -#endif -// to use strdup and putenv w/o warnings -#define _CRT_NONSTDC_NO_DEPRECATE 1 -#endif -#include "harness_report.h" -#include "harness_assert.h" -#include -#include -#include -#include -#include - -#if __linux__ -#include -#include // for sysconf -#include // for uintptr_t - -#elif _WIN32 -#include -#if __MINGW32__ -#include -#else -typedef unsigned __int16 uint16_t; -typedef unsigned __int32 uint32_t; -typedef unsigned __int64 uint64_t; -#endif - -#endif /* OS selection */ - -#if _WIN32 -// On Windows, the tricky way to print "done" is necessary to create -// dependence on msvcpXX.dll, for sake of a regression test. -// On Linux, C++ RTL headers are undesirable because of breaking strict ANSI mode. -#if defined(_MSC_VER) && _MSC_VER >= 1300 && _MSC_VER <= 1310 && !defined(__INTEL_COMPILER) -/* Fixing compilation error reported by VS2003 for exception class - when _HAS_EXCEPTIONS is 0: - bad_cast that inherited from exception is not in std namespace. -*/ -using namespace std; -#endif -#include -#endif - - -template -static inline T alignDown(T arg, uintptr_t alignment) { - return T( (uintptr_t)arg & ~(alignment-1)); -} -template -static inline bool isAligned(T arg, uintptr_t alignment) { - return 0==((uintptr_t)arg & (alignment-1)); -} - -/* Below is part of MemoryAllocator.cpp. */ - -class BackRefIdx { // composite index to backreference array -private: - uint16_t master; // index in BackRefMaster - uint16_t largeObj:1; // is this object "large"? - uint16_t offset :15; // offset from beginning of BackRefBlock -public: - BackRefIdx() : master((uint16_t)-1) {} - bool isInvalid() { return master == (uint16_t)-1; } - bool isLargeObject() const { return largeObj; } - uint16_t getMaster() const { return master; } - uint16_t getOffset() const { return offset; } - - // only newBackRef can modify BackRefIdx - static BackRefIdx newBackRef(bool largeObj); -}; - -struct LargeMemoryBlock { - LargeMemoryBlock *next, // ptrs in list of cached blocks - *prev; - uintptr_t age; // age of block while in cache - size_t objectSize; // the size requested by a client - size_t unalignedSize; // the size requested from getMemory - bool fromMapMemory; - BackRefIdx backRefIdx; // cached here, used copy is in LargeObjectHdr -}; - -struct LargeObjectHdr { - LargeMemoryBlock *memoryBlock; - /* Have to duplicate it here from CachedObjectHdr, - as backreference must be checked without further pointer dereference. - Points to LargeObjectHdr. */ - BackRefIdx backRefIdx; -}; - -/* - * Objects of this size and larger are considered large objects. - */ -const uint32_t minLargeObjectSize = 8065; - -/* end of inclusion from MemoryAllocator.cpp */ - -/* Correct only for large blocks, i.e. not smaller then minLargeObjectSize */ -static bool scalableMallocLargeBlock(void *object, size_t size) -{ - ASSERT(size >= minLargeObjectSize, NULL); -#if MALLOC_REPLACEMENT_AVAILABLE == 2 - // Check that _msize works correctly - ASSERT(_msize(object) >= size, NULL); -#endif - - LargeMemoryBlock *lmb = ((LargeObjectHdr*)object-1)->memoryBlock; - return uintptr_t(lmb)objectSize==size; -} - -struct BigStruct { - char f[minLargeObjectSize]; -}; - -int main(int , char *[]) { - void *ptr, *ptr1; - -#if MALLOC_REPLACEMENT_AVAILABLE == 1 - if (NULL == dlsym(RTLD_DEFAULT, "scalable_malloc")) { - REPORT("libtbbmalloc not found\nfail\n"); - return 1; - } -#endif - -/* On Windows, memory block size returned by _msize() is sometimes used - to calculate the size for an extended block. Substituting _msize, - scalable_msize initially returned 0 for regions not allocated by the scalable - allocator, which led to incorrect memory reallocation and subsequent crashes. - It was found that adding a new environment variable triggers the error. -*/ - ASSERT(getenv("PATH"), "We assume that PATH is set everywhere."); - char *pathCopy = strdup(getenv("PATH")); - const char *newEnvName = "__TBBMALLOC_OVERLOAD_REGRESSION_TEST_FOR_REALLOC_AND_MSIZE"; - char *newEnv = (char*)malloc(3 + strlen(newEnvName)); - - ASSERT(!getenv(newEnvName), "Environment variable should not be used before."); - strcpy(newEnv, newEnvName); - strcat(newEnv, "=1"); - int r = putenv(newEnv); - ASSERT(!r, NULL); - char *path = getenv("PATH"); - ASSERT(path && 0==strcmp(path, pathCopy), "Environment was changed erroneously."); - free(pathCopy); - free(newEnv); - - ptr = malloc(minLargeObjectSize); - ASSERT(ptr!=NULL && scalableMallocLargeBlock(ptr, minLargeObjectSize), NULL); - free(ptr); - - ptr = calloc(minLargeObjectSize, 2); - ASSERT(ptr!=NULL && scalableMallocLargeBlock(ptr, minLargeObjectSize*2), NULL); - ptr1 = realloc(ptr, minLargeObjectSize*10); - ASSERT(ptr1!=NULL && scalableMallocLargeBlock(ptr1, minLargeObjectSize*10), NULL); - free(ptr1); - -#if MALLOC_REPLACEMENT_AVAILABLE == 1 - - int ret = posix_memalign(&ptr, 1024, 3*minLargeObjectSize); - ASSERT(0==ret && ptr!=NULL && scalableMallocLargeBlock(ptr, 3*minLargeObjectSize), NULL); - free(ptr); - - ptr = memalign(128, 4*minLargeObjectSize); - ASSERT(ptr!=NULL && scalableMallocLargeBlock(ptr, 4*minLargeObjectSize), NULL); - free(ptr); - - ptr = valloc(minLargeObjectSize); - ASSERT(ptr!=NULL && scalableMallocLargeBlock(ptr, minLargeObjectSize), NULL); - free(ptr); - - long memoryPageSize = sysconf(_SC_PAGESIZE); - int sz = 1024*minLargeObjectSize; - ptr = pvalloc(sz); - ASSERT(ptr!=NULL && // align size up to the page size - scalableMallocLargeBlock(ptr, ((sz-1) | (memoryPageSize-1)) + 1), NULL); - free(ptr); - - struct mallinfo info = mallinfo(); - // right now mallinfo initialized by zero - ASSERT(!info.arena && !info.ordblks && !info.smblks && !info.hblks - && !info.hblkhd && !info.usmblks && !info.fsmblks - && !info.uordblks && !info.fordblks && !info.keepcost, NULL); - -#elif MALLOC_REPLACEMENT_AVAILABLE == 2 - - ptr = _aligned_malloc(minLargeObjectSize,16); - ASSERT(ptr!=NULL && scalableMallocLargeBlock(ptr, minLargeObjectSize), NULL); - - ptr1 = _aligned_realloc(ptr, minLargeObjectSize*10,16); - ASSERT(ptr1!=NULL && scalableMallocLargeBlock(ptr1, minLargeObjectSize*10), NULL); - _aligned_free(ptr1); - -#endif - - BigStruct *f = new BigStruct; - ASSERT(f!=NULL && scalableMallocLargeBlock(f, sizeof(BigStruct)), NULL); - delete f; - - f = new BigStruct[10]; - ASSERT(f!=NULL && scalableMallocLargeBlock(f, 10*sizeof(BigStruct)), NULL); - delete []f; - - f = new(std::nothrow) BigStruct; - ASSERT(f!=NULL && scalableMallocLargeBlock(f, sizeof(BigStruct)), NULL); - delete f; - - f = new(std::nothrow) BigStruct[2]; - ASSERT(f!=NULL && scalableMallocLargeBlock(f, 2*sizeof(BigStruct)), NULL); - delete []f; - -#if _WIN32 - std::string stdstring = "done"; - const char* s = stdstring.c_str(); -#else - const char* s = "done"; -#endif - REPORT("%s\n", s); - return 0; -} - -#define HARNESS_NO_PARSE_COMMAND_LINE 1 -#define HARNESS_CUSTOM_MAIN 1 -#include "harness.h" - -#else /* !MALLOC_REPLACEMENT_AVAILABLE */ -#include - -int main(int , char *[]) { - printf("skip\n"); - return 0; -} -#endif /* !MALLOC_REPLACEMENT_AVAILABLE */ diff --git a/deal.II/contrib/tbb/tbb30_104oss/src/test/test_malloc_pure_c.c b/deal.II/contrib/tbb/tbb30_104oss/src/test/test_malloc_pure_c.c deleted file mode 100644 index a92c4816e5..0000000000 --- a/deal.II/contrib/tbb/tbb30_104oss/src/test/test_malloc_pure_c.c +++ /dev/null @@ -1,80 +0,0 @@ -/* - Copyright 2005-2010 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. -*/ - -#ifdef __cplusplus -#error For testing purpose, this file should be compiled with a C compiler, not C++ -#endif /*__cplusplus */ - -#include "tbb/scalable_allocator.h" -#include -#include - -/* - * The test is to check if the scalable_allocator.h and its functions - * can be used from pure C programs; also some regression checks are done - */ - -int main(void) { - size_t i, j; - void *p1, *p2; - for( i=0; i<=1<<16; ++i) { - p1 = scalable_malloc(i); - if( !p1 ) - printf("Warning: there should be memory but scalable_malloc returned NULL\n"); - scalable_free(p1); - } - p1 = p2 = NULL; - for( i=1024*1024; ; i/=2 ) - { - scalable_free(p1); - p1 = scalable_realloc(p2, i); - p2 = scalable_calloc(i, 32); - if (p2) { - if (i -#include "tbb/scalable_allocator.h" - -class minimalAllocFree { -public: - void operator()(int size) const { - tbb::scalable_allocator a; - char* str = a.allocate( size ); - a.deallocate( str, size ); - } -}; - -#include "harness.h" - -template -void RunThread(const Body& body, const Arg& arg) { - NativeParallelForTask job(arg, body); - job.start(); - job.wait_to_finish(); -} - -/*--------------------------------------------------------------------*/ -// The regression test against bug #1518 where thread boot strap allocations "leaked" - -#include "harness_memory.h" - -bool TestBootstrapLeak() { - /* In the bug 1518, each thread leaked ~384 bytes. - Initially, scalable allocator maps 1MB. Thus it is necessary to take out most of this space. - 1MB is chunked into 16K blocks; of those, one block is for thread boot strap, and one more - should be reserved for the test body. 62 blocks left, each can serve 15 objects of 1024 bytes. - */ - const int alloc_size = 1024; - const int take_out_count = 15*62; - - tbb::scalable_allocator a; - char* array[take_out_count]; - for( int i=0; i0 ) { // possibly too strong? - REPORT( "Error: memory leak of up to %ld bytes\n", static_cast(memory_leak)); - } - - for( int i=0; i=startSz, "scalable_msize must be not less then allocated size"); - memset(buf, 'a', realSz-1); - buf[realSz-1] = 0; - char *buf1 = (char*)scalable_realloc(buf, 2*realSz); - ASSERT(buf1, ""); - ASSERT(scalable_msize(buf1)>=2*realSz, - "scalable_msize must be not less then allocated size"); - buf1[2*realSz-1] = 0; - if ( strspn(buf1, "a") < realSz-1 ) { - REPORT( "Error: data broken for %d Bytes object.\n", startSz); - passed = false; - } - scalable_free(buf1); - - return passed; -} - -/*--------------------------------------------------------------------*/ -// The main test function - -int TestMain () { - bool passed = true; - // Check whether memory usage data can be obtained; if not, skip test_bootstrap_leak. - if( GetMemoryUsage() ) - passed &= TestBootstrapLeak(); - - // TestReallocMsize runs for each power of 2 and each Fibonacci number below 64K - for (size_t a=1, b=1, sum=1; sum<=64*1024; ) { - passed &= TestReallocMsize(sum); - a = b; - b = sum; - sum = a+b; - } - for (size_t a=2; a<=64*1024; a*=2) - passed &= TestReallocMsize(a); - - ASSERT( passed, "Test failed" ); - return Harness::Done; -} diff --git a/deal.II/contrib/tbb/tbb30_104oss/src/test/test_malloc_whitebox.cpp b/deal.II/contrib/tbb/tbb30_104oss/src/test/test_malloc_whitebox.cpp deleted file mode 100644 index c8bc6a689c..0000000000 --- a/deal.II/contrib/tbb/tbb30_104oss/src/test/test_malloc_whitebox.cpp +++ /dev/null @@ -1,346 +0,0 @@ -/* - Copyright 2005-2010 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. -*/ - -#include "tbb/scalable_allocator.h" -#include "harness.h" -#include "harness_barrier.h" - -// To not depends on ITT support stuff -#ifdef DO_ITT_NOTIFY -#undef DO_ITT_NOTIFY -#endif - -#define protected public -#define private public -#include "../tbbmalloc/frontend.cpp" -#undef protected -#undef private -#include "../tbbmalloc/backend.cpp" -#include "../tbbmalloc/backref.cpp" -#include "../tbbmalloc/large_objects.cpp" -#include "../tbbmalloc/tbbmalloc.cpp" - -const int LARGE_MEM_SIZES_NUM = 10; -const size_t MByte = 1024*1024; - -class AllocInfo { - int *p; - int val; - int size; -public: - AllocInfo() : p(NULL), val(0), size(0) {} - explicit AllocInfo(int size) : p((int*)scalable_malloc(size*sizeof(int))), - val(rand()), size(size) { - ASSERT(p, NULL); - for (int k=0; k=blocks1[i].sz - && 0==(uintptr_t)blocks1[i].ptr % sizeof(void*), NULL); - memset(blocks1[i].ptr, i, blocks1[i].sz); - } - for (int i=0; i=blocks2[i].sz - && 0==(uintptr_t)blocks2[i].ptr % sizeof(void*), NULL); - memset(blocks2[i].ptr, i, blocks2[i].sz); - - for (size_t j=0; jfree(blocks1[i].ptr); - } - for (int i=ITERS-1; i>=0; i--) { - for (size_t j=0; jfree(blocks2[i].ptr); - } - } -}; - -Harness::SpinBarrier TestStartupAlloc::init_barrier; - -#endif /* MALLOC_CHECK_RECURSION */ - -class BackRefWork: NoAssign { - struct TestBlock { - intptr_t data; - BackRefIdx idx; - }; - static const int ITERS = 2*BR_MAX_CNT+2; -public: - BackRefWork() {} - void operator()(int) const { - TestBlock blocks[ITERS]; - - for (int i=0; i=0; i--) - removeBackRef(blocks[i].idx); - } -}; - -class FreeBlockPoolHit: NoAssign { - // to trigger possible leak for both cleanup on pool overflow - // and on thread termination - static const int ITERS = 2*FreeBlockPool::POOL_HIGH_MARK; -public: - FreeBlockPoolHit() {} - void operator()(int) const { - void *objs[ITERS]; - - for (int i=0; ilastUsed; i++) - cnt += backRefMaster->backRefBl[i]->allocatedCount; - return cnt; -} - -void TestBackRef() { - size_t beforeNumBackRef, afterNumBackRef; - - beforeNumBackRef = allocatedBackRefCount(); - for( int p=MaxThread; p>=MinThread; --p ) - NativeParallelFor( p, BackRefWork() ); - afterNumBackRef = allocatedBackRefCount(); - ASSERT(beforeNumBackRef==afterNumBackRef, "backreference leak detected"); - - // lastUsed marks peak resource consumption. As we allocate below the mark, - // it must not move up, otherwise there is a resource leak. - int sustLastUsed = backRefMaster->lastUsed; - NativeParallelFor( 1, BackRefWork() ); - ASSERT(sustLastUsed == backRefMaster->lastUsed, "backreference leak detected"); - - // check leak of back references while per-thread small object pool is in use - // warm up need to cover bootStrapMalloc call - NativeParallelFor( 1, FreeBlockPoolHit() ); - beforeNumBackRef = allocatedBackRefCount(); - NativeParallelFor( 1, FreeBlockPoolHit() ); - afterNumBackRef = allocatedBackRefCount(); - ASSERT(beforeNumBackRef==afterNumBackRef, "backreference leak detected"); -} - -void TestObjectRecognition() { - size_t headersSize = sizeof(LargeMemoryBlock)+sizeof(LargeObjectHdr); - unsigned falseObjectSize = 113; // unsigned is the type expected by getObjectSize - size_t obtainedSize; - Block *auxBackRef; - - ASSERT(sizeof(BackRefIdx)==4, "Unexpected size of BackRefIdx"); - ASSERT(getObjectSize(falseObjectSize)!=falseObjectSize, "Error in test: bad choice for false object size"); - - void* mem = scalable_malloc(2*blockSize); - Block* falseBlock = (Block*)alignUp((uintptr_t)mem, blockSize); - falseBlock->objectSize = falseObjectSize; - char* falseSO = (char*)falseBlock + falseObjectSize*7; - ASSERT(alignDown(falseSO, blockSize)==(void*)falseBlock, "Error in test: false object offset is too big"); - - void* bufferLOH = scalable_malloc(2*blockSize + headersSize); - LargeObjectHdr* falseLO = - (LargeObjectHdr*)alignUp((uintptr_t)bufferLOH + headersSize, blockSize); - LargeObjectHdr* headerLO = (LargeObjectHdr*)falseLO-1; - headerLO->memoryBlock = (LargeMemoryBlock*)bufferLOH; - headerLO->memoryBlock->unalignedSize = 2*blockSize + headersSize; - headerLO->memoryBlock->objectSize = blockSize + headersSize; - headerLO->backRefIdx = BackRefIdx::newBackRef(/*largeObj=*/true); - setBackRef(headerLO->backRefIdx, headerLO); - ASSERT(scalable_msize(falseLO) == blockSize + headersSize, - "Error in test: LOH falsification failed"); - removeBackRef(headerLO->backRefIdx); - - const int NUM_OF_IDX = BR_MAX_CNT+2; - BackRefIdx idxs[NUM_OF_IDX]; - for (int cnt=0; cnt<2; cnt++) { - for (int master = -10; master<10; master++) { - falseBlock->backRefIdx.master = (uint16_t)master; - headerLO->backRefIdx.master = (uint16_t)master; - - for (int bl = -10; blbackRefIdx.offset = (uint16_t)bl; - headerLO->backRefIdx.offset = (uint16_t)bl; - - for (int largeObj = 0; largeObj<2; largeObj++) { - falseBlock->backRefIdx.largeObj = largeObj; - headerLO->backRefIdx.largeObj = largeObj; - - obtainedSize = safer_scalable_msize(falseSO, NULL); - ASSERT(obtainedSize==0, "Incorrect pointer accepted"); - obtainedSize = safer_scalable_msize(falseLO, NULL); - ASSERT(obtainedSize==0, "Incorrect pointer accepted"); - } - } - } - if (cnt == 1) { - for (int i=0; i=2*blockSize, "Correct pointer not accepted?"); - scalable_free(mem); - scalable_free(bufferLOH); -} - - -int TestMain () { - // backreference requires that initialization was done - if(!isMallocInitialized()) doInitialization(); - // to succeed, leak detection must be the 1st memory-intensive test - TestBackRef(); - -#if MALLOC_CHECK_RECURSION - for( int p=MaxThread; p>=MinThread; --p ) { - TestStartupAlloc::initBarrier( p ); - NativeParallelFor( p, TestStartupAlloc() ); - ASSERT(!firstStartupBlock, "Startup heap memory leak detected"); - } -#endif - - for (int i=0; i=MinThread; --p ) { - TestLargeObjCache::initBarrier( p ); - NativeParallelFor( p, TestLargeObjCache() ); - } - - TestObjectRecognition(); - return Harness::Done; -} diff --git a/deal.II/contrib/tbb/tbb30_104oss/src/test/test_model_plugin.cpp b/deal.II/contrib/tbb/tbb30_104oss/src/test/test_model_plugin.cpp deleted file mode 100644 index c9adf9fc9d..0000000000 --- a/deal.II/contrib/tbb/tbb30_104oss/src/test/test_model_plugin.cpp +++ /dev/null @@ -1,262 +0,0 @@ -/* - Copyright 2005-2010 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. -*/ - - -#if _WIN32 || _WIN64 -#include "tbb/machine/windows_api.h" -#else -#include -#endif - -#include -#include - -#include "tbb/tbb_config.h" - -#if !TBB_USE_EXCEPTIONS && _MSC_VER - // Suppress "C++ exception handler used, but unwind semantics are not enabled" warning in STL headers - #pragma warning (push) - #pragma warning (disable: 4530) -#endif - -#include - -#if !TBB_USE_EXCEPTIONS && _MSC_VER - #pragma warning (pop) -#endif - -#if TBB_USE_EXCEPTIONS - #include "harness_report.h" -#endif - -#ifdef _USRDLL -#include "tbb/task_scheduler_init.h" - -class CModel { -public: - CModel(void) {}; - static tbb::task_scheduler_init tbb_init; - - void init_and_terminate( int ); -}; - -tbb::task_scheduler_init CModel::tbb_init(1); - -//! Test that task::initialize and task::terminate work when doing nothing else. -/** maxthread is treated as the "maximum" number of worker threads. */ -void CModel::init_and_terminate( int maxthread ) { - for( int i=0; i<200; ++i ) { - switch( i&3 ) { - default: { - tbb::task_scheduler_init init( rand() % maxthread + 1 ); - break; - } - case 0: { - tbb::task_scheduler_init init; - break; - } - case 1: { - tbb::task_scheduler_init init( tbb::task_scheduler_init::automatic ); - break; - } - case 2: { - tbb::task_scheduler_init init( tbb::task_scheduler_init::deferred ); - init.initialize( rand() % maxthread + 1 ); - init.terminate(); - break; - } - } - } -} - -extern "C" -#if _WIN32 || _WIN64 -__declspec(dllexport) -#endif -void plugin_call(int maxthread) -{ - srand(2); - __TBB_TRY { - CModel model; - model.init_and_terminate(maxthread); - } __TBB_CATCH( std::runtime_error& error ) { -#if TBB_USE_EXCEPTIONS - REPORT("ERROR: %s\n", error.what()); -#endif /* TBB_USE_EXCEPTIONS */ - } -} - -#else /* _USRDLL undefined */ - -#define HARNESS_NO_ASSERT 1 -#include "harness.h" - -extern "C" void plugin_call(int); - -void report_error_in(const char* function_name) -{ -#if _WIN32 || _WIN64 - char* message; - int code = GetLastError(); - - FormatMessage( - FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM, - NULL, code,MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), - (char*)&message, 0, NULL ); -#else - char* message = (char*)dlerror(); - int code = 0; -#endif - REPORT( "%s failed with error %d: %s\n", function_name, code, message); - -#if _WIN32 || _WIN64 - LocalFree(message); -#endif -} - -int use_lot_of_tls() { - int count = 0; -#if _WIN32 || _WIN64 - DWORD last_handles[10]; - DWORD result; - result = TlsAlloc(); - while( result!=TLS_OUT_OF_INDEXES ) { - last_handles[++count%10] = result; - result = TlsAlloc(); - } - for( int i=0; i<10; ++i ) - TlsFree(last_handles[i]); -#else - pthread_key_t last_handles[10]; - pthread_key_t result; - int setspecific_dummy=10; - while( pthread_key_create(&result, NULL)==0 - && count < 4096 ) // Sun Solaris doesn't have any built-in limit, so we set something big enough - { - last_handles[++count%10] = result; - pthread_setspecific(result,&setspecific_dummy); - } - REMARK("Created %d keys\n", count); - for( int i=0; i<10; ++i ) - pthread_key_delete(last_handles[i]); -#endif - return count-10; -} - -typedef void (*PLUGIN_CALL)(int); - -int TestMain () { -#if !RML_USE_WCRM - PLUGIN_CALL my_plugin_call; - - int tls_key_count = use_lot_of_tls(); - REMARK("%d thread local objects allocated in advance\n", tls_key_count); - -#if _WIN32 || _WIN64 - HMODULE hLib; -#if __TBB_ARENA_PER_MASTER - hLib = LoadLibrary("irml.dll"); - if ( !hLib ) - hLib = LoadLibrary("irml_debug.dll"); - if ( !hLib ) - return Harness::Skipped; // No shared RML, skip the test - FreeLibrary(hLib); -#endif /* __TBB_ARENA_PER_MASTER */ -#else /* !WIN */ -#if __APPLE__ - #define LIBRARY_NAME(base) base".dylib" -#else - #define LIBRARY_NAME(base) base".so" -#endif - void* hLib; -#if __TBB_ARENA_PER_MASTER -#if __linux__ - #define RML_LIBRARY_NAME(base) LIBRARY_NAME(base) ".1" -#else - #define RML_LIBRARY_NAME(base) LIBRARY_NAME(base) -#endif - hLib = dlopen(RML_LIBRARY_NAME("libirml"), RTLD_LAZY); - if ( !hLib ) - hLib = dlopen(RML_LIBRARY_NAME("libirml_debug"), RTLD_LAZY); - if ( !hLib ) - return Harness::Skipped; - dlclose(hLib); -#endif /* __TBB_ARENA_PER_MASTER */ -#endif /* OS */ - for( int i=1; i<100; ++i ) { - REMARK("Iteration %d, loading plugin library...\n", i); -#if _WIN32 || _WIN64 - hLib = LoadLibrary("test_model_plugin_dll.dll"); - if ( !hLib ) { -#if !__TBB_NO_IMPLICIT_LINKAGE - report_error_in("LoadLibrary"); - return -1; -#else - return Harness::Skipped; -#endif - } - my_plugin_call = (PLUGIN_CALL) GetProcAddress(hLib, "plugin_call"); - if (my_plugin_call==NULL) { - report_error_in("GetProcAddress"); - return -1; - } -#else /* !WIN */ - hLib = dlopen( LIBRARY_NAME("test_model_plugin_dll"), RTLD_LAZY ); - if ( !hLib ) { -#if !__TBB_NO_IMPLICIT_LINKAGE - report_error_in("dlopen"); - return -1; -#else - return Harness::Skipped; -#endif - } - my_plugin_call = PLUGIN_CALL (dlsym(hLib, "plugin_call")); - if (my_plugin_call==NULL) { - report_error_in("dlsym"); - return -1; - } -#endif /* !WIN */ - - REMARK("Calling plugin method...\n"); - my_plugin_call(MaxThread); - - REMARK("Unloading plugin library...\n"); -#if _WIN32 || _WIN64 - FreeLibrary(hLib); -#else - dlclose(hLib); -#endif - } // end for(1,100) - - return Harness::Done; -#else - return Harness::Skipped; -#endif /* !RML_USE_WCRM */ -} - -#endif//_USRDLL diff --git a/deal.II/contrib/tbb/tbb30_104oss/src/test/test_mutex.cpp b/deal.II/contrib/tbb/tbb30_104oss/src/test/test_mutex.cpp deleted file mode 100644 index 0e0ecb267f..0000000000 --- a/deal.II/contrib/tbb/tbb30_104oss/src/test/test_mutex.cpp +++ /dev/null @@ -1,628 +0,0 @@ -/* - Copyright 2005-2010 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. -*/ - -//------------------------------------------------------------------------ -// Test TBB mutexes when used with parallel_for.h -// -// Usage: test_Mutex.exe [-v] nthread -// -// The -v option causes timing information to be printed. -// -// Compile with _OPENMP and -openmp -//------------------------------------------------------------------------ -#include "tbb/spin_mutex.h" -#include "tbb/critical_section.h" -#include "tbb/spin_rw_mutex.h" -#include "tbb/queuing_rw_mutex.h" -#include "tbb/queuing_mutex.h" -#include "tbb/mutex.h" -#include "tbb/recursive_mutex.h" -#include "tbb/null_mutex.h" -#include "tbb/null_rw_mutex.h" -#include "tbb/parallel_for.h" -#include "tbb/blocked_range.h" -#include "tbb/tick_count.h" -#include "tbb/atomic.h" -#include "harness.h" -#include -#include -#if _OPENMP -#include "test/OpenMP_Mutex.h" -#endif /* _OPENMP */ -#include "tbb/tbb_profiling.h" - -#ifndef TBB_TEST_LOW_WORKLOAD - #define TBB_TEST_LOW_WORKLOAD TBB_USE_THREADING_TOOLS -#endif - -// This test deliberately avoids a "using tbb" statement, -// so that the error of putting types in the wrong namespace will be caught. - -template -struct Counter { - typedef M mutex_type; - M mutex; - volatile long value; -}; - -//! Function object for use with parallel_for.h. -template -struct AddOne: NoAssign { - C& counter; - /** Increments counter once for each iteration in the iteration space. */ - void operator()( tbb::blocked_range& range ) const { - for( size_t i=range.begin(); i!=range.end(); ++i ) { - if( i&1 ) { - // Try implicit acquire and explicit release - typename C::mutex_type::scoped_lock lock(counter.mutex); - counter.value = counter.value+1; - lock.release(); - } else { - // Try explicit acquire and implicit release - typename C::mutex_type::scoped_lock lock; - lock.acquire(counter.mutex); - counter.value = counter.value+1; - } - } - } - AddOne( C& counter_ ) : counter(counter_) {} -}; - -//! Adaptor for using ISO C++0x style mutex as a TBB-style mutex. -template -class TBB_MutexFromISO_Mutex { - M my_iso_mutex; -public: - typedef TBB_MutexFromISO_Mutex mutex_type; - - class scoped_lock; - friend class scoped_lock; - - class scoped_lock { - mutex_type* my_mutex; - public: - scoped_lock() : my_mutex(NULL) {} - scoped_lock( mutex_type& m ) : my_mutex(NULL) { - acquire(m); - } - scoped_lock( mutex_type& m, bool is_writer ) : my_mutex(NULL) { - acquire(m,is_writer); - } - void acquire( mutex_type& m ) { - m.my_iso_mutex.lock(); - my_mutex = &m; - } - bool try_acquire( mutex_type& m ) { - if( m.my_iso_mutex.try_lock() ) { - my_mutex = &m; - return true; - } else { - return false; - } - } - void release() { - my_mutex->my_iso_mutex.unlock(); - my_mutex = NULL; - } - - // Methods for reader-writer mutex - // These methods can be instantiated only if M supports lock_read() and try_lock_read(). - - void acquire( mutex_type& m, bool is_writer ) { - if( is_writer ) m.my_iso_mutex.lock(); - else m.my_iso_mutex.lock_read(); - my_mutex = &m; - } - bool try_acquire( mutex_type& m, bool is_writer ) { - if( is_writer ? m.my_iso_mutex.try_lock() : m.my_iso_mutex.try_lock_read() ) { - my_mutex = &m; - return true; - } else { - return false; - } - } - bool upgrade_to_writer() { - my_mutex->my_iso_mutex.unlock(); - my_mutex->my_iso_mutex.lock(); - return false; - } - bool downgrade_to_reader() { - my_mutex->my_iso_mutex.unlock(); - my_mutex->my_iso_mutex.lock_read(); - return false; - } - ~scoped_lock() { - if( my_mutex ) - release(); - } - }; - - static const bool is_recursive_mutex = M::is_recursive_mutex; - static const bool is_rw_mutex = M::is_rw_mutex; -}; - -namespace tbb { - namespace profiling { - template - void set_name( const TBB_MutexFromISO_Mutex&, const char* ) {} - } -} - -//! Generic test of a TBB mutex type M. -/** Does not test features specific to reader-writer locks. */ -template -void Test( const char * name ) { - REMARK("%s time = ",name); - Counter counter; - counter.value = 0; - tbb::profiling::set_name(counter.mutex, name); -#if TBB_TEST_LOW_WORKLOAD - const int n = 10000; -#else - const int n = 100000; -#endif /* TBB_TEST_LOW_WORKLOAD */ - tbb::tick_count t0 = tbb::tick_count::now(); - tbb::parallel_for(tbb::blocked_range(0,n,n/10),AddOne >(counter)); - tbb::tick_count t1 = tbb::tick_count::now(); - REMARK("%g usec\n",(t1-t0).seconds()); - if( counter.value!=n ) - REPORT("ERROR for %s: counter.value=%ld\n",name,counter.value); -} - -template -struct Invariant { - typedef M mutex_type; - M mutex; - const char* mutex_name; - volatile long value[N]; - volatile long single_value; - Invariant( const char* mutex_name_ ) : - mutex_name(mutex_name_) - { - single_value = 0; - for( size_t k=0; k -struct TwiddleInvariant: NoAssign { - I& invariant; - /** Increments counter once for each iteration in the iteration space. */ - void operator()( tbb::blocked_range& range ) const { - for( size_t i=range.begin(); i!=range.end(); ++i ) { - //! Every 8th access is a write access - bool write = (i%8)==7; - bool okay = true; - bool lock_kept = true; - if( (i/8)&1 ) { - // Try implicit acquire and explicit release - typename I::mutex_type::scoped_lock lock(invariant.mutex,write); - if( write ) { - long my_value = invariant.value[0]; - invariant.update(); - if( i%16==7 ) { - lock_kept = lock.downgrade_to_reader(); - if( !lock_kept ) - my_value = invariant.value[0] - 1; - okay = invariant.value_is(my_value+1); - } - } else { - okay = invariant.is_okay(); - if( i%8==3 ) { - long my_value = invariant.value[0]; - lock_kept = lock.upgrade_to_writer(); - if( !lock_kept ) - my_value = invariant.value[0]; - invariant.update(); - okay = invariant.value_is(my_value+1); - } - } - lock.release(); - } else { - // Try explicit acquire and implicit release - typename I::mutex_type::scoped_lock lock; - lock.acquire(invariant.mutex,write); - if( write ) { - long my_value = invariant.value[0]; - invariant.update(); - if( i%16==7 ) { - lock_kept = lock.downgrade_to_reader(); - if( !lock_kept ) - my_value = invariant.value[0] - 1; - okay = invariant.value_is(my_value+1); - } - } else { - okay = invariant.is_okay(); - if( i%8==3 ) { - long my_value = invariant.value[0]; - lock_kept = lock.upgrade_to_writer(); - if( !lock_kept ) - my_value = invariant.value[0]; - invariant.update(); - okay = invariant.value_is(my_value+1); - } - } - } - if( !okay ) { - REPORT( "ERROR for %s at %ld: %s %s %s %s\n",invariant.mutex_name, long(i), - write?"write,":"read,", write?(i%16==7?"downgrade,":""):(i%8==3?"upgrade,":""), - lock_kept?"lock kept,":"lock not kept,", (i/8)&1?"imp/exp":"exp/imp" ); - } - } - } - TwiddleInvariant( I& invariant_ ) : invariant(invariant_) {} -}; - -/** This test is generic so that we can test any other kinds of ReaderWriter locks we write later. */ -template -void TestReaderWriterLock( const char * mutex_name ) { - REMARK( "%s readers & writers time = ", mutex_name ); - Invariant invariant(mutex_name); -#if TBB_TEST_LOW_WORKLOAD - const size_t n = 10000; -#else - const size_t n = 500000; -#endif /* TBB_TEST_LOW_WORKLOAD */ - tbb::tick_count t0 = tbb::tick_count::now(); - tbb::parallel_for(tbb::blocked_range(0,n,n/100),TwiddleInvariant >(invariant)); - tbb::tick_count t1 = tbb::tick_count::now(); - // There is either a writer or a reader upgraded to a writer for each 4th iteration - long expected_value = n/4; - if( !invariant.value_is(expected_value) ) - REPORT("ERROR for %s: final invariant value is wrong\n",mutex_name); - REMARK( "%g usec\n", (t1-t0).seconds() ); -} - -#if _MSC_VER && !defined(__INTEL_COMPILER) - // Suppress "conditional expression is constant" warning. - #pragma warning( push ) - #pragma warning( disable: 4127 ) -#endif - -/** Test try_acquire_reader functionality of a non-reenterable reader-writer mutex */ -template -void TestTryAcquireReader_OneThread( const char * mutex_name ) { - M tested_mutex; - typename M::scoped_lock lock1; - if( M::is_rw_mutex ) { - if( lock1.try_acquire(tested_mutex, false) ) - lock1.release(); - else - REPORT("ERROR for %s: try_acquire failed though it should not\n", mutex_name); - { - typename M::scoped_lock lock2(tested_mutex, false); - if( lock1.try_acquire(tested_mutex) ) - REPORT("ERROR for %s: try_acquire succeeded though it should not\n", mutex_name); - lock2.release(); - lock2.acquire(tested_mutex, true); - if( lock1.try_acquire(tested_mutex, false) ) - REPORT("ERROR for %s: try_acquire succeeded though it should not\n", mutex_name); - } - if( lock1.try_acquire(tested_mutex, false) ) - lock1.release(); - else - REPORT("ERROR for %s: try_acquire failed though it should not\n", mutex_name); - } -} - -/** Test try_acquire functionality of a non-reenterable mutex */ -template -void TestTryAcquire_OneThread( const char * mutex_name ) { - M tested_mutex; - typename M::scoped_lock lock1; - if( lock1.try_acquire(tested_mutex) ) - lock1.release(); - else - REPORT("ERROR for %s: try_acquire failed though it should not\n", mutex_name); - { - if( M::is_recursive_mutex ) { - typename M::scoped_lock lock2(tested_mutex); - if( lock1.try_acquire(tested_mutex) ) - lock1.release(); - else - REPORT("ERROR for %s: try_acquire on recursive lock failed though it should not\n", mutex_name); - //windows.. -- both are recursive - } else { - typename M::scoped_lock lock2(tested_mutex); - if( lock1.try_acquire(tested_mutex) ) - REPORT("ERROR for %s: try_acquire succeeded though it should not\n", mutex_name); - } - } - if( lock1.try_acquire(tested_mutex) ) - lock1.release(); - else - REPORT("ERROR for %s: try_acquire failed though it should not\n", mutex_name); -} - -#if _MSC_VER && !defined(__INTEL_COMPILER) - #pragma warning( pop ) -#endif - -const int RecurN = 4; -int RecurArray[ RecurN ]; -tbb::recursive_mutex RecurMutex[ RecurN ]; - -struct RecursiveAcquisition { - /** x = number being decoded in base N - max_lock = index of highest lock acquired so far - mask = bit mask; ith bit set if lock i has been acquired. */ - void Body( size_t x, int max_lock=-1, unsigned int mask=0 ) const - { - int i = (int) (x % RecurN); - bool first = (mask&1U< &r ) const - { - for( size_t x=r.begin(); x -void TestRecursiveMutex( const char * mutex_name ) -{ - for ( int i = 0; i < RecurN; ++i ) { - tbb::profiling::set_name(RecurMutex[i], mutex_name); - } - tbb::tick_count t0 = tbb::tick_count::now(); - tbb::parallel_for(tbb::blocked_range(0,10000,500), RecursiveAcquisition()); - tbb::tick_count t1 = tbb::tick_count::now(); - REMARK( "%s recursive mutex time = %g usec\n", mutex_name, (t1-t0).seconds() ); -} - -template -struct NullRecursive: NoAssign { - void recurse_till( size_t i, size_t till ) const { - if( i==till ) { - counter.value = counter.value+1; - return; - } - if( i&1 ) { - typename C::mutex_type::scoped_lock lock2(counter.mutex); - recurse_till( i+1, till ); - lock2.release(); - } else { - typename C::mutex_type::scoped_lock lock2; - lock2.acquire(counter.mutex); - recurse_till( i+1, till ); - } - } - - void operator()( tbb::blocked_range& range ) const { - typename C::mutex_type::scoped_lock lock(counter.mutex); - recurse_till( range.begin(), range.end() ); - } - NullRecursive( C& counter_ ) : counter(counter_) { - ASSERT( C::mutex_type::is_recursive_mutex, "Null mutex should be a recursive mutex." ); - } - C& counter; -}; - -template -struct NullUpgradeDowngrade: NoAssign { - void operator()( tbb::blocked_range& range ) const { - typename M::scoped_lock lock2; - for( size_t i=range.begin(); i!=range.end(); ++i ) { - if( i&1 ) { - typename M::scoped_lock lock1(my_mutex, true) ; - if( lock1.downgrade_to_reader()==false ) - REPORT("ERROR for %s: downgrade should always succeed\n", name); - } else { - lock2.acquire( my_mutex, false ); - if( lock2.upgrade_to_writer()==false ) - REPORT("ERROR for %s: upgrade should always succeed\n", name); - lock2.release(); - } - } - } - - NullUpgradeDowngrade( M& m_, const char* n_ ) : my_mutex(m_), name(n_) {} - M& my_mutex; - const char* name; -} ; - -template -void TestNullMutex( const char * name ) { - Counter counter; - counter.value = 0; - const int n = 100; - REMARK("%s ",name); - { - tbb::parallel_for(tbb::blocked_range(0,n,10),AddOne >(counter)); - } - counter.value = 0; - { - tbb::parallel_for(tbb::blocked_range(0,n,10),NullRecursive >(counter)); - } - -} - -template -void TestNullRWMutex( const char * name ) { - REMARK("%s ",name); - const int n = 100; - M m; - tbb::parallel_for(tbb::blocked_range(0,n,10),NullUpgradeDowngrade(m, name)); -} - -//! Test ISO C++0x compatibility portion of TBB mutex -template -void TestISO( const char * name ) { - typedef TBB_MutexFromISO_Mutex tbb_from_iso; - Test( name ); -} - -//! Test ISO C++0x try_lock functionality of a non-reenterable mutex */ -template -void TestTryAcquire_OneThreadISO( const char * name ) { - typedef TBB_MutexFromISO_Mutex tbb_from_iso; - TestTryAcquire_OneThread( name ); -} - -//! Test ISO-like C++0x compatibility portion of TBB reader-writer mutex -template -void TestReaderWriterLockISO( const char * name ) { - typedef TBB_MutexFromISO_Mutex tbb_from_iso; - TestReaderWriterLock( name ); - TestTryAcquireReader_OneThread( name ); -} - -//! Test ISO C++0x compatibility portion of TBB recursive mutex -template -void TestRecursiveMutexISO( const char * name ) { - typedef TBB_MutexFromISO_Mutex tbb_from_iso; - TestRecursiveMutex(name); -} - -#include "tbb/task_scheduler_init.h" - -int TestMain () { - for( int p=MinThread; p<=MaxThread; ++p ) { - tbb::task_scheduler_init init( p ); - REMARK( "testing with %d workers\n", static_cast(p) ); -#if TBB_TEST_LOW_WORKLOAD - // The amount of work is decreased in this mode to bring the length - // of the runs under tools into the tolerable limits. - const int n = 1; -#else - const int n = 3; -#endif - // Run each test several times. - for( int i=0; i( "Null Mutex" ); - TestNullMutex( "Null RW Mutex" ); - TestNullRWMutex( "Null RW Mutex" ); - Test( "Spin Mutex" ); -#if _OPENMP - Test( "OpenMP_Mutex" ); -#endif /* _OPENMP */ - Test( "Queuing Mutex" ); - Test( "Wrapper Mutex" ); - Test( "Recursive Mutex" ); - Test( "Queuing RW Mutex" ); - Test( "Spin RW Mutex" ); - - TestTryAcquire_OneThread("Spin Mutex"); - TestTryAcquire_OneThread("Queuing Mutex"); -#if USE_PTHREAD - // under ifdef because on Windows tbb::mutex is reenterable and the test will fail - TestTryAcquire_OneThread("Wrapper Mutex"); -#endif /* USE_PTHREAD */ - TestTryAcquire_OneThread( "Recursive Mutex" ); - TestTryAcquire_OneThread("Spin RW Mutex"); // only tests try_acquire for writers - TestTryAcquire_OneThread("Queuing RW Mutex"); // only tests try_acquire for writers - TestTryAcquireReader_OneThread("Spin RW Mutex"); - TestTryAcquireReader_OneThread("Queuing RW Mutex"); - - TestReaderWriterLock( "Queuing RW Mutex" ); - TestReaderWriterLock( "Spin RW Mutex" ); - - TestRecursiveMutex( "Recursive Mutex" ); - - // Test ISO C++0x interface - TestISO( "ISO Spin Mutex" ); - TestISO( "ISO Mutex" ); - TestISO( "ISO Spin RW Mutex" ); - TestISO( "ISO Recursive Mutex" ); - TestISO( "ISO Critical Section" ); - TestTryAcquire_OneThreadISO( "ISO Spin Mutex" ); -#if USE_PTHREAD - // under ifdef because on Windows tbb::mutex is reenterable and the test will fail - TestTryAcquire_OneThreadISO( "ISO Mutex" ); -#endif /* USE_PTHREAD */ - TestTryAcquire_OneThreadISO( "ISO Spin RW Mutex" ); - TestTryAcquire_OneThreadISO( "ISO Recursive Mutex" ); - TestTryAcquire_OneThreadISO( "ISO Critical Section" ); - TestReaderWriterLockISO( "ISO Spin RW Mutex" ); - TestRecursiveMutexISO( "ISO Recursive Mutex" ); - } - REMARK( "calling destructor for task_scheduler_init\n" ); - } - return Harness::Done; -} diff --git a/deal.II/contrib/tbb/tbb30_104oss/src/test/test_mutex_native_threads.cpp b/deal.II/contrib/tbb/tbb30_104oss/src/test/test_mutex_native_threads.cpp deleted file mode 100644 index ffda4e4d84..0000000000 --- a/deal.II/contrib/tbb/tbb30_104oss/src/test/test_mutex_native_threads.cpp +++ /dev/null @@ -1,224 +0,0 @@ -/* - Copyright 2005-2010 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. -*/ - -#include "tbb/spin_mutex.h" -#include "tbb/queuing_mutex.h" -#include "tbb/queuing_rw_mutex.h" -#include "tbb/spin_rw_mutex.h" -#include "tbb/tick_count.h" -#include "tbb/atomic.h" - -#include "harness.h" - -// This test deliberately avoids a "using tbb" statement, -// so that the error of putting types in the wrong namespace will be caught. - -template -struct Counter { - typedef M mutex_type; - M mutex; - volatile long value; - void flog_once( size_t mode ); -}; - -template -void Counter::flog_once(size_t mode) -/** Increments counter once for each iteration in the iteration space. */ -{ - if( mode&1 ) { - // Try implicit acquire and explicit release - typename mutex_type::scoped_lock lock(mutex); - value = value+1; - lock.release(); - } else { - // Try explicit acquire and implicit release - typename mutex_type::scoped_lock lock; - lock.acquire(mutex); - value = value+1; - } -} - -template -struct Invariant { - typedef M mutex_type; - M mutex; - const char* mutex_name; - volatile long value[N]; - volatile long single_value; - Invariant( const char* mutex_name_ ) : - mutex_name(mutex_name_) - { - single_value = 0; - for( long k=0; k -void Invariant::flog_once( size_t mode ) -{ - //! Every 8th access is a write access - bool write = (mode%8)==7; - bool okay = true; - bool lock_kept = true; - if( (mode/8)&1 ) { - // Try implicit acquire and explicit release - typename mutex_type::scoped_lock lock(mutex,write); - if( write ) { - long my_value = value[0]; - update(); - if( mode%16==7 ) { - lock_kept = lock.downgrade_to_reader(); - if( !lock_kept ) - my_value = value[0] - 1; - okay = value_is(my_value+1); - } - } else { - okay = is_okay(); - if( mode%8==3 ) { - long my_value = value[0]; - lock_kept = lock.upgrade_to_writer(); - if( !lock_kept ) - my_value = value[0]; - update(); - okay = value_is(my_value+1); - } - } - lock.release(); - } else { - // Try explicit acquire and implicit release - typename mutex_type::scoped_lock lock; - lock.acquire(mutex,write); - if( write ) { - long my_value = value[0]; - update(); - if( mode%16==7 ) { - lock_kept = lock.downgrade_to_reader(); - if( !lock_kept ) - my_value = value[0] - 1; - okay = value_is(my_value+1); - } - } else { - okay = is_okay(); - if( mode%8==3 ) { - long my_value = value[0]; - lock_kept = lock.upgrade_to_writer(); - if( !lock_kept ) - my_value = value[0]; - update(); - okay = value_is(my_value+1); - } - } - } - if( !okay ) { - REPORT( "ERROR for %s at %ld: %s %s %s %s\n",mutex_name, long(mode), - write?"write,":"read,", write?(mode%16==7?"downgrade,":""):(mode%8==3?"upgrade,":""), - lock_kept?"lock kept,":"lock not kept,", (mode/8)&1?"imp/exp":"exp/imp" ); - } -} - -static tbb::atomic Order; - -template -struct Work: NoAssign { - static const size_t chunk = 100; - State& state; - Work( State& state_ ) : state(state_) {} - void operator()( int ) const { - size_t step; - while( (step=Order.fetch_and_add(chunk)) -void Test( const char * name, int nthread ) { - REMARK("testing %s\n",name); - Counter counter; - counter.value = 0; - Order = 0; - const long test_size = 100000; - tbb::tick_count t0 = tbb::tick_count::now(); - NativeParallelFor( nthread, Work, test_size>(counter) ); - tbb::tick_count t1 = tbb::tick_count::now(); - - REMARK("%s time = %g usec\n",name, (t1-t0).seconds() ); - if( counter.value!=test_size ) - REPORT("ERROR for %s: counter.value=%ld != %ld=test_size\n",name,counter.value,test_size); -} - - -//! Generic test of TBB ReaderWriterMutex type M -template -void TestReaderWriter( const char * mutex_name, int nthread ) { - REMARK("testing %s\n",mutex_name); - Invariant invariant(mutex_name); - Order = 0; - static const long test_size = 1000000; - tbb::tick_count t0 = tbb::tick_count::now(); - NativeParallelFor( nthread, Work, test_size>(invariant) ); - tbb::tick_count t1 = tbb::tick_count::now(); - // There is either a writer or a reader upgraded to a writer for each 4th iteration - long expected_value = test_size/4; - if( !invariant.value_is(expected_value) ) - REPORT("ERROR for %s: final invariant value is wrong\n",mutex_name); - REMARK("%s readers & writers time = %g usec\n",mutex_name,(t1-t0).seconds()); -} - -int TestMain () { - for( int p=MinThread; p<=MaxThread; ++p ) { - REMARK( "testing with %d threads\n", p ); - Test( "spin_mutex", p ); - Test( "queuing_mutex", p ); - Test( "queuing_rw_mutex", p ); - Test( "spin_rw_mutex", p ); - TestReaderWriter( "queuing_rw_mutex", p ); - TestReaderWriter( "spin_rw_mutex", p ); - } - return Harness::Done; -} diff --git a/deal.II/contrib/tbb/tbb30_104oss/src/test/test_openmp.cpp b/deal.II/contrib/tbb/tbb30_104oss/src/test/test_openmp.cpp deleted file mode 100644 index 9d74a41e72..0000000000 --- a/deal.II/contrib/tbb/tbb30_104oss/src/test/test_openmp.cpp +++ /dev/null @@ -1,230 +0,0 @@ -/* - Copyright 2005-2010 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. -*/ - -// Test mixing OpenMP and TBB - -/* SCR #471 - Bellow is workaround to compile test within enviroment of Intel Compiler - but by Microsoft Compiler. So, there is wrong "omp.h" file included and - manifest section is missed from .exe file - restoring here. - - As of Visual Studio 2010, crtassem.h is no longer shipped. - */ -#if !defined(__INTEL_COMPILER) && _MSC_VER >= 1400 && _MSC_VER < 1600 - #include - #if !defined(_OPENMP) - #define _OPENMP - #if defined(_DEBUG) - #pragma comment(lib, "vcompd") - #else // _DEBUG - #pragma comment(lib, "vcomp") - #endif // _DEBUG - #endif // _OPENMP - - #if defined(_DEBUG) - #if defined(_M_IX86) - #pragma comment(linker,"/manifestdependency:\"type='win32' " \ - "name='" __LIBRARIES_ASSEMBLY_NAME_PREFIX ".DebugOpenMP' " \ - "version='" _CRT_ASSEMBLY_VERSION "' " \ - "processorArchitecture='x86' " \ - "publicKeyToken='" _VC_ASSEMBLY_PUBLICKEYTOKEN "'\"") - #elif defined(_M_AMD64) - #pragma comment(linker,"/manifestdependency:\"type='win32' " \ - "name='" __LIBRARIES_ASSEMBLY_NAME_PREFIX ".DebugOpenMP' " \ - "version='" _CRT_ASSEMBLY_VERSION "' " \ - "processorArchitecture='amd64' " \ - "publicKeyToken='" _VC_ASSEMBLY_PUBLICKEYTOKEN "'\"") - #elif defined(_M_IA64) - #pragma comment(linker,"/manifestdependency:\"type='win32' " \ - "name='" __LIBRARIES_ASSEMBLY_NAME_PREFIX ".DebugOpenMP' " \ - "version='" _CRT_ASSEMBLY_VERSION "' " \ - "processorArchitecture='ia64' " \ - "publicKeyToken='" _VC_ASSEMBLY_PUBLICKEYTOKEN "'\"") - #endif - #else // _DEBUG - #if defined(_M_IX86) - #pragma comment(linker,"/manifestdependency:\"type='win32' " \ - "name='" __LIBRARIES_ASSEMBLY_NAME_PREFIX ".OpenMP' " \ - "version='" _CRT_ASSEMBLY_VERSION "' " \ - "processorArchitecture='x86' " \ - "publicKeyToken='" _VC_ASSEMBLY_PUBLICKEYTOKEN "'\"") - #elif defined(_M_AMD64) - #pragma comment(linker,"/manifestdependency:\"type='win32' " \ - "name='" __LIBRARIES_ASSEMBLY_NAME_PREFIX ".OpenMP' " \ - "version='" _CRT_ASSEMBLY_VERSION "' " \ - "processorArchitecture='amd64' " \ - "publicKeyToken='" _VC_ASSEMBLY_PUBLICKEYTOKEN "'\"") - #elif defined(_M_IA64) - #pragma comment(linker,"/manifestdependency:\"type='win32' " \ - "name='" __LIBRARIES_ASSEMBLY_NAME_PREFIX ".OpenMP' " \ - "version='" _CRT_ASSEMBLY_VERSION "' " \ - "processorArchitecture='ia64' " \ - "publicKeyToken='" _VC_ASSEMBLY_PUBLICKEYTOKEN "'\"") - #endif - #endif // _DEBUG - #define _OPENMP_NOFORCE_MANIFEST -#endif - -#include - - -typedef short T; - -void SerialConvolve( T c[], const T a[], int m, const T b[], int n ) { - for( int i=0; i& range ) { - for( int j=range.begin(); j!=range.end(); ++j ) - sum += my_a[j]*my_b[i-j]; - } -}; - -#if _MSC_VER && !defined(__INTEL_COMPILER) - #pragma warning( pop ) -#endif - -//! Test OpenMMP loop around TBB loop -void OpenMP_TBB_Convolve( T c[], const T a[], int m, const T b[], int n ) { - REMARK("testing OpenMP loop around TBB loop\n"); -#pragma omp parallel - { - task_scheduler_init init; -#pragma omp for - for( int i=0; i(start,finish,10), body ); - c[i] = body.sum; - } - } -} - -class OuterBody: NoAssign { - const T* my_a; - const T* my_b; - T* my_c; - const int m; - const int n; -public: - T sum; - OuterBody( T c[], const T a[], int m_, const T b[], int n_ ) : - my_c(c), my_a(a), my_b(b), m(m_), n(n_) - {} - void operator()( const blocked_range& range ) const { - for( int i=range.begin(); i!=range.end(); ++i ) { - int start = i(0,m+n-1,10), OuterBody( c, a, m, b, n ) ); -} - -#include - -const int M = 17*17; -const int N = 13*13; - -int TestMain () { - MinThread = 1; - for( int p=MinThread; p<=MaxThread; ++p ) { - T a[M]; - T b[N]; - for( int m=1; m<=M; m*=17 ) { - for( int n=1; n<=M; n*=13 ) { - for( int i=0; i g_values_counter; - -class value_t { - size_t x; - value_t& operator= ( const value_t& ); -public: - value_t ( size_t xx ) : x(xx) { ++g_values_counter; } - value_t ( const value_t& v ) : x(v.value()) { ++g_values_counter; } - ~value_t () { --g_values_counter; } - size_t value() const volatile { return x; } -}; - -#include "harness_iterator.h" - -static size_t g_tasks_expected = 0; -static tbb::atomic g_tasks_observed; - -size_t FindNumOfTasks ( size_t max_depth ) { - if( max_depth == 0 ) - return 1; - return max_depth * FindNumOfTasks( max_depth - 1 ) + 1; -} - -//! Simplest form of the parallel_do functor object. -class FakeTaskGeneratorBody { -public: - //! The simplest form of the function call operator - /** It does not allow adding new tasks during its execution. **/ - void operator() ( value_t depth ) const { - g_tasks_observed += FindNumOfTasks(depth.value()); - } -}; - -/** Work item is passed by reference here. **/ -class FakeTaskGeneratorBody_RefVersion { -public: - void operator() ( value_t& depth ) const { - g_tasks_observed += FindNumOfTasks(depth.value()); - } -}; - -/** Work item is passed by reference to const here. **/ -class FakeTaskGeneratorBody_ConstRefVersion { -public: - void operator() ( const value_t& depth ) const { - g_tasks_observed += FindNumOfTasks(depth.value()); - } -}; - -/** Work item is passed by reference to volatile here. **/ -class FakeTaskGeneratorBody_VolatileRefVersion { -public: - void operator() ( volatile value_t& depth, tbb::parallel_do_feeder& ) const { - g_tasks_observed += FindNumOfTasks(depth.value()); - } -}; - -void do_work ( const value_t& depth, tbb::parallel_do_feeder& feeder ) { - ++g_tasks_observed; - size_t d=depth.value(); - --d; - for( size_t i = 0; i < depth.value(); ++i) - feeder.add(value_t(d)); -} - -//! Standard form of the parallel_do functor object. -/** Allows adding new work items on the fly. **/ -class TaskGeneratorBody -{ -public: - //! This form of the function call operator can be used when the body needs to add more work during the processing - void operator() ( value_t depth, tbb::parallel_do_feeder& feeder ) const { - do_work(depth, feeder); - } -private: - // Assert that parallel_do does not ever access body constructors - TaskGeneratorBody () {} - TaskGeneratorBody ( const TaskGeneratorBody& ); - // TestBody() needs access to the default constructor - template friend void TestBody( size_t ); -}; // class TaskGeneratorBody - -/** Work item is passed by reference here. **/ -class TaskGeneratorBody_RefVersion -{ -public: - void operator() ( value_t& depth, tbb::parallel_do_feeder& feeder ) const { - do_work(depth, feeder); - } -}; // class TaskGeneratorBody - -/** Work item is passed as const here. Compilers must ignore the const qualifier. **/ -class TaskGeneratorBody_ConstVersion -{ -public: - void operator() ( const value_t depth, tbb::parallel_do_feeder& feeder ) const { - do_work(depth, feeder); - } -}; // class TaskGeneratorBody - -/** Work item is passed by reference to const here. **/ -class TaskGeneratorBody_ConstRefVersion -{ -public: - void operator() ( const value_t& depth, tbb::parallel_do_feeder& feeder ) const { - do_work(depth, feeder); - } -}; // class TaskGeneratorBody - -/** Work item is passed by reference to volatile here. **/ -class TaskGeneratorBody_VolatileRefVersion -{ -public: - void operator() ( volatile value_t& depth, tbb::parallel_do_feeder& feeder ) const { - do_work(const_cast(depth), feeder); - } -}; // class TaskGeneratorBody - -/** Work item is passed by reference to volatile here. **/ -class TaskGeneratorBody_ConstVolatileRefVersion -{ -public: - void operator() ( const volatile value_t& depth, tbb::parallel_do_feeder& feeder ) const { - do_work(const_cast(depth), feeder); - } -}; // class TaskGeneratorBody - - -static value_t g_depths[N_DEPTHS] = {0, 1, 2, 3, 4, 0, 1, 0, 1, 2, 0, 1, 2, 3, 0, 1, 2, 0, 1, 2}; - -template -void TestBody ( size_t depth ) { - typedef typename std::iterator_traits::value_type value_type; - value_type a_depths[N_DEPTHS] = {0, 1, 2, 3, 4, 0, 1, 0, 1, 2, 0, 1, 2, 3, 0, 1, 2, 0, 1, 2}; - Body body; - Iterator begin(a_depths); - Iterator end(a_depths + depth); - g_tasks_observed = 0; - tbb::parallel_do(begin, end, body); - ASSERT (g_tasks_observed == g_tasks_expected, NULL); -} - -template -void TestIterator_RvalueOnly ( int /*nthread*/, size_t depth ) { - g_values_counter = 0; - TestBody (depth); - TestBody (depth); - TestBody (depth); - TestBody (depth); - TestBody (depth); -} - -template -void TestIterator ( int nthread, size_t depth ) { - TestIterator_RvalueOnly(nthread, depth); - TestBody (depth); - TestBody (depth); - TestBody (depth); - TestBody (depth); - TestBody (depth); -} - -void Run( int nthread ) { - for( size_t depth = 0; depth <= N_DEPTHS; ++depth ) { - g_tasks_expected = 0; - for ( size_t i=0; i < depth; ++i ) - g_tasks_expected += FindNumOfTasks( g_depths[i].value() ); - // Test for iterators over values convertible to work item type - TestIterator_RvalueOnly(nthread, depth); - // Test for random access iterators - TestIterator(nthread, depth); - // Test for input iterators - TestIterator >(nthread, depth); - // Test for forward iterators - TestIterator >(nthread, depth); - } -} - -int TestMain () { - if( MinThread<1 ) { - REPORT("number of threads must be positive\n"); - exit(1); - } - for( int p=MinThread; p<=MaxThread; ++p ) { - tbb::task_scheduler_init init( p ); - Run(p); - // Test that all workers sleep when no work - TestCPUUserTime(p); - } - // This check must be performed after the scheduler terminated because only in this - // case there is a guarantee that the workers already destroyed their last tasks. - ASSERT( g_values_counter == 0, "Value objects were leaked" ); - return Harness::Done; -} diff --git a/deal.II/contrib/tbb/tbb30_104oss/src/test/test_parallel_for.cpp b/deal.II/contrib/tbb/tbb30_104oss/src/test/test_parallel_for.cpp deleted file mode 100644 index 68fe08bf0d..0000000000 --- a/deal.II/contrib/tbb/tbb30_104oss/src/test/test_parallel_for.cpp +++ /dev/null @@ -1,362 +0,0 @@ -/* - Copyright 2005-2010 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. -*/ - -// Test for function template parallel_for.h - -#if _MSC_VER -#pragma warning (push) -#if !defined(__INTEL_COMPILER) - // Suppress pointless "unreachable code" warning. - #pragma warning (disable: 4702) -#endif -#if defined(_Wp64) - // Workaround for overzealous compiler warnings in /Wp64 mode - #pragma warning (disable: 4267) -#endif -#endif //#if _MSC_VER - -#include "tbb/parallel_for.h" -#include "tbb/atomic.h" -#include "harness_assert.h" -#include "harness.h" - -static tbb::atomic FooBodyCount; - -//! An range object whose only public members are those required by the Range concept. -template -class FooRange { - //! Start of range - int start; - - //! Size of range - int size; - FooRange( int start_, int size_ ) : start(start_), size(size_) { - zero_fill(pad, Pad); - pad[Pad-1] = 'x'; - } - template friend void Flog( int nthread ); - template friend class FooBody; - void operator&(); - - char pad[Pad]; -public: - bool empty() const {return size==0;} - bool is_divisible() const {return size>1;} - FooRange( FooRange& original, tbb::split ) : size(original.size/2) { - original.size -= size; - start = original.start+original.size; - ASSERT( original.pad[Pad-1]=='x', NULL ); - pad[Pad-1] = 'x'; - } -}; - -//! An range object whose only public members are those required by the parallel_for.h body concept. -template -class FooBody { - static const int LIVE = 0x1234; - tbb::atomic* array; - int state; - friend class FooRange; - template friend void Flog( int nthread ); - FooBody( tbb::atomic* array_ ) : array(array_), state(LIVE) {} -public: - ~FooBody() { - --FooBodyCount; - for( size_t i=0; i(this)[i] = -1; - } - //! Copy constructor - FooBody( const FooBody& other ) : array(other.array), state(other.state) { - ++FooBodyCount; - ASSERT( state==LIVE, NULL ); - } - void operator()( FooRange& r ) const { - for( int k=0; k Array[N]; - -template -void Flog( int nthread ) { - tbb::tick_count T0 = tbb::tick_count::now(); - for( int i=0; i r( 0, i ); - const FooRange rc = r; - FooBody f( Array ); - const FooBody fc = f; - memset( Array, 0, sizeof(Array) ); - FooBodyCount = 1; - switch (mode) { - case 0: - tbb::parallel_for( rc, fc ); - break; - case 1: - tbb::parallel_for( rc, fc, tbb::simple_partitioner() ); - break; - case 2: - tbb::parallel_for( rc, fc, tbb::auto_partitioner() ); - break; - case 3: { - static tbb::affinity_partitioner affinity; - tbb::parallel_for( rc, fc, affinity ); - } - break; - } - for( int j=0; j1 && FooBodyCount<=nthread ) - __TBB_Yield(); - ASSERT( FooBodyCount==1, NULL ); - } - } - tbb::tick_count T1 = tbb::tick_count::now(); - REMARK("time=%g\tnthread=%d\tpad=%d\n",(T1-T0).seconds(),nthread,int(Pad)); -} - -// Testing parallel_for with step support -const size_t PFOR_BUFFER_TEST_SIZE = 1024; -// test_buffer has some extra items beyound right bound -const size_t PFOR_BUFFER_ACTUAL_SIZE = PFOR_BUFFER_TEST_SIZE + 1024; -size_t pfor_buffer[PFOR_BUFFER_ACTUAL_SIZE]; - -template -class TestFunctor{ -public: - void operator ()(T index) const { - pfor_buffer[index]++; - } -}; - -#if !TBB_USE_EXCEPTIONS && _MSC_VER - // Suppress "C++ exception handler used, but unwind semantics are not enabled" warning in STL headers - #pragma warning (push) - #pragma warning (disable: 4530) -#endif - -#include // std::invalid_argument - -#if !TBB_USE_EXCEPTIONS && _MSC_VER - #pragma warning (pop) -#endif - -template -void TestParallelForWithStepSupport() -{ - const T pfor_buffer_test_size = static_cast(PFOR_BUFFER_TEST_SIZE); - const T pfor_buffer_actual_size = static_cast(PFOR_BUFFER_ACTUAL_SIZE); - // Testing parallel_for with different step values - for (T begin = 0; begin < pfor_buffer_test_size - 1; begin += pfor_buffer_test_size / 10 + 1) { - T step; - for (step = 1; step < pfor_buffer_test_size; step++) { - memset(pfor_buffer, 0, pfor_buffer_actual_size * sizeof(size_t)); - if (step == 1){ - tbb::parallel_for(begin, pfor_buffer_test_size, TestFunctor()); - } else { - tbb::parallel_for(begin, pfor_buffer_test_size, step, TestFunctor()); - } - // Verifying that parallel_for processed all items it should - for (T i = begin; i < pfor_buffer_test_size; i = i + step) { - ASSERT(pfor_buffer[i] == 1, "parallel_for didn't process all required elements"); - pfor_buffer[i] = 0; - } - // Verifying that no extra items were processed and right bound of array wasn't crossed - for (T i = 0; i < pfor_buffer_actual_size; i++) { - ASSERT(pfor_buffer[i] == 0, "parallel_for processed an extra element"); - } - } - } - - // Testing some corner cases - tbb::parallel_for(static_cast(2), static_cast(1), static_cast(1), TestFunctor()); -#if TBB_USE_EXCEPTIONS && !__TBB_THROW_ACROSS_MODULE_BOUNDARY_BROKEN - try{ - tbb::parallel_for(static_cast(1), static_cast(100), static_cast(0), TestFunctor()); // should cause std::invalid_argument - }catch(std::invalid_argument){ - return; - } - catch ( ... ) { - ASSERT ( __TBB_EXCEPTION_TYPE_INFO_BROKEN, "Unrecognized exception. std::invalid_argument is expected" ); - } -#endif /* TBB_USE_EXCEPTIONS && !__TBB_THROW_ACROSS_MODULE_BOUNDARY_BROKEN */ -} - -// Exception support test -#define HARNESS_EH_SIMPLE_MODE 1 -#include "tbb/tbb_exception.h" -#include "harness_eh.h" - -#if TBB_USE_EXCEPTIONS -class test_functor_with_exception { -public: - void operator ()(size_t) const { ThrowTestException(); } -}; - -void TestExceptionsSupport() { - REMARK (__FUNCTION__); - { // Tests version with a step provided - ResetEhGlobals(); - TRY(); - tbb::parallel_for((size_t)0, (size_t)PFOR_BUFFER_TEST_SIZE, (size_t)1, test_functor_with_exception()); - CATCH_AND_ASSERT(); - } - { // Tests version without a step - ResetEhGlobals(); - TRY(); - tbb::parallel_for((size_t)0, (size_t)PFOR_BUFFER_TEST_SIZE, test_functor_with_exception()); - CATCH_AND_ASSERT(); - } -} -#endif /* TBB_USE_EXCEPTIONS */ - -// Cancellation support test -class functor_to_cancel { -public: - void operator()(size_t) const { - ++g_CurExecuted; - CancellatorTask::WaitUntilReady(); - } -}; - -size_t g_worker_task_step = 0; - -class my_worker_pfor_step_task : public tbb::task -{ - tbb::task_group_context &my_ctx; - - tbb::task* execute () { - if (g_worker_task_step == 0){ - tbb::parallel_for((size_t)0, (size_t)PFOR_BUFFER_TEST_SIZE, functor_to_cancel(), my_ctx); - }else{ - tbb::parallel_for((size_t)0, (size_t)PFOR_BUFFER_TEST_SIZE, g_worker_task_step, functor_to_cancel(), my_ctx); - } - return NULL; - } -public: - my_worker_pfor_step_task ( tbb::task_group_context &context_) : my_ctx(context_) { } -}; - -void TestCancellation() -{ - // tests version without a step - g_worker_task_step = 0; - ResetEhGlobals(); - RunCancellationTest(); - - // tests version with step - g_worker_task_step = 1; - ResetEhGlobals(); - RunCancellationTest(); -} - -#include "harness_m128.h" - -#if HAVE_m128 && !__TBB_SSE_STACK_ALIGNMENT_BROKEN -struct SSE_Functor { - ClassWithSSE* Src, * Dst; - SSE_Functor( ClassWithSSE* src, ClassWithSSE* dst ) : Src(src), Dst(dst) {} - - void operator()( tbb::blocked_range& r ) const { - for( int i=r.begin(); i!=r.end(); ++i ) - Dst[i] = Src[i]; - } -}; - -//! Test that parallel_for works with stack-allocated __m128 -void TestSSE() { - ClassWithSSE Array1[N], Array2[N]; - for( int i=0; i(0,N), SSE_Functor(Array1, Array2) ); - for( int i=0; i -#include "tbb/task_scheduler_init.h" -#include "harness_cpu.h" - -int TestMain () { - if( MinThread<1 ) { - REPORT("number of threads must be positive\n"); - exit(1); - } - for( int p=MinThread; p<=MaxThread; ++p ) { - if( p>0 ) { - tbb::task_scheduler_init init( p ); - Flog<1>(p); - Flog<10>(p); - Flog<100>(p); - Flog<1000>(p); - Flog<10000>(p); - - // Testing with different integer types - TestParallelForWithStepSupport(); - TestParallelForWithStepSupport(); - TestParallelForWithStepSupport(); - TestParallelForWithStepSupport(); - TestParallelForWithStepSupport(); - TestParallelForWithStepSupport(); - TestParallelForWithStepSupport(); - TestParallelForWithStepSupport(); - TestParallelForWithStepSupport(); -#if TBB_USE_EXCEPTIONS && !__TBB_THROW_ACROSS_MODULE_BOUNDARY_BROKEN - TestExceptionsSupport(); -#endif /* TBB_USE_EXCEPTIONS && !__TBB_THROW_ACROSS_MODULE_BOUNDARY_BROKEN */ - if (p>1) TestCancellation(); -#if HAVE_m128 && !__TBB_SSE_STACK_ALIGNMENT_BROKEN - TestSSE(); -#endif /* HAVE_m128 */ - - // Test that all workers sleep when no work - TestCPUUserTime(p); - } - } -#if __TBB_THROW_ACROSS_MODULE_BOUNDARY_BROKEN - REPORT("Known issue: exception handling tests are skipped.\n"); -#endif -#if HAVE_m128 && __TBB_SSE_STACK_ALIGNMENT_BROKEN - REPORT("Known issue: stack alignment for SSE not tested.\n"); -#endif - return Harness::Done; -} - -#if _MSC_VER -#pragma warning (pop) -#endif diff --git a/deal.II/contrib/tbb/tbb30_104oss/src/test/test_parallel_for_each.cpp b/deal.II/contrib/tbb/tbb30_104oss/src/test/test_parallel_for_each.cpp deleted file mode 100644 index 320aadff0a..0000000000 --- a/deal.II/contrib/tbb/tbb30_104oss/src/test/test_parallel_for_each.cpp +++ /dev/null @@ -1,191 +0,0 @@ -/* - Copyright 2005-2010 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. -*/ - -#if _MSC_VER && !defined(__INTEL_COMPILER) -#pragma warning(disable: 4180) // "qualifier applied to function type has no meaning; ignored" -#endif - -#include "tbb/parallel_for_each.h" -#include "tbb/task_scheduler_init.h" -#include "tbb/atomic.h" -#include "harness.h" -#include "harness_iterator.h" - -// Some old compilers can't deduce template paremeter type for parallel_for_each -// if the function name is passed without explicit cast to function pointer. -typedef void (*TestFunctionType)(size_t); - -tbb::atomic sum; - -// This function is called via parallel_for_each -void TestFunction (size_t value) { - sum += (unsigned int)value; -} - -const size_t NUMBER_OF_ELEMENTS = 1000; - -// Tests tbb::parallel_for_each functionality -template -void RunPForEachTests() -{ - size_t test_vector[NUMBER_OF_ELEMENTS + 1]; - - sum = 0; - size_t test_sum = 0; - - for (size_t i =0; i < NUMBER_OF_ELEMENTS; i++) { - test_vector[i] = i; - test_sum += i; - } - test_vector[NUMBER_OF_ELEMENTS] = 1000000; // parallel_for_each shouldn't touch this element - - Iterator begin(&test_vector[0]); - Iterator end(&test_vector[NUMBER_OF_ELEMENTS]); - - tbb::parallel_for_each(begin, end, (TestFunctionType)TestFunction); - ASSERT(sum == test_sum, "Not all items of test vector were processed by parallel_for_each"); - ASSERT(test_vector[NUMBER_OF_ELEMENTS] == 1000000, "parallel_for_each processed an extra element"); -} - -typedef void (*TestMutatorType)(size_t&); - -void TestMutator(size_t& value) { - ASSERT(value==0,NULL); - ++sum; - ++value; -} - -//! Test that tbb::parallel_for_each works for mutable iterators. -template -void RunMutablePForEachTests() { - size_t test_vector[NUMBER_OF_ELEMENTS]; - for( size_t i=0; i -void TestExceptionsSupport() -{ - REMARK (__FUNCTION__); - size_t test_vector[NUMBER_OF_ELEMENTS + 1]; - - for (size_t i = 0; i < NUMBER_OF_ELEMENTS; i++) { - test_vector[i] = i; - } - - Iterator begin(&test_vector[0]); - Iterator end(&test_vector[NUMBER_OF_ELEMENTS]); - - TRY(); - tbb::parallel_for_each(begin, end, (TestFunctionType)test_function_with_exception); - CATCH_AND_ASSERT(); -} -#endif /* TBB_USE_EXCEPTIONS */ - -// Cancelation support test -void function_to_cancel(size_t ) { - ++g_CurExecuted; - CancellatorTask::WaitUntilReady(); -} - -template -class my_worker_pforeach_task : public tbb::task -{ - tbb::task_group_context &my_ctx; - - tbb::task* execute () { - size_t test_vector[NUMBER_OF_ELEMENTS + 1]; - for (size_t i = 0; i < NUMBER_OF_ELEMENTS; i++) { - test_vector[i] = i; - } - Iterator begin(&test_vector[0]); - Iterator end(&test_vector[NUMBER_OF_ELEMENTS]); - - tbb::parallel_for_each(begin, end, (TestFunctionType)function_to_cancel); - - return NULL; - } -public: - my_worker_pforeach_task ( tbb::task_group_context &ctx) : my_ctx(ctx) { } -}; - -template -void TestCancellation() -{ - REMARK (__FUNCTION__); - ResetEhGlobals(); - RunCancellationTest, CancellatorTask>(); -} - -#include "harness_cpu.h" - -int TestMain () { - if( MinThread<1 ) { - REPORT("number of threads must be positive\n"); - exit(1); - } - for( int p=MinThread; p<=MaxThread; ++p ) { - tbb::task_scheduler_init init( p ); - RunPForEachTests >(); - RunPForEachTests >(); - RunPForEachTests >(); - RunMutablePForEachTests >(); - RunMutablePForEachTests >(); - -#if TBB_USE_EXCEPTIONS && !__TBB_THROW_ACROSS_MODULE_BOUNDARY_BROKEN - TestExceptionsSupport >(); - TestExceptionsSupport >(); - TestExceptionsSupport >(); -#endif /* TBB_USE_EXCEPTIONS && !__TBB_THROW_ACROSS_MODULE_BOUNDARY_BROKEN */ - if (p > 1) { - TestCancellation >(); - TestCancellation >(); - TestCancellation >(); - } - // Test that all workers sleep when no work - TestCPUUserTime(p); - } -#if __TBB_THROW_ACROSS_MODULE_BOUNDARY_BROKEN - REPORT("Known issue: exception handling tests are skipped.\n"); -#endif - return Harness::Done; -} diff --git a/deal.II/contrib/tbb/tbb30_104oss/src/test/test_parallel_invoke.cpp b/deal.II/contrib/tbb/tbb30_104oss/src/test/test_parallel_invoke.cpp deleted file mode 100644 index e4ce649c34..0000000000 --- a/deal.II/contrib/tbb/tbb30_104oss/src/test/test_parallel_invoke.cpp +++ /dev/null @@ -1,324 +0,0 @@ -/* - Copyright 2005-2010 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. -*/ - -#if _MSC_VER && !defined(__INTEL_COMPILER) -#pragma warning(disable: 4180) // "qualifier applied to function type has no meaning; ignored" -#endif - -#include "tbb/parallel_invoke.h" -#include "tbb/task_scheduler_init.h" -#include "tbb/atomic.h" -#include "tbb/tbb_exception.h" -#include "harness.h" - -#if !defined(__INTEL_COMPILER) -#if defined(_MSC_VER) && _MSC_VER <= 1400 || __GNUC__==3 && __GNUC_MINOR__<=3 || __SUNPRO_CC - #define __TBB_FUNCTION_BY_CONSTREF_IN_TEMPLATE_BROKEN 1 -#endif -#endif - -static const size_t MAX_NUMBER_OF_PINVOKE_ARGS = 10; -tbb::atomic function_counter; - -// Some macros to make the test easier to read - -// 10 functions test0 ... test9 are defined -// pointer to each function is also defined - -#define TEST_FUNCTION(value) void test##value () \ -{ \ - ASSERT(!(function_counter & (1 << value)), "Test function has already been called"); \ - function_counter += 1 << value; \ -} \ -void (*test_pointer##value)(void) = test##value; - -TEST_FUNCTION(0) -TEST_FUNCTION(1) -TEST_FUNCTION(2) -TEST_FUNCTION(3) -TEST_FUNCTION(4) -TEST_FUNCTION(5) -TEST_FUNCTION(6) -TEST_FUNCTION(7) -TEST_FUNCTION(8) -TEST_FUNCTION(9) - -// The same with functors -#define TEST_FUNCTOR(value) class test_functor##value \ -{ \ -public: \ - void operator() () const { \ - function_counter += 1 << value; \ - } \ -} functor##value; - -TEST_FUNCTOR(0) -TEST_FUNCTOR(1) -TEST_FUNCTOR(2) -TEST_FUNCTOR(3) -TEST_FUNCTOR(4) -TEST_FUNCTOR(5) -TEST_FUNCTOR(6) -TEST_FUNCTOR(7) -TEST_FUNCTOR(8) -TEST_FUNCTOR(9) - -#define INIT_TEST function_counter = 0; - -#define VALIDATE_INVOKE_RUN(number_of_args, test_type) \ - ASSERT( (size_t)function_counter == (size_t)(1 << number_of_args) - 1, "parallel_invoke called with " #number_of_args " arguments didn't process all " #test_type); - -// Calls parallel_invoke for different number of arguments -// It can be called with and without user context -template -void call_parallel_invoke( size_t n, F0& f0, F1& f1, F2& f2, F3& f3, F4 &f4, F5 &f5, - F6& f6, F7 &f7, F8 &f8, F9 &f9, tbb::task_group_context* context) { - switch(n) { - default: - ASSERT(false, "number of arguments must be between 2 and 10"); - case 2: - if (context) - tbb::parallel_invoke (f0, f1, *context); - else - tbb::parallel_invoke (f0, f1); - break; - case 3: - if (context) - tbb::parallel_invoke (f0, f1, f2, *context); - else - tbb::parallel_invoke (f0, f1, f2); - break; - case 4: - if(context) - tbb::parallel_invoke (f0, f1, f2, f3, *context); - else - tbb::parallel_invoke (f0, f1, f2, f3); - break; - case 5: - if(context) - tbb::parallel_invoke (f0, f1, f2, f3, f4, *context); - else - tbb::parallel_invoke (f0, f1, f2, f3, f4); - break; - case 6: - if(context) - tbb::parallel_invoke (f0, f1, f2, f3, f4, f5, *context); - else - tbb::parallel_invoke (f0, f1, f2, f3, f4, f5); - break; - case 7: - if(context) - tbb::parallel_invoke (f0, f1, f2, f3, f4, f5, f6, *context); - else - tbb::parallel_invoke (f0, f1, f2, f3, f4, f5, f6); - break; - case 8: - if(context) - tbb::parallel_invoke (f0, f1, f2, f3, f4, f5, f6, f7, *context); - else - tbb::parallel_invoke (f0, f1, f2, f3, f4, f5, f6, f7); - break; - case 9: - if(context) - tbb::parallel_invoke (f0, f1, f2, f3, f4, f5, f6, f7, f8, *context); - else - tbb::parallel_invoke (f0, f1, f2, f3, f4, f5, f6, f7, f8); - break; - case 10: - if(context) - tbb::parallel_invoke (f0, f1, f2, f3, f4, f5, f6, f7, f8, f9, *context); - else - tbb::parallel_invoke (f0, f1, f2, f3, f4, f5, f6, f7, f8, f9); - break; - } -} - -#if !__TBB_FUNCTION_BY_CONSTREF_IN_TEMPLATE_BROKEN -template void aux_invoke(const function& f) { - f(); -} - -bool function_by_constref_in_template_codegen_broken() { - function_counter = 0; - aux_invoke(test1); - return function_counter==0; -} -#endif /* !__TBB_FUNCTION_BY_CONSTREF_IN_TEMPLATE_BROKEN */ - -void test_parallel_invoke() -{ - REMARK (__FUNCTION__); - // Testing with pointers to functions - for (int n = 2; n <=10; n++) - { - INIT_TEST; - call_parallel_invoke(n, test_pointer0, test_pointer1, test_pointer2, test_pointer3, test_pointer4, - test_pointer5, test_pointer6, test_pointer7, test_pointer8, test_pointer9, NULL); - VALIDATE_INVOKE_RUN(n, "pointers to function"); - } - - // Testing parallel_invoke with functors - for (int n = 2; n <=10; n++) - { - INIT_TEST; - call_parallel_invoke(n, functor0, functor1, functor2, functor3, functor4, - functor5, functor6, functor7, functor8, functor9, NULL); - VALIDATE_INVOKE_RUN(n, "functors"); - } - -#if __TBB_FUNCTION_BY_CONSTREF_IN_TEMPLATE_BROKEN - // some old compilers can't cope with passing function name into parallel_invoke -#else - // and some compile but generate broken code that does not call the function - if (function_by_constref_in_template_codegen_broken()) - return; - - // Testing parallel_invoke with functions - for (int n = 2; n <=10; n++) - { - INIT_TEST; - call_parallel_invoke(n, test0, test1, test2, test3, test4, test5, test6, test7, test8, test9, NULL); - VALIDATE_INVOKE_RUN(n, "functions"); - } -#endif -} - -// Exception handling support test - -#define HARNESS_EH_SIMPLE_MODE 1 -#include "harness_eh.h" - -#if TBB_USE_EXCEPTIONS -volatile size_t exception_mask; // each bit represents whether the function should throw exception or not - -// throws exception if corresponding exception_mask bit is set -#define TEST_FUNCTOR_WITH_THROW(value) \ -struct throwing_functor##value { \ - void operator() () const { \ - if (exception_mask & (1 << value)) \ - ThrowTestException(); \ - } \ -} test_with_throw##value; - -TEST_FUNCTOR_WITH_THROW(0) -TEST_FUNCTOR_WITH_THROW(1) -TEST_FUNCTOR_WITH_THROW(2) -TEST_FUNCTOR_WITH_THROW(3) -TEST_FUNCTOR_WITH_THROW(4) -TEST_FUNCTOR_WITH_THROW(5) -TEST_FUNCTOR_WITH_THROW(6) -TEST_FUNCTOR_WITH_THROW(7) -TEST_FUNCTOR_WITH_THROW(8) -TEST_FUNCTOR_WITH_THROW(9) - -void TestExceptionHandling() -{ - REMARK (__FUNCTION__); - for( size_t n = 2; n <= 10; ++n ) { - for( exception_mask = 1; exception_mask < (size_t) (1 << n); ++exception_mask ) { - ResetEhGlobals(); - TRY(); - REMARK("Calling parallel_invoke, number of functions = %d, exception_mask = %d\n", n, exception_mask); - call_parallel_invoke(n, test_with_throw0, test_with_throw1, test_with_throw2, test_with_throw3, - test_with_throw4, test_with_throw5, test_with_throw6, test_with_throw7, test_with_throw8, test_with_throw9, NULL); - CATCH_AND_ASSERT(); - } - } -} -#endif /* TBB_USE_EXCEPTIONS */ - -// Cancelation support test -void function_to_cancel() { - ++g_CurExecuted; - CancellatorTask::WaitUntilReady(); -} - -// The function is used to test cancellation -void simple_test_nothrow (){ - ++g_CurExecuted; -} - -size_t g_numFunctions, - g_functionToCancel; - -class ParInvokeLauncherTask : public tbb::task -{ - tbb::task_group_context &my_ctx; - void(*func_array[10])(void); - - tbb::task* execute () { - func_array[g_functionToCancel] = &function_to_cancel; - call_parallel_invoke(g_numFunctions, func_array[0], func_array[1], func_array[2], func_array[3], - func_array[4], func_array[5], func_array[6], func_array[7], func_array[8], func_array[9], &my_ctx); - return NULL; - } -public: - ParInvokeLauncherTask ( tbb::task_group_context& ctx ) : my_ctx(ctx) { - for (int i = 0; i <=9; ++i) - func_array[i] = &simple_test_nothrow; - } -}; - -void TestCancellation () -{ - REMARK (__FUNCTION__); - for ( int n = 2; n <= 10; ++n ) { - for ( int m = 0; m <= n - 1; ++m ) { - g_numFunctions = n; - g_functionToCancel = m; - ResetEhGlobals(); - RunCancellationTest(); - } - } -} - -//------------------------------------------------------------------------ -// Entry point -//------------------------------------------------------------------------ - -#include "harness_cpu.h" - -int TestMain () { - MinThread = min(MinThread, MaxThread); - ASSERT (MinThread>=1, "Minimal number of threads must be 1 or more"); - for ( int p = MinThread; p <= MaxThread; ++p ) { - tbb::task_scheduler_init init(p); - test_parallel_invoke(); - if (p > 1) { -#if __TBB_THROW_ACROSS_MODULE_BOUNDARY_BROKEN - REPORT("Known issue: exception handling tests are skipped.\n"); -#elif TBB_USE_EXCEPTIONS - TestExceptionHandling(); -#endif /* TBB_USE_EXCEPTIONS */ - TestCancellation(); - } - TestCPUUserTime(p); - } - return Harness::Done; -} diff --git a/deal.II/contrib/tbb/tbb30_104oss/src/test/test_parallel_pipeline.cpp b/deal.II/contrib/tbb/tbb30_104oss/src/test/test_parallel_pipeline.cpp deleted file mode 100644 index e5cd43c9bf..0000000000 --- a/deal.II/contrib/tbb/tbb30_104oss/src/test/test_parallel_pipeline.cpp +++ /dev/null @@ -1,354 +0,0 @@ -/* - Copyright 2005-2010 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. -*/ - -// Before including pipeline.h, set up the variable to count heap allocated -// filter_node objects, and make it known for the header. -int filter_node_count = 0; -#define __TBB_TEST_FILTER_NODE_COUNT filter_node_count -#include "tbb/pipeline.h" - -#include "tbb/atomic.h" -#include "harness.h" - -const int n_tokens = 8; -const int max_counter = 16; -static tbb::atomic output_counter; -static tbb::atomic input_counter; -static tbb::atomic check_type_counter; - -class check_type : Harness::NoAfterlife { - unsigned int id; - bool am_ready; -public: - check_type( ) : id(0), am_ready(false) { - ++check_type_counter; - } - - check_type(const check_type& other) : Harness::NoAfterlife(other) { - other.AssertLive(); - AssertLive(); - id = other.id; - am_ready = other.am_ready; - ++check_type_counter; - } - - ~check_type() { - AssertLive(); - --check_type_counter; - } - unsigned int my_id() { AssertLive(); return id; } - bool is_ready() { AssertLive(); return am_ready; } - void function() { - AssertLive(); - if( id == 0 ) { - id = 1; - am_ready = true; - } - } -}; - -// Filters must be copy-constructible, and be const-qualifiable. -template -class input_filter : Harness::NoAfterlife { -public: - U operator()( tbb::flow_control& control ) const { - AssertLive(); - if( --input_counter < 0 ) { - control.stop(); - } - return U(); // default constructed - } - -}; - -template<> -class input_filter : Harness::NoAfterlife { -public: - void operator()( tbb::flow_control& control ) const { - AssertLive(); - if( --input_counter < 0 ) { - control.stop(); - } - } - -}; - - -template<> -class input_filter : Harness::NoAfterlife { -public: - check_type operator()( tbb::flow_control& control ) const { - AssertLive(); - if( --input_counter < 0 ) { - control.stop(); - } - return check_type( ); // default constructed - } -}; - -template -class middle_filter : Harness::NoAfterlife { -public: - U operator()(T /*my_storage*/) const { - AssertLive(); - return U(); - } -}; - -template<> -class middle_filter : Harness::NoAfterlife { -public: - check_type& operator()( check_type &c) const { - AssertLive(); - ASSERT(!c.my_id(), "bad id value"); - ASSERT(!c.is_ready(), "Already ready" ); - c.function(); - return c; - } - -}; - -template -class output_filter : Harness::NoAfterlife { -public: - void operator()(T) const { - AssertLive(); - output_counter++; - } -}; - -template<> -class output_filter : Harness::NoAfterlife { -public: - void operator()(check_type &c) const { - AssertLive(); - ASSERT(c.my_id(), "unset id value"); - ASSERT(c.is_ready(), "not yet ready"); - output_counter++; - } -}; - -void resetCounters() { - output_counter = 0; - input_counter = max_counter; -} - -void checkCounters() { - ASSERT(output_counter == max_counter, "not all tokens were passed through pipeline"); -} - -static const tbb::filter::mode filter_table[] = { tbb::filter::parallel, tbb::filter::serial_in_order, tbb::filter::serial_out_of_order}; -const unsigned number_of_filter_types = sizeof(filter_table)/sizeof(filter_table[0]); - -typedef tbb::filter_t filter_chain; -typedef tbb::filter::mode mode_array; - -// The filters are passed by value, which forces a temporary copy to be created. This is -// to reproduce the bug where a filter_chain uses refs to filters, which after a call -// would be references to destructed temporaries. -template -void fill_chain( filter_chain &my_chain, mode_array *filter_type, input_filter i_filter, - middle_filter m_filter, output_filter o_filter ) { - my_chain = tbb::make_filter(filter_type[0], i_filter) & - tbb::make_filter(filter_type[1], m_filter) & - tbb::make_filter(filter_type[2], o_filter); -} - -void run_function_spec() { - ASSERT(!filter_node_count, NULL); - REMARK("Testing < void, void > (single filter in pipeline)"); -#if __TBB_LAMBDAS_PRESENT - REMARK( " ( + lambdas)"); -#endif - REMARK("\n"); - input_filter i_filter; - // Test pipeline that contains only one filter - for( unsigned i = 0; i one_filter( filter_table[i], i_filter ); - ASSERT(filter_node_count==1, "some filter nodes left after previous iteration?"); - resetCounters(); - tbb::parallel_pipeline( n_tokens, one_filter ); - // no need to check counters -#if __TBB_LAMBDAS_PRESENT - tbb::atomic counter; - counter = max_counter; - // Construct filter using lambda-syntax when parallel_pipeline() is being run; - tbb::parallel_pipeline( n_tokens, - tbb::make_filter(filter_table[i], [&counter]( tbb::flow_control& control ) { - if( counter-- == 0 ) - control.stop(); - } - ) - ); -#endif - } - ASSERT(!filter_node_count, "filter_node objects leaked"); -} - -template -void run_function(const char *l1, const char *l2) { - ASSERT(!filter_node_count, NULL); - REMARK("Testing < %s, %s >", l1, l2 ); -#if __TBB_LAMBDAS_PRESENT - REMARK( " ( + lambdas)"); -#endif - REMARK("\n"); - - const size_t number_of_filters = 3; - - input_filter i_filter; - middle_filter m_filter; - output_filter o_filter; - - unsigned limit = 1; - // Test pipeline that contains number_of_filters filters - for( unsigned i=0; i filter1( filter_type[0], i_filter ); - tbb::filter_t filter2( filter_type[1], m_filter ); - tbb::filter_t filter3( filter_type[2], o_filter ); - ASSERT(filter_node_count==3, "some filter nodes left after previous iteration?"); - resetCounters(); - // Create filters sequence when parallel_pipeline() is being run - tbb::parallel_pipeline( n_tokens, filter1 & filter2 & filter3 ); - checkCounters(); - - // Create filters sequence partially outside parallel_pipeline() and also when parallel_pipeline() is being run - tbb::filter_t filter12; - filter12 = filter1 & filter2; - resetCounters(); - tbb::parallel_pipeline( n_tokens, filter12 & filter3 ); - checkCounters(); - - tbb::filter_t filter123 = filter12 & filter3; - // Run pipeline twice with the same filter sequence - for( unsigned i = 0; i<2; i++ ) { - resetCounters(); - tbb::parallel_pipeline( n_tokens, filter123 ); - checkCounters(); - } - - // Now copy-construct another filter_t instance, and use it to run pipeline - { - tbb::filter_t copy123( filter123 ); - resetCounters(); - tbb::parallel_pipeline( n_tokens, copy123 ); - checkCounters(); - } - - // Construct filters and create the sequence when parallel_pipeline() is being run - resetCounters(); - tbb::parallel_pipeline( n_tokens, - tbb::make_filter(filter_type[0], i_filter) & - tbb::make_filter(filter_type[1], m_filter) & - tbb::make_filter(filter_type[2], o_filter) ); - checkCounters(); - - // Construct filters, make a copy, destroy the original filters, and run with the copy - int cnt = filter_node_count; - { - tbb::filter_t* p123 = new tbb::filter_t ( - tbb::make_filter(filter_type[0], i_filter) & - tbb::make_filter(filter_type[1], m_filter) & - tbb::make_filter(filter_type[2], o_filter) ); - ASSERT(filter_node_count==cnt+5, "filter node accounting error?"); - tbb::filter_t copy123( *p123 ); - delete p123; - ASSERT(filter_node_count==cnt+5, "filter nodes deleted prematurely?"); - resetCounters(); - tbb::parallel_pipeline( n_tokens, copy123 ); - checkCounters(); - } - - // construct a filter with temporaries - { - tbb::filter_t my_filter; - fill_chain( my_filter, filter_type, i_filter, m_filter, o_filter ); - resetCounters(); - tbb::parallel_pipeline( n_tokens, my_filter ); - checkCounters(); - } - ASSERT(filter_node_count==cnt, "scope ended but filter nodes not deleted?"); - -#if __TBB_LAMBDAS_PRESENT - tbb::atomic counter; - counter = max_counter; - // Construct filters using lambda-syntax and create the sequence when parallel_pipeline() is being run; - resetCounters(); // only need the output_counter reset. - tbb::parallel_pipeline( n_tokens, - tbb::make_filter(filter_type[0], [&counter]( tbb::flow_control& control ) -> type1 { - if( --counter < 0 ) - control.stop(); - return type1(); } - ) & - tbb::make_filter(filter_type[1], []( type1 /*my_storage*/ ) -> type2 { - return type2(); } - ) & - tbb::make_filter(filter_type[2], [] ( type2 ) -> void { - output_counter++; } - ) - ); - checkCounters(); -#endif - } - ASSERT(!filter_node_count, "filter_node objects leaked"); -} - -#include "tbb/task_scheduler_init.h" - -int TestMain() { - // Test with varying number of threads. - for( int nthread=MinThread; nthread<=MaxThread; ++nthread ) { - // Initialize TBB task scheduler - REMARK("\nTesting with nthread=%d\n", nthread); - tbb::task_scheduler_init init(nthread); - - // Run test several times with different types - run_function_spec(); - run_function("size_t", "int"); - run_function("int", "double"); - check_type_counter = 0; - run_function("check_type", "size_t"); - ASSERT(!check_type_counter, "Error in check_type creation/destruction"); - // check_type as the second type in the pipeline only works if check_type - // is also the first type. The middle_filter specialization for - // changes the state of the check_type items, and this is checked in the output_filter - // specialization. - run_function("check_type", "check_type"); - ASSERT(!check_type_counter, "Error in check_type creation/destruction"); - } - return Harness::Done; -} - diff --git a/deal.II/contrib/tbb/tbb30_104oss/src/test/test_parallel_reduce.cpp b/deal.II/contrib/tbb/tbb30_104oss/src/test/test_parallel_reduce.cpp deleted file mode 100644 index c29eb89b06..0000000000 --- a/deal.II/contrib/tbb/tbb30_104oss/src/test/test_parallel_reduce.cpp +++ /dev/null @@ -1,271 +0,0 @@ -/* - Copyright 2005-2010 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. -*/ - -#include "tbb/parallel_reduce.h" -#include "tbb/atomic.h" -#include "harness_assert.h" - -using namespace std; - -static tbb::atomic ForkCount; -static tbb::atomic FooBodyCount; - -//! Class with public interface that is exactly minimal requirements for Range concept -class MinimalRange { - size_t begin, end; - friend class FooBody; - explicit MinimalRange( size_t i ) : begin(0), end(i) {} - friend void Flog( int nthread, bool inteference ); -public: - MinimalRange( MinimalRange& r, tbb::split ) : end(r.end) { - begin = r.end = (r.begin+r.end)/2; - } - bool is_divisible() const {return end-begin>=2;} - bool empty() const {return begin==end;} -}; - -//! Class with public interface that is exactly minimal requirements for Body of a parallel_reduce -class FooBody { -private: - FooBody( const FooBody& ); // Deny access - void operator=( const FooBody& ); // Deny access - friend void Flog( int nthread, bool interference ); - //! Parent that created this body via split operation. NULL if original body. - FooBody* parent; - //! Total number of index values processed by body and its children. - size_t sum; - //! Number of join operations done so far on this body and its children. - long join_count; - //! Range that has been processed so far by this body and its children. - size_t begin, end; - //! True if body has not yet been processed at least once by operator(). - bool is_new; - //! 1 if body was created by split; 0 if original body. - int forked; - FooBody() {++FooBodyCount;} -public: - ~FooBody() { - forked = 0xDEADBEEF; - sum=0xDEADBEEF; - join_count=0xDEADBEEF; - --FooBodyCount; - } - FooBody( FooBody& other, tbb::split ) { - ++FooBodyCount; - ++ForkCount; - sum = 0; - parent = &other; - join_count = 0; - is_new = true; - forked = 1; - } - void join( FooBody& s ) { - ASSERT( s.forked==1, NULL ); - ASSERT( this!=&s, NULL ); - ASSERT( this==s.parent, NULL ); - ASSERT( end==s.begin, NULL ); - end = s.end; - sum += s.sum; - join_count += s.join_count + 1; - s.forked = 2; - } - void operator()( const MinimalRange& r ) { - for( size_t k=r.begin; k -#include "harness.h" -#include "tbb/tick_count.h" - -void Flog( int nthread, bool interference=false ) { - for (int mode = 0; mode < 4; mode++) { - tbb::tick_count T0 = tbb::tick_count::now(); - long join_count = 0; - tbb::affinity_partitioner ap; - for( size_t i=0; i<=1000; ++i ) { - FooBody f; - f.sum = 0; - f.parent = NULL; - f.join_count = 0; - f.is_new = true; - f.forked = 0; - f.begin = ~size_t(0); - f.end = ~size_t(0); - ASSERT( FooBodyCount==1, NULL ); - switch (mode) { - case 0: - tbb::parallel_reduce( MinimalRange(i), f ); - break; - case 1: - tbb::parallel_reduce( MinimalRange(i), f, tbb::simple_partitioner() ); - break; - case 2: - tbb::parallel_reduce( MinimalRange(i), f, tbb::auto_partitioner() ); - break; - case 3: - tbb::parallel_reduce( MinimalRange(i), f, ap ); - break; - } - join_count += f.join_count; - ASSERT( FooBodyCount==1, NULL ); - ASSERT( f.sum==i, NULL ); - ASSERT( f.begin==(i==0 ? ~size_t(0) : 0), NULL ); - ASSERT( f.end==(i==0 ? ~size_t(0) : i), NULL ); - } - tbb::tick_count T1 = tbb::tick_count::now(); - REMARK("time=%g join_count=%ld ForkCount=%ld nthread=%d%s\n", - (T1-T0).seconds(),join_count,long(ForkCount), nthread, interference ? " with interference)":""); - } -} - -class DeepThief: public tbb::task { - /*override*/tbb::task* execute() { - if( !is_stolen_task() ) - spawn(*child); - wait_for_all(); - return NULL; - } - task* child; - friend void FlogWithInterference(int); -public: - DeepThief() : child() {} -}; - -//! Test for problem in TBB 2.1 parallel_reduce where middle of a range is stolen. -/** Warning: this test is a somewhat abusive use of TBB somewhat because - it requires two or more threads to avoid deadlock. */ -void FlogWithInterference( int nthread ) { - ASSERT( nthread>=2, "requires too or more threads" ); - - // Build linear chain of tasks. - // The purpose is to drive up "task depth" in TBB 2.1. - // An alternative would be to use add_to_depth, but that method is deprecated in TBB 2.2, - // and this way we generalize to catching problems with implicit depth calculations. - tbb::task* root = new( tbb::task::allocate_root() ) tbb::empty_task; - root->set_ref_count(2); - tbb::task* t = root; - for( int i=0; i<3; ++i ) { - t = new( t->allocate_child() ) tbb::empty_task; - t->set_ref_count(1); - } - - // Append a DeepThief to the chain. - DeepThief* deep_thief = new( t->allocate_child() ) DeepThief; - deep_thief->set_ref_count(2); - - // Append a leaf to the chain. - tbb::task* leaf = new( deep_thief->allocate_child() ) tbb::empty_task; - deep_thief->child = leaf; - - root->spawn(*deep_thief); - - Flog(nthread,true); - - if( root->ref_count()==2 ) { - // Spawn leaf, which when it finishes, cause the DeepThief and rest of the chain to finish. - root->spawn( *leaf ); - } - // Wait for all tasks in the chain from root to leaf to finish. - root->wait_for_all(); - root->destroy( *root ); -} - -#include "tbb/blocked_range.h" - -#if _MSC_VER - typedef tbb::internal::uint64_t ValueType; -#else - typedef uint64_t ValueType; -#endif - -struct Sum { - template - T operator() ( const T& v1, const T& v2 ) const { - return v1 + v2; - } -}; - -struct Accumulator { - ValueType operator() ( const tbb::blocked_range& r, ValueType value ) const { - for ( ValueType* pv = r.begin(); pv != r.end(); ++pv ) - value += *pv; - return value; - } -}; - -void ParallelSum () { - const ValueType I = 0, - N = 1000000, - R = N * (N + 1) / 2; - ValueType *array = new ValueType[N + 1]; - for ( ValueType i = 0; i < N; ++i ) - array[i] = i + 1; - tbb::blocked_range range(array, array + N); - ValueType r1 = tbb::parallel_reduce( range, I, Accumulator(), Sum() ); - ASSERT( r1 == R, NULL ); -#if __TBB_LAMBDAS_PRESENT - ValueType r2 = tbb::parallel_reduce( range, I, - [](const tbb::blocked_range& r, ValueType value) -> ValueType { - for ( ValueType* pv = r.begin(); pv != r.end(); ++pv ) - value += *pv; - return value; - }, - Sum() - ); - ASSERT( r2 == R, NULL ); -#endif /* LAMBDAS */ - delete array; -} - -#include "tbb/task_scheduler_init.h" -#include "harness_cpu.h" - -int TestMain () { - if( MinThread<0 ) { - REPORT("Usage: nthread must be positive\n"); - exit(1); - } - for( int p=MinThread; p<=MaxThread; ++p ) { - tbb::task_scheduler_init init( p ); - Flog(p); - if( p>=2 ) - FlogWithInterference(p); - ParallelSum(); - // Test that all workers sleep when no work - TestCPUUserTime(p); - } - return Harness::Done; -} diff --git a/deal.II/contrib/tbb/tbb30_104oss/src/test/test_parallel_scan.cpp b/deal.II/contrib/tbb/tbb30_104oss/src/test/test_parallel_scan.cpp deleted file mode 100644 index ac9f2435ac..0000000000 --- a/deal.II/contrib/tbb/tbb30_104oss/src/test/test_parallel_scan.cpp +++ /dev/null @@ -1,270 +0,0 @@ -/* - Copyright 2005-2010 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. -*/ - -#include "tbb/parallel_scan.h" -#include "tbb/blocked_range.h" -#include "harness_assert.h" - -typedef tbb::blocked_range Range; - -static volatile bool ScanIsRunning = false; - -//! Sum of 0..i with wrap around on overflow. -inline int TriangularSum( int i ) { - return i&1 ? ((i>>1)+1)*i : (i>>1)*(i+1); -} - -//! Verify that sum is sum of integers in closed interval [start_index..finish_index]. -/** line should be the source line of the caller */ -static void VerifySum( long start_index, long finish_index, int sum, int line ); - -const int MAXN = 2000; - -enum AddendFlag { - UNUSED=0, - USED_NONFINAL=1, - USED_FINAL=2 -}; - -//! Array recording how each addend was used. -/** 'unsigned char' instead of AddendFlag for sake of compactness. */ -static unsigned char AddendHistory[MAXN]; - -//! Set to 1 for debugging output -#define PRINT_DEBUG 0 - -#include "tbb/atomic.h" -#if PRINT_DEBUG -#include -tbb::atomic NextBodyId; -#endif /* PRINT_DEBUG */ - -struct BodyId { -#if PRINT_DEBUG - const int id; - BodyId() : id(NextBodyId++) {} -#endif /* PRINT_DEBUG */ -}; - -tbb::atomic NumberOfLiveAccumulator; - -static void Snooze( bool scan_should_be_running ) { - ASSERT( ScanIsRunning==scan_should_be_running, NULL ); -} - -template -class Accumulator: BodyId { - T my_total; - const T* my_array; - T* my_sum; - Range my_range; - //! Equals this while object is fully constructed, NULL otherwise. - /** Used to detect premature destruction and accidental bitwise copy. */ - Accumulator* self; - Accumulator( const T array[], T sum[] ) : - my_total(), my_array(array), my_sum(sum), my_range(-1,-1,1) - { - ++NumberOfLiveAccumulator; - // Set self as last action of constructor, to indicate that object is fully constructed. - self = this; - } - friend void TestAccumulator( int mode, int nthread ); -public: -#if PRINT_DEBUG - void print() const { - REPORT("%d [%ld..%ld)\n", id,my_range.begin(),my_range.end() ); - } -#endif /* PRINT_DEBUG */ - ~Accumulator() { -#if PRINT_DEBUG - REPORT("%d [%ld..%ld) destroyed\n",id,my_range.begin(),my_range.end() ); -#endif /* PRINT_DEBUG */ - // Clear self as first action of destructor, to indicate that object is not fully constructed. - self = 0; - --NumberOfLiveAccumulator; - } - Accumulator( Accumulator& a, tbb::split ) : - my_total(0), my_array(a.my_array), my_sum(a.my_sum), my_range(-1,-1,1) - { - ++NumberOfLiveAccumulator; -#if PRINT_DEBUG - REPORT("%d forked from %d\n",id,a.id); -#endif /* PRINT_DEBUG */ - Snooze(true); - // Set self as last action of constructor, to indicate that object is fully constructed. - self = this; - } - template - void operator()( const Range& r, Tag /*tag*/ ) { - Snooze(true); -#if PRINT_DEBUG - if( my_range.empty() ) - REPORT("%d computing %s [%ld..%ld)\n",id,Tag::is_final_scan()?"final":"lookahead",r.begin(),r.end() ); - else - REPORT("%d computing %s [%ld..%ld) [%ld..%ld)\n",id,Tag::is_final_scan()?"final":"lookahead",my_range.begin(),my_range.end(),r.begin(),r.end()); -#endif /* PRINT_DEBUG */ - ASSERT( !Tag::is_final_scan() || (my_range.begin()==0 && my_range.end()==r.begin()) || (my_range.empty() && r.begin()==0), NULL ); - for( long i=r.begin(); i acc( addend, sum ); - tbb::tick_count t0 = tbb::tick_count::now(); -#if PRINT_DEBUG - REPORT("--------- mode=%d range=[0..%ld)\n",mode,n); -#endif /* PRINT_DEBUG */ - ScanIsRunning = true; - - switch (mode) { - case 0: - tbb::parallel_scan( Range( 0, n, 1 ), acc ); - break; - case 1: - tbb::parallel_scan( Range( 0, n, 1 ), acc, tbb::simple_partitioner() ); - break; - case 2: - tbb::parallel_scan( Range( 0, n, 1 ), acc, tbb::auto_partitioner() ); - break; - } - - ScanIsRunning = false; -#if PRINT_DEBUG - REPORT("=========\n"); -#endif /* PRINT_DEBUG */ - Snooze(false); - tbb::tick_count t1 = tbb::tick_count::now(); - long used_once_count = 0; - for( long i=0; i -#include - -#if !TBB_USE_EXCEPTIONS && _MSC_VER - // Suppress "C++ exception handler used, but unwind semantics are not enabled" warning in STL headers - #pragma warning (push) - #pragma warning (disable: 4530) -#endif - -#include -#include -#include -#include -#include - -#if !TBB_USE_EXCEPTIONS && _MSC_VER - #pragma warning (pop) -#endif - -/** Has tightly controlled interface so that we can verify - that parallel_sort uses only the required interface. */ -class Minimal { - int val; -public: - Minimal() {} - void set_val(int i) { val = i; } - static bool CompareWith (const Minimal &a, const Minimal &b) { - return (a.val < b.val); - } - static bool AreEqual( Minimal &a, Minimal &b) { - return a.val == b.val; - } -}; - -//! Defines a comparison function object for Minimal -class MinimalCompare { -public: - bool operator() (const Minimal &a, const Minimal &b) const { - return Minimal::CompareWith(a,b); - } -}; - -//! The default validate; but it uses operator== which is not required -template -bool Validate(RandomAccessIterator a, RandomAccessIterator b, size_t n) { - for (size_t i = 0; i < n; i++) { - ASSERT( a[i] == b[i], NULL ); - } - return true; -} - -//! A Validate specialized to string for debugging-only -template<> -bool Validate(std::string * a, std::string * b, size_t n) { - for (size_t i = 0; i < n; i++) { - if ( Verbose && a[i] != b[i]) { - for (size_t j = 0; j < n; j++) { - REPORT("a[%llu] == %s and b[%llu] == %s\n", static_cast(j), a[j].c_str(), static_cast(j), b[j].c_str()); - } - } - ASSERT( a[i] == b[i], NULL ); - } - return true; -} - -//! A Validate specialized to Minimal since it does not define an operator== -template<> -bool Validate(Minimal *a, Minimal *b, size_t n) { - for (size_t i = 0; i < n; i++) { - ASSERT( Minimal::AreEqual(a[i],b[i]), NULL ); - } - return true; -} - -//! A Validate specialized to concurrent_vector since it does not define an operator== -template<> -bool Validate::iterator>(tbb::concurrent_vector::iterator a, - tbb::concurrent_vector::iterator b, size_t n) { - for (size_t i = 0; i < n; i++) { - ASSERT( Minimal::AreEqual(a[i],b[i]), NULL ); - } - return true; -} - -//! used in Verbose mode for identifying which data set is being used -static std::string test_type; - -//! The default initialization routine. -/*! This routine assumes that you can assign to the elements from a float. - It assumes that iter and sorted_list have already been allocated. It fills - them according to the current data set (tracked by a local static variable). - Returns true if a valid test has been setup, or false if there is no test to - perform. -*/ - -template < typename RandomAccessIterator, typename Compare > -bool init_iter(RandomAccessIterator iter, RandomAccessIterator sorted_list, size_t n, const Compare &compare, bool reset) { - static char test_case = 0; - const char num_cases = 3; - - if (reset) test_case = 0; - - if (test_case < num_cases) { - // switch on the current test case, filling the iter and sorted_list appropriately - switch(test_case) { - case 0: - /* use sin to generate the values */ - test_type = "sin"; - for (size_t i = 0; i < n; i++) - iter[i] = sorted_list[i] = static_cast::value_type>(sin(float(i))); - break; - case 1: - /* presorted list */ - test_type = "pre-sorted"; - for (size_t i = 0; i < n; i++) - iter[i] = sorted_list[i] = static_cast::value_type>(i); - break; - case 2: - /* reverse-sorted list */ - test_type = "reverse-sorted"; - for (size_t i = 0; i < n; i++) - iter[i] = sorted_list[i] = static_cast::value_type>(n - i); - break; - } - - // pre-sort sorted_list for later validity testing - std::sort(sorted_list, sorted_list + n, compare); - test_case++; - return true; - } - return false; -} - -template < typename T, typename Compare > -bool init_iter(T * iter, T * sorted_list, size_t n, const Compare &compare, bool reset) { - static char test_case = 0; - const char num_cases = 3; - - if (reset) test_case = 0; - - if (test_case < num_cases) { - // switch on the current test case, filling the iter and sorted_list appropriately - switch(test_case) { - case 0: - /* use sin to generate the values */ - test_type = "sin"; - for (size_t i = 0; i < n; i++) - iter[i] = sorted_list[i] = T(sin(float(i))); - break; - case 1: - /* presorted list */ - test_type = "pre-sorted"; - for (size_t i = 0; i < n; i++) - iter[i] = sorted_list[i] = T(i); - break; - case 2: - /* reverse-sorted list */ - test_type = "reverse-sorted"; - for (size_t i = 0; i < n; i++) - iter[i] = sorted_list[i] = T(n - i); - break; - } - - // pre-sort sorted_list for later validity testing - std::sort(sorted_list, sorted_list + n, compare); - test_case++; - return true; - } - return false; -} - - -//! The initialization routine specialized to the class Minimal -/*! Minimal cannot have floats assigned to it. This function uses the set_val method -*/ - -template < > -bool init_iter(Minimal* iter, Minimal * sorted_list, size_t n, const MinimalCompare &compare, bool reset) { - static char test_case = 0; - const char num_cases = 3; - - if (reset) test_case = 0; - - if (test_case < num_cases) { - switch(test_case) { - case 0: - /* use sin to generate the values */ - test_type = "sin"; - for (size_t i = 0; i < n; i++) { - iter[i].set_val( int( sin( float(i) ) * 1000.f) ); - sorted_list[i].set_val( int ( sin( float(i) ) * 1000.f) ); - } - break; - case 1: - /* presorted list */ - test_type = "pre-sorted"; - for (size_t i = 0; i < n; i++) { - iter[i].set_val( int(i) ); - sorted_list[i].set_val( int(i) ); - } - break; - case 2: - /* reverse-sorted list */ - test_type = "reverse-sorted"; - for (size_t i = 0; i < n; i++) { - iter[i].set_val( int(n-i) ); - sorted_list[i].set_val( int(n-i) ); - } - break; - } - std::sort(sorted_list, sorted_list + n, compare); - test_case++; - return true; - } - return false; -} - -//! The initialization routine specialized to the class concurrent_vector -/*! Minimal cannot have floats assigned to it. This function uses the set_val method -*/ - -template < > -bool init_iter(tbb::concurrent_vector::iterator iter, tbb::concurrent_vector::iterator sorted_list, - size_t n, const MinimalCompare &compare, bool reset) { - static char test_case = 0; - const char num_cases = 3; - - if (reset) test_case = 0; - - if (test_case < num_cases) { - switch(test_case) { - case 0: - /* use sin to generate the values */ - test_type = "sin"; - for (size_t i = 0; i < n; i++) { - iter[i].set_val( int( sin( float(i) ) * 1000.f) ); - sorted_list[i].set_val( int ( sin( float(i) ) * 1000.f) ); - } - break; - case 1: - /* presorted list */ - test_type = "pre-sorted"; - for (size_t i = 0; i < n; i++) { - iter[i].set_val( int(i) ); - sorted_list[i].set_val( int(i) ); - } - break; - case 2: - /* reverse-sorted list */ - test_type = "reverse-sorted"; - for (size_t i = 0; i < n; i++) { - iter[i].set_val( int(n-i) ); - sorted_list[i].set_val( int(n-i) ); - } - break; - } - std::sort(sorted_list, sorted_list + n, compare); - test_case++; - return true; - } - return false; -} - -//! The initialization routine specialized to the class string -/*! strings are created from floats. -*/ - -template<> -bool init_iter(std::string *iter, std::string *sorted_list, size_t n, const std::less &compare, bool reset) { - static char test_case = 0; - const char num_cases = 1; - - if (reset) test_case = 0; - - if (test_case < num_cases) { - switch(test_case) { - case 0: - /* use sin to generate the values */ - test_type = "sin"; - for (size_t i = 0; i < n; i++) { - char buffer[20]; -#if __STDC_SECURE_LIB__>=200411 && !__MINGW64__ - sprintf_s(buffer, sizeof(buffer), "%f", float(sin(float(i)))); -#else - sprintf(buffer, "%f", float(sin(float(i)))); -#endif /* _MSC_VER>=1400 */ - sorted_list[i] = iter[i] = std::string(buffer); - } - break; - } - std::sort(sorted_list, sorted_list + n, compare); - test_case++; - return true; - } - return false; -} - -//! The current number of threads in use (for Verbose only) -static size_t current_p; - -//! The current data type being sorted (for Verbose only) -static std::string current_type; - -//! The default test routine. -/*! Tests all data set sizes from 0 to N, all grainsizes from 0 to G=10, and selects from - all possible interfaces to parallel_sort depending on whether a scratch space and - compare have been provided. -*/ -template -bool parallel_sortTest(size_t n, RandomAccessIterator iter, RandomAccessIterator sorted_list, const Compare *comp) { - bool passed = true; - - Compare local_comp; - - init_iter(iter, sorted_list, n, local_comp, true); - do { - REMARK("%s %s p=%llu n=%llu :",current_type.c_str(), test_type.c_str(), - static_cast(current_p), static_cast(n)); - if (comp != NULL) { - tbb::parallel_sort(iter, iter + n, local_comp ); - } else { - tbb::parallel_sort(iter, iter + n ); - } - if (!Validate(iter, sorted_list, n)) - passed = false; - REMARK("passed\n"); - } while (init_iter(iter, sorted_list, n, local_comp, false)); - return passed; -} - -//! The test routine specialize to Minimal, since it does not have a less defined for it -template<> -bool parallel_sortTest(size_t n, Minimal * iter, Minimal * sorted_list, const MinimalCompare *compare) { - bool passed = true; - - if (compare == NULL) return passed; - - init_iter(iter, sorted_list, n, *compare, true); - do { - REMARK("%s %s p=%llu n=%llu :",current_type.c_str(), test_type.c_str(), - static_cast(current_p), static_cast(n)); - - tbb::parallel_sort(iter, iter + n, *compare ); - - if (!Validate(iter, sorted_list, n)) - passed = false; - REMARK("passed\n"); - } while (init_iter(iter, sorted_list, n, *compare, false)); - return passed; -} - -//! The test routine specialize to concurrent_vector of Minimal, since it does not have a less defined for it -template<> -bool parallel_sortTest(size_t n, tbb::concurrent_vector::iterator iter, - tbb::concurrent_vector::iterator sorted_list, const MinimalCompare *compare) { - bool passed = true; - - if (compare == NULL) return passed; - - init_iter(iter, sorted_list, n, *compare, true); - do { - REMARK("%s %s p=%llu n=%llu :",current_type.c_str(), test_type.c_str(), - static_cast(current_p), static_cast(n)); - - tbb::parallel_sort(iter, iter + n, *compare ); - - if (!Validate(iter, sorted_list, n)) - passed = false; - REMARK("passed\n"); - } while (init_iter(iter, sorted_list, n, *compare, false)); - return passed; -} - -//! The main driver for the tests. -/*! Minimal, float and string types are used. All interfaces to parallel_sort that are usable - by each type are tested. -*/ -void Flog() { - // For each type create: - // the list to be sorted by parallel_sort (array) - // the list to be sort by STL sort (array_2) - // and a less function object - - const size_t N = 50000; - - Minimal *minimal_array = new Minimal[N]; - Minimal *minimal_array_2 = new Minimal[N]; - MinimalCompare minimal_less; - - float *float_array = new float[N]; - float *float_array_2 = new float[N]; - std::less float_less; - - tbb::concurrent_vector float_cv1; - tbb::concurrent_vector float_cv2; - float_cv1.grow_to_at_least(N); - float_cv2.grow_to_at_least(N); - - std::string *string_array = new std::string[N]; - std::string *string_array_2 = new std::string[N]; - std::less string_less; - - tbb::concurrent_vector minimal_cv1; - tbb::concurrent_vector minimal_cv2; - minimal_cv1.grow_to_at_least(N); - minimal_cv2.grow_to_at_least(N); - - - // run the appropriate tests for each type - - current_type = "Minimal(less)"; - parallel_sortTest(0, minimal_array, minimal_array_2, &minimal_less); - parallel_sortTest(1, minimal_array, minimal_array_2, &minimal_less); - parallel_sortTest(10, minimal_array, minimal_array_2, &minimal_less); - parallel_sortTest(9999, minimal_array, minimal_array_2, &minimal_less); - parallel_sortTest(50000, minimal_array, minimal_array_2, &minimal_less); - - current_type = "float (no less)"; - parallel_sortTest(0, float_array, float_array_2, static_cast *>(NULL)); - parallel_sortTest(1, float_array, float_array_2, static_cast *>(NULL)); - parallel_sortTest(10, float_array, float_array_2, static_cast *>(NULL)); - parallel_sortTest(9999, float_array, float_array_2, static_cast *>(NULL)); - parallel_sortTest(50000, float_array, float_array_2, static_cast *>(NULL)); - - current_type = "float (less)"; - parallel_sortTest(0, float_array, float_array_2, &float_less); - parallel_sortTest(1, float_array, float_array_2, &float_less); - parallel_sortTest(10, float_array, float_array_2, &float_less); - parallel_sortTest(9999, float_array, float_array_2, &float_less); - parallel_sortTest(50000, float_array, float_array_2, &float_less); - - current_type = "concurrent_vector (no less)"; - parallel_sortTest(0, float_cv1.begin(), float_cv2.begin(), static_cast *>(NULL)); - parallel_sortTest(1, float_cv1.begin(), float_cv2.begin(), static_cast *>(NULL)); - parallel_sortTest(10, float_cv1.begin(), float_cv2.begin(), static_cast *>(NULL)); - parallel_sortTest(9999, float_cv1.begin(), float_cv2.begin(), static_cast *>(NULL)); - parallel_sortTest(50000, float_cv1.begin(), float_cv2.begin(), static_cast *>(NULL)); - - current_type = "concurrent_vector (less)"; - parallel_sortTest(0, float_cv1.begin(), float_cv2.begin(), &float_less); - parallel_sortTest(1, float_cv1.begin(), float_cv2.begin(), &float_less); - parallel_sortTest(10, float_cv1.begin(), float_cv2.begin(), &float_less); - parallel_sortTest(9999, float_cv1.begin(), float_cv2.begin(), &float_less); - parallel_sortTest(50000, float_cv1.begin(), float_cv2.begin(), &float_less); - - current_type = "string (no less)"; - parallel_sortTest(0, string_array, string_array_2, static_cast *>(NULL)); - parallel_sortTest(1, string_array, string_array_2, static_cast *>(NULL)); - parallel_sortTest(10, string_array, string_array_2, static_cast *>(NULL)); - parallel_sortTest(9999, string_array, string_array_2, static_cast *>(NULL)); - parallel_sortTest(50000, string_array, string_array_2, static_cast *>(NULL)); - - current_type = "string (less)"; - parallel_sortTest(0, string_array, string_array_2, &string_less); - parallel_sortTest(1, string_array, string_array_2, &string_less); - parallel_sortTest(10, string_array, string_array_2, &string_less); - parallel_sortTest(9999, string_array, string_array_2, &string_less); - parallel_sortTest(50000, string_array, string_array_2, &string_less); - - current_type = "concurrent_vector (less)"; - parallel_sortTest(0, minimal_cv1.begin(), minimal_cv2.begin(), &minimal_less); - parallel_sortTest(1, minimal_cv1.begin(), minimal_cv2.begin(), &minimal_less); - parallel_sortTest(10, minimal_cv1.begin(), minimal_cv2.begin(), &minimal_less); - parallel_sortTest(9999, minimal_cv1.begin(), minimal_cv2.begin(), &minimal_less); - parallel_sortTest(50000, minimal_cv1.begin(), minimal_cv2.begin(), &minimal_less); - - delete [] minimal_array; - delete [] minimal_array_2; - - delete [] float_array; - delete [] float_array_2; - - delete [] string_array; - delete [] string_array_2; -} - -#include -#include "harness_cpu.h" - -int TestMain () { - if( MinThread<1 ) { - REPORT("Usage: number of threads must be positive\n"); - exit(1); - } - for( int p=MinThread; p<=MaxThread; ++p ) { - if( p>0 ) { - tbb::task_scheduler_init init( p ); - current_p = p; - Flog(); - - // Test that all workers sleep when no work - TestCPUUserTime(p); - } - } - return Harness::Done; -} - diff --git a/deal.II/contrib/tbb/tbb30_104oss/src/test/test_parallel_while.cpp b/deal.II/contrib/tbb/tbb30_104oss/src/test/test_parallel_while.cpp deleted file mode 100644 index 88f799794e..0000000000 --- a/deal.II/contrib/tbb/tbb30_104oss/src/test/test_parallel_while.cpp +++ /dev/null @@ -1,179 +0,0 @@ -/* - Copyright 2005-2010 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. -*/ - -#include "tbb/parallel_while.h" -#include "harness.h" - -const int N = 200; - -typedef int Element; - -//! Representation of an array index with only those signatures required by parallel_while. -class MinimalArgumentType { - void operator=( const MinimalArgumentType& ); - long my_value; - enum { - DEAD=0xDEAD, - LIVE=0x2718, - INITIALIZED=0x3141 - } my_state; -public: - ~MinimalArgumentType() { - ASSERT( my_state==LIVE||my_state==INITIALIZED, NULL ); - my_state = DEAD; - } - MinimalArgumentType() { - my_state = LIVE; - } - void set_value( long i ) { - ASSERT( my_state==LIVE||my_state==INITIALIZED, NULL ); - my_value = i; - my_state = INITIALIZED; - } - long get_value() const { - ASSERT( my_state==INITIALIZED, NULL ); - return my_value; - } -}; - -class IntegerStream { - long my_limit; - long my_index; -public: - IntegerStream( long n ) : my_limit(n), my_index(0) {} - bool pop_if_present( MinimalArgumentType& v ) { - if( my_index>=my_limit ) - return false; - v.set_value( my_index ); - my_index+=2; - return true; - } -}; - -class MatrixMultiplyBody: NoAssign { - Element (*a)[N]; - Element (*b)[N]; - Element (*c)[N]; - const int n; - tbb::parallel_while& my_while; -public: - typedef MinimalArgumentType argument_type; - void operator()( argument_type i_arg ) const { - long i = i_arg.get_value(); - if( (i&1)==0 && i+1& w, Element c_[N][N], Element a_[N][N], Element b_[N][N], int n_ ) : - a(a_), b(b_), c(c_), n(n_), my_while(w) - {} -}; - -void WhileMatrixMultiply( Element c[N][N], Element a[N][N], Element b[N][N], int n ) { - IntegerStream stream( N ); - tbb::parallel_while w; - MatrixMultiplyBody body(w,c,a,b,n); - w.run( stream, body ); -} - -#include "tbb/tick_count.h" -#include -#include -using namespace std; - -static long Iterations = 5; - -static void SerialMatrixMultiply( Element c[N][N], Element a[N][N], Element b[N][N], int n ) { - for( int i=0; i -#include -#include "harness.h" - -// In the test, variables related to token counting are declared -// as unsigned long to match definition of tbb::internal::Token. - -struct Buffer { - //! Indicates that the buffer is not used. - static const unsigned long unused = ~0ul; - unsigned long id; - //! True if Buffer is in use. - bool is_busy; - unsigned long sequence_number; - Buffer() : id(unused), is_busy(false), sequence_number(unused) {} -}; - -class waiting_probe { - size_t check_counter; -public: - waiting_probe() : check_counter(0) {} - bool required( ) { - ++check_counter; - return !((check_counter+1)&size_t(0x7FFF)); - } - void probe( ); // defined below -}; - -static const unsigned MaxStreamSize = 8000; -static const unsigned MaxStreamItemsPerThread = 1000; -//! Maximum number of filters allowed -static const unsigned MaxFilters = 5; -static unsigned StreamSize; -static const unsigned MaxBuffer = 8; -static bool Done[MaxFilters][MaxStreamSize]; -static waiting_probe WaitTest; -static unsigned out_of_order_count; - -#include "harness_concurrency_tracker.h" - -class BaseFilter: public tbb::filter { - bool* const my_done; - const bool my_is_last; - bool my_is_running; -public: - tbb::atomic current_token; - BaseFilter( tbb::filter::mode type, bool done[], bool is_last ) : - filter(type), - my_done(done), - my_is_last(is_last), - my_is_running(false), - current_token() - {} - virtual Buffer* get_buffer( void* item ) { - current_token++; - return static_cast(item); - } - /*override*/void* operator()( void* item ) { - Harness::ConcurrencyTracker ct; - if( is_serial() ) - ASSERT( !my_is_running, "premature entry to serial stage" ); - my_is_running = true; - Buffer* b = get_buffer(item); - if( b ) { - if( is_ordered() ) { - if( b->sequence_number == Buffer::unused ) - b->sequence_number = current_token-1; - else - ASSERT( b->sequence_number==current_token-1, "item arrived out of order" ); - } else if( is_serial() ) { - if( b->sequence_number != current_token-1 && b->sequence_number != Buffer::unused ) - out_of_order_count++; - } - ASSERT( b->id < StreamSize, NULL ); - ASSERT( !my_done[b->id], "duplicate processing of token?" ); - ASSERT( b->is_busy, NULL ); - my_done[b->id] = true; - if( my_is_last ) { - b->id = Buffer::unused; - b->sequence_number = Buffer::unused; - __TBB_store_with_release(b->is_busy, false); - } - } - my_is_running = false; - return b; - } -}; - -class InputFilter: public BaseFilter { - tbb::spin_mutex input_lock; - Buffer buffer[MaxBuffer]; - const tbb::internal::Token my_number_of_tokens; -public: - InputFilter( tbb::filter::mode type, tbb::internal::Token ntokens, bool done[], bool is_last ) : - BaseFilter(type, done, is_last), - my_number_of_tokens(ntokens) - {} - /*override*/Buffer* get_buffer( void* ) { - unsigned long next_input; - unsigned free_buffer = 0; - { // lock protected scope - tbb::spin_mutex::scoped_lock lock(input_lock); - if( current_token>=StreamSize ) - return NULL; - next_input = current_token++; - // once in a while, emulate waiting for input; this only makes sense for serial input - if( is_serial() && WaitTest.required() ) - WaitTest.probe( ); - while( free_bufferid == Buffer::unused, NULL); - b->id = next_input; - ASSERT( b->sequence_number == Buffer::unused, NULL); - return b; - } -}; - -//! The struct below repeats layout of tbb::pipeline. -struct hacked_pipeline { - tbb::filter* filter_list; - tbb::filter* filter_end; - tbb::empty_task* end_counter; - tbb::atomic input_tokens; - tbb::atomic token_counter; - bool end_of_input; - bool has_thread_bound_filters; - - virtual ~hacked_pipeline(); -}; - -//! The struct below repeats layout of tbb::internal::input_buffer. -struct hacked_input_buffer { - void* array; // This should be changed to task_info* if ever used - void* my_sem; // This should be changed to semaphore* if ever used - tbb::internal::Token array_size; - tbb::internal::Token low_token; - tbb::spin_mutex array_mutex; - tbb::internal::Token high_token; - bool is_ordered; - bool is_bound; -}; - -//! The struct below repeats layout of tbb::filter. -struct hacked_filter { - tbb::filter* next_filter_in_pipeline; - hacked_input_buffer* my_input_buffer; - unsigned char my_filter_mode; - tbb::filter* prev_filter_in_pipeline; - tbb::pipeline* my_pipeline; - tbb::filter* next_segment; - - virtual ~hacked_filter(); -}; - -bool do_hacking_tests = true; -const tbb::internal::Token tokens_before_wraparound = 0xF; - -void TestTrivialPipeline( unsigned nthread, unsigned number_of_filters ) { - // There are 3 filter types: parallel, serial_in_order and serial_out_of_order - static const tbb::filter::mode filter_table[] = { tbb::filter::parallel, tbb::filter::serial_in_order, tbb::filter::serial_out_of_order}; - const unsigned number_of_filter_types = sizeof(filter_table)/sizeof(filter_table[0]); - REMARK( "testing with %lu threads and %lu filters\n", nthread, number_of_filters ); - ASSERT( number_of_filters<=MaxFilters, "too many filters" ); - ASSERT( sizeof(hacked_pipeline) == sizeof(tbb::pipeline), "layout changed for tbb::pipeline?" ); - ASSERT( sizeof(hacked_filter) == sizeof(tbb::filter), "layout changed for tbb::filter?" ); - tbb::internal::Token ntokens = nthreadtoken_counter = ~tokens_before_wraparound; - } - tbb::filter* filter[MaxFilters]; - unsigned temp = numeral; - // parallelism_limit is the upper bound on the possible parallelism - unsigned parallelism_limit = 0; - for( unsigned i=0; iis_serial() ) { - if( do_hacking_tests ) { - ((hacked_filter*)(void*)filter[i])->my_input_buffer->low_token = ~tokens_before_wraparound; - ((hacked_filter*)(void*)filter[i])->my_input_buffer->high_token = ~tokens_before_wraparound; - } - parallelism_limit += 1; - } else { - parallelism_limit = nthread; - } - } - // Account for clipping of parallelism. - if( parallelism_limit>nthread ) - parallelism_limit = nthread; - if( parallelism_limit>ntokens ) - parallelism_limit = (unsigned)ntokens; - Harness::ConcurrencyTracker::Reset(); - unsigned streamSizeLimit = min( MaxStreamSize, nthread * MaxStreamItemsPerThread ); - for( StreamSize=0; StreamSize<=streamSizeLimit; ) { - memset( Done, 0, sizeof(Done) ); - for( unsigned i=0; i(filter[i])->current_token=0; - } - pipeline.run( ntokens ); - ASSERT( !Harness::ConcurrencyTracker::InstantParallelism(), "filter still running?" ); - for( unsigned i=0; i(filter[i])->current_token==StreamSize, NULL ); - for( unsigned i=0; iTBB_INTERFACE_VERSION) { - REMARK("Warning: implementation dependent tests disabled\n"); - do_hacking_tests = false; - } - - // Test with varying number of threads. - for( nthread=MinThread; nthread<=MaxThread; ++nthread ) { - // Initialize TBB task scheduler - tbb::task_scheduler_init init(nthread); - - // Test pipelines with n filters - for( unsigned n=0; n<=MaxFilters; ++n ) - TestTrivialPipeline(nthread,n); - - // Test that all workers sleep when no work - TestCPUUserTime(nthread); - } - if( !out_of_order_count ) - REPORT("Warning: out of order serial filter received tokens in order\n"); - return Harness::Done; -} diff --git a/deal.II/contrib/tbb/tbb30_104oss/src/test/test_pipeline_with_tbf.cpp b/deal.II/contrib/tbb/tbb30_104oss/src/test/test_pipeline_with_tbf.cpp deleted file mode 100644 index 9cac1e5efc..0000000000 --- a/deal.II/contrib/tbb/tbb30_104oss/src/test/test_pipeline_with_tbf.cpp +++ /dev/null @@ -1,493 +0,0 @@ -/* - Copyright 2005-2010 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. -*/ - -#include "tbb/pipeline.h" -#include "tbb/spin_mutex.h" -#include "tbb/atomic.h" -#include "tbb/tbb_thread.h" -#include -#include -#include "harness.h" - -// In the test, variables related to token counting are declared -// as unsigned long to match definition of tbb::internal::Token. - -//! Id of thread that first executes work on non-thread-bound stages -tbb::tbb_thread::id thread_id; -//! Zero thread id -tbb::tbb_thread::id id0; -//! True if non-thread-bound stages must be executed on one thread -bool is_serial_execution; -double sleeptime; // how long is a non-thread-bound stage to sleep? - -struct Buffer { - //! Indicates that the buffer is not used. - static const unsigned long unused = ~0ul; - unsigned long id; - //! True if Buffer is in use. - bool is_busy; - unsigned long sequence_number; - Buffer() : id(unused), is_busy(false), sequence_number(unused) {} -}; - -class waiting_probe { - size_t check_counter; -public: - waiting_probe() : check_counter(0) {} - bool required( ) { - ++check_counter; - return !((check_counter+1)&size_t(0x7FFF)); - } - void probe( ); // defined below -}; - -static const unsigned MaxStreamSize = 8000; -static const unsigned MaxStreamItemsPerThread = 1000; -//! Maximum number of filters allowed -static const unsigned MaxFilters = 4; -static unsigned StreamSize; -static const unsigned MaxBuffer = 8; -static bool Done[MaxFilters][MaxStreamSize]; -static waiting_probe WaitTest; -static unsigned out_of_order_count; - -#include "harness_concurrency_tracker.h" - -template -class BaseFilter: public T { - bool* const my_done; - const bool my_is_last; - bool my_is_running; -public: - tbb::atomic current_token; - BaseFilter( tbb::filter::mode type, bool done[], bool is_last ) : - T(type), - my_done(done), - my_is_last(is_last), - my_is_running(false), - current_token() - {} - virtual Buffer* get_buffer( void* item ) { - current_token++; - return static_cast(item); - } - /*override*/void* operator()( void* item ) { - // Check if work is done only on one thread when ntokens==1 or - // when pipeline has only one filter that is serial and non-thread-bound - if( is_serial_execution && !this->is_bound() ) { - // Get id of current thread - tbb::tbb_thread::id id = tbb::this_tbb_thread::get_id(); - // At first execution, set thread_id to current thread id. - // Serialized execution is expected, so there should be no race. - if( thread_id == id0 ) - thread_id = id; - // Check if work is done on one thread - ASSERT( thread_id == id, "non-thread-bound stages executed on different threads when must be executed on a single one"); - } - Harness::ConcurrencyTracker ct; - if( this->is_serial() ) - ASSERT( !my_is_running, "premature entry to serial stage" ); - my_is_running = true; - Buffer* b = get_buffer(item); - if( b ) { - if(!this->is_bound() && sleeptime > 0) { - Harness::Sleep((int)sleeptime); - } - if( this->is_ordered() ) { - if( b->sequence_number == Buffer::unused ) - b->sequence_number = current_token-1; - else - ASSERT( b->sequence_number==current_token-1, "item arrived out of order" ); - } else if( this->is_serial() ) { - if( b->sequence_number != current_token-1 && b->sequence_number != Buffer::unused ) - out_of_order_count++; - } - ASSERT( b->id < StreamSize, NULL ); - ASSERT( !my_done[b->id], "duplicate processing of token?" ); - ASSERT( b->is_busy, NULL ); - my_done[b->id] = true; - if( my_is_last ) { - b->id = Buffer::unused; - b->sequence_number = Buffer::unused; - __TBB_store_with_release(b->is_busy, false); - } - } - my_is_running = false; - return b; - } -}; - -template -class InputFilter: public BaseFilter { - tbb::spin_mutex input_lock; - Buffer buffer[MaxBuffer]; - const tbb::internal::Token my_number_of_tokens; -public: - InputFilter( tbb::filter::mode type, tbb::internal::Token ntokens, bool done[], bool is_last ) : - BaseFilter(type, done, is_last), - my_number_of_tokens(ntokens) - {} - /*override*/Buffer* get_buffer( void* ) { - unsigned long next_input; - unsigned free_buffer = 0; - { // lock protected scope - tbb::spin_mutex::scoped_lock lock(input_lock); - if( this->current_token>=StreamSize ) - return NULL; - next_input = this->current_token++; - // once in a while, emulate waiting for input; this only makes sense for serial input - if( this->is_serial() && WaitTest.required() ) - WaitTest.probe( ); - while( free_bufferid == Buffer::unused, NULL); - b->id = next_input; - ASSERT( b->sequence_number == Buffer::unused, NULL); - return b; - } -}; - -class process_loop { -public: - void operator()( tbb::thread_bound_filter* tbf ) { - tbb::thread_bound_filter::result_type flag; - do - flag = tbf->process_item(); - while( flag != tbb::thread_bound_filter::end_of_stream ); - } -}; - -//! The struct below repeats layout of tbb::pipeline. -struct hacked_pipeline { - tbb::filter* filter_list; - tbb::filter* filter_end; - tbb::empty_task* end_counter; - tbb::atomic input_tokens; - tbb::atomic global_token_counter; - bool end_of_input; - bool has_thread_bound_filters; - - virtual ~hacked_pipeline(); -}; - -//! The struct below repeats layout of tbb::internal::ordered_buffer. -struct hacked_ordered_buffer { - void* array; // This should be changed to task_info* if ever used - tbb::internal::Token array_size; - tbb::internal::Token low_token; - tbb::spin_mutex array_mutex; - tbb::internal::Token high_token; - bool is_ordered; - bool is_bound; -}; - -//! The struct below repeats layout of tbb::filter. -struct hacked_filter { - tbb::filter* next_filter_in_pipeline; - hacked_ordered_buffer* input_buffer; - unsigned char my_filter_mode; - tbb::filter* prev_filter_in_pipeline; - tbb::pipeline* my_pipeline; - tbb::filter* next_segment; - - virtual ~hacked_filter(); -}; - -#if _MSC_VER && !defined(__INTEL_COMPILER) - // Workaround for overzealous compiler warnings - // Suppress compiler warning about constant conditional expression - #pragma warning (disable: 4127) -#endif - -void clear_global_state() { - Harness::ConcurrencyTracker::Reset(); - memset( Done, 0, sizeof(Done) ); - thread_id = id0; - is_serial_execution = false; -} - - -class PipelineTest { - // There are 3 non-thread-bound filter types: serial_in_order and serial_out_of_order, parallel - static const tbb::filter::mode non_tb_filters_table[3]; // = { tbb::filter::serial_in_order, tbb::filter::serial_out_of_order, tbb::filter::parallel}; - // There are 2 thread-bound filter types: serial_in_order and serial_out_of_order - static const tbb::filter::mode tb_filters_table[2]; // = { tbb::filter::serial_in_order, tbb::filter::serial_out_of_order }; - - static const unsigned number_of_non_tb_filter_types = sizeof(non_tb_filters_table)/sizeof(non_tb_filters_table[0]); - static const unsigned number_of_tb_filter_types = sizeof(tb_filters_table)/sizeof(tb_filters_table[0]); - static const unsigned number_of_filter_types = number_of_non_tb_filter_types + number_of_tb_filter_types; - // static unsigned my_nthread; - public: - static double TestOneConfiguration( unsigned numeral, unsigned nthread, unsigned number_of_filters, tbb::internal::Token ntokens); - static void TestTrivialPipeline( unsigned nthread, unsigned number_of_filters ); - static void TestIdleSpinning(unsigned nthread); -}; - -const tbb::filter::mode PipelineTest::non_tb_filters_table[3] = { tbb::filter::serial_in_order, tbb::filter::serial_out_of_order, tbb::filter::parallel}; -const tbb::filter::mode PipelineTest::tb_filters_table[2] = { tbb::filter::serial_in_order, tbb::filter::serial_out_of_order }; - -#include "harness_cpu.h" - -double PipelineTest::TestOneConfiguration(unsigned numeral, unsigned nthread, unsigned number_of_filters, tbb::internal::Token ntokens) -{ - // Build pipeline - tbb::pipeline pipeline; - tbb::filter* filter[MaxFilters]; - unsigned temp = numeral; - // parallelism_limit is the upper bound on the possible parallelism - unsigned parallelism_limit = 0; - // number of thread-bound-filters in the current sequence - unsigned number_of_tb_filters = 0; - // ordinal numbers of thread-bound-filters in the current sequence - unsigned array_of_tb_filter_numbers[MaxFilters]; - for( unsigned i=0; i(filter_type,ntokens,Done[i],is_last); - else - filter[i] = new BaseFilter(filter_type,Done[i],is_last); - array_of_tb_filter_numbers[number_of_tb_filters] = i; - number_of_tb_filters++; - } else { - if( i == 0 ) - filter[i] = new InputFilter(filter_type,ntokens,Done[i],is_last); - else - filter[i] = new BaseFilter(filter_type,Done[i],is_last); - } - pipeline.add_filter(*filter[i]); - if ( filter[i]->is_serial() ) { - parallelism_limit += 1; - } else { - parallelism_limit = nthread; - } - } - clear_global_state(); - // Account for clipping of parallelism. - if( parallelism_limit>nthread ) - parallelism_limit = nthread; - if( parallelism_limit>ntokens ) - parallelism_limit = (unsigned)ntokens; - StreamSize = nthread; // min( MaxStreamSize, nthread * MaxStreamItemsPerThread ); - - for( unsigned i=0; i*>(filter[i])->current_token=0; - } - tbb::tbb_thread* t[MaxFilters]; - for( unsigned j = 0; j(filter[array_of_tb_filter_numbers[j]])); - if( ntokens == 1 || ( number_of_filters == 1 && number_of_tb_filters == 0 && filter[0]->is_serial() )) - is_serial_execution = true; - double strttime = GetCPUUserTime(); - pipeline.run( ntokens ); - double endtime = GetCPUUserTime(); - for( unsigned j = 0; jjoin(); - ASSERT( !Harness::ConcurrencyTracker::InstantParallelism(), "filter still running?" ); - for( unsigned i=0; i*>(filter[i])->current_token==StreamSize, NULL ); - for( unsigned i=0; i1: - // one iteration for ntokens=1 and second for ntokens=max_tokens - // Iteration for ntokens=1 is required in each test case to check if pipeline run only on one thread - unsigned max_iteration = max_tokens > 1 ? 2 : 1; - tbb::internal::Token ntokens = 1; - for( unsigned iteration = 0; iteration < max_iteration; iteration++) { - if( iteration > 0 ) - ntokens = max_tokens; - // Count maximum iterations number - unsigned limit = 1; - for( unsigned i=0; i 0.0) { - ++v0cnt; - s0 = (s0a < s0) ? s0a : s0; - } - else { - ++zero_count; - } - if(s1a > 0.0) { - ++v1cnt; - s1 = (s1a < s1) ? s1a : s1; - } - else { - ++zero_count; - } - } - if(s0 == bignum || s1 == bignum) continue; - s0sum /= (double)v0cnt; - s1sum /= (double)v1cnt; - double slowdown = (s1sum-s0sum)/s0sum; - if(slowdown > allowable_slowdown) - REMARK( "with %lu threads configuration %lu has slowdown > %g (%g)\n", nthread, numeral, allowable_slowdown, slowdown ); - } - REMARK("Total of %lu zero times\n", zero_count); -} - -static int nthread; // knowing number of threads is necessary to call TestCPUUserTime - -void waiting_probe::probe( ) { - if( nthread==1 ) return; - REMARK("emulating wait for input\n"); - // Test that threads sleep while no work. - // The master doesn't sleep so there could be 2 active threads if a worker is waiting for input - TestCPUUserTime(nthread, 2); -} - -#include "tbb/task_scheduler_init.h" - -int TestMain () { - out_of_order_count = 0; - if( MinThread<1 ) { - REPORT("must have at least one thread"); - exit(1); - } - - sleeptime = 0.0; // msec : 0 == no_timing, > 0, each filter stage sleeps for sleeptime - // Test with varying number of threads. - for( nthread=MinThread; nthread<=MaxThread; ++nthread ) { - // Initialize TBB task scheduler - tbb::task_scheduler_init init(nthread); - - // Test pipelines with 1 and maximal number of filters - for( unsigned n=1; n<=MaxFilters; n*=MaxFilters ) { - // Thread-bound stages are serviced by user-created threads those - // don't run the pipeline and don't service non-thread-bound stages - PipelineTest::TestTrivialPipeline(nthread,n); - } - - // Test that all workers sleep when no work - TestCPUUserTime(nthread); - if((unsigned)nthread >= MaxFilters) // test works when number of threads >= number of stages - PipelineTest::TestIdleSpinning(nthread); - } - if( !out_of_order_count ) - REPORT("Warning: out of order serial filter received tokens in order\n"); - return Harness::Done; -} diff --git a/deal.II/contrib/tbb/tbb30_104oss/src/test/test_reader_writer_lock.cpp b/deal.II/contrib/tbb/tbb30_104oss/src/test/test_reader_writer_lock.cpp deleted file mode 100644 index 86a4dd0afa..0000000000 --- a/deal.II/contrib/tbb/tbb30_104oss/src/test/test_reader_writer_lock.cpp +++ /dev/null @@ -1,226 +0,0 @@ -/* - Copyright 2005-2010 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. -*/ - -// test reader_writer_lock -#include "tbb/reader_writer_lock.h" -#include "tbb/atomic.h" -#include "tbb/tbb_exception.h" -#include "harness_assert.h" -#include "harness.h" - -tbb::reader_writer_lock the_mutex; -const int MAX_WORK = 10000; - -tbb::atomic active_readers, active_writers; -tbb::atomic sim_readers; - - -int BusyWork(int percentOfMaxWork) { - int iters = 0; - for (int i=0; i 1) sim_readers = true; - ASSERT(active_writers==0, "Active writers in read-locked region."); - Harness::Sleep(10); - active_readers--; - } - else { // is writer - tbb::reader_writer_lock::scoped_lock my_lock(the_mutex); - active_writers++; - ASSERT(active_readers==0, "Active readers in write-locked region."); - ASSERT(active_writers<=1, "More than one active writer in write-locked region."); - Harness::Sleep(10); - active_writers--; - } - } - } -}; - -struct CorrectRWLBody : NoAssign { - const int nThread; - - CorrectRWLBody(int nThread_) : nThread(nThread_) {} - - void operator()(const int /* threadID */ ) const { - bool is_reader; - - for (int i=0; i<50; i++) { - if (i%5==0) is_reader = false; // 1 writer for every 5 readers - else is_reader = true; - - if (is_reader) { - the_mutex.lock_read(); - active_readers++; - if (active_readers > 1) sim_readers = true; - ASSERT(active_writers==0, "Active writers in read-locked region."); - } - else { // is writer - the_mutex.lock(); - active_writers++; - ASSERT(active_readers==0, "Active readers in write-locked region."); - ASSERT(active_writers<=1, "More than one active writer in write-locked region."); - } - Harness::Sleep(10); - if (is_reader) { - active_readers--; - } - else { // is writer - active_writers--; - } - the_mutex.unlock(); - } - } -}; - -void TestReaderWriterLockOnNThreads(int nThreads) { - // Stress-test all interfaces - for (int pc=0; pc<101; pc+=20) { - REMARK("\nTesting reader_writer_lock with %d threads, percent of MAX_WORK=%d", nThreads, pc); - StressRWLBody myStressBody(nThreads, pc); - NativeParallelFor(nThreads, myStressBody); - } - - // Test mutual exclusion in direct locking mode - CorrectRWLBody myCorrectBody(nThreads); - active_writers = active_readers = 0; - sim_readers = false; - NativeParallelFor(nThreads, myCorrectBody); - ASSERT(sim_readers || nThreads<2, "There were no simultaneous readers."); - REMARK("Unscoped lock testing succeeded on %d threads.", nThreads); - - // Test mutual exclusionin scoped locking mode - CorrectRWLScopedBody myCorrectScopedBody(nThreads); - active_writers = active_readers = 0; - sim_readers = false; - NativeParallelFor(nThreads, myCorrectScopedBody); - ASSERT(sim_readers || nThreads<2, "There were no simultaneous readers."); - REMARK("Scoped lock testing succeeded on %d threads.", nThreads); -} - -void TestReaderWriterLock() { - for(int p = MinThread; p <= MaxThread; p++) { - TestReaderWriterLockOnNThreads(p); - } -} - - -int TestMain() { - if(MinThread <= 0) MinThread = 1; - if(MaxThread > 0) { - TestReaderWriterLock(); - } - return Harness::Done; -} diff --git a/deal.II/contrib/tbb/tbb30_104oss/src/test/test_rwm_upgrade_downgrade.cpp b/deal.II/contrib/tbb/tbb30_104oss/src/test/test_rwm_upgrade_downgrade.cpp deleted file mode 100644 index 1cb26e2729..0000000000 --- a/deal.II/contrib/tbb/tbb30_104oss/src/test/test_rwm_upgrade_downgrade.cpp +++ /dev/null @@ -1,79 +0,0 @@ -/* - Copyright 2005-2010 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. -*/ - -#include "tbb/queuing_rw_mutex.h" -#include "tbb/spin_rw_mutex.h" -#include "harness.h" - -using namespace tbb; - -volatile int Count; - -template -struct Hammer: NoAssign { - RWMutex &MutexProtectingCount; - mutable volatile int dummy; - - Hammer(RWMutex &m): MutexProtectingCount(m) {} - void operator()( int /*thread_id*/ ) const { - for( int j=0; j<100000; ++j ) { - typename RWMutex::scoped_lock lock(MutexProtectingCount,false); - int c = Count; - for( int k=0; k<10; ++k ) { - ++dummy; - } - if( lock.upgrade_to_writer() ) { - // The upgrade succeeded without any intervening writers - ASSERT( c==Count, "another thread modified Count while I held a read lock" ); - } else { - c = Count; - } - for( int k=0; k<10; ++k ) { - ++Count; - } - lock.downgrade_to_reader(); - for( int k=0; k<10; ++k ) { - ++dummy; - } - } - } -}; - -queuing_rw_mutex QRW_mutex; -spin_rw_mutex SRW_mutex; - -int TestMain () { - for( int p=MinThread; p<=MaxThread; ++p ) { - REMARK("Testing on %d threads", p); - Count = 0; - NativeParallelFor( p, Hammer(QRW_mutex) ); - Count = 0; - NativeParallelFor( p, Hammer(SRW_mutex) ); - } - return Harness::Done; -} diff --git a/deal.II/contrib/tbb/tbb30_104oss/src/test/test_semaphore.cpp b/deal.II/contrib/tbb/tbb30_104oss/src/test/test_semaphore.cpp deleted file mode 100644 index 75b5507c0a..0000000000 --- a/deal.II/contrib/tbb/tbb30_104oss/src/test/test_semaphore.cpp +++ /dev/null @@ -1,258 +0,0 @@ -/* - Copyright 2005-2010 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. -*/ - -// -// Test for counting semaphore. -// -// set semaphore to N -// create N + M threads -// have each thread -// A. P() -// B. increment atomic count -// C. spin for awhile checking the value of the count; make sure it doesn't exceed N -// D. decrement atomic count -// E. V() -// - -#include "tbb/semaphore.h" -#include "tbb/atomic.h" - -#include -using std::vector; - -#include "harness_assert.h" -#include "harness.h" - -using tbb::internal::semaphore; - -#include "harness_barrier.h" - -tbb::atomic pCount; - -Harness::SpinBarrier sBarrier; - -#include "tbb/tick_count.h" -// semaphore basic function: -// set semaphore to initial value -// see that semaphore only allows that number of threads to be active -class Body: NoAssign { - const int nThreads; - const int nIters; - tbb::internal::semaphore &mySem; - vector &ourCounts; - vector &tottime; - static const int tickCounts = 1; // millisecond - static const int innerWait = 5; // millisecond -public: - Body(int nThread_, int nIter_, semaphore &mySem_, - vector& ourCounts_, - vector& tottime_ - ) : nThreads(nThread_), nIters(nIter_), mySem(mySem_), ourCounts(ourCounts_), tottime(tottime_) { sBarrier.initialize(nThread_); pCount = 0; } -void operator()(const int tid) const { - sBarrier.wait(); - for(int i=0; i < nIters; ++i) { - Harness::Sleep( tid * tickCounts ); - tbb::tick_count t0 = tbb::tick_count::now(); - mySem.P(); - tbb::tick_count t1 = tbb::tick_count::now(); - tottime[tid] += (t1-t0).seconds(); - int curval = ++pCount; - if(curval > ourCounts[tid]) ourCounts[tid] = curval; - Harness::Sleep( innerWait ); - --pCount; - ASSERT((int)pCount >= 0, NULL); - mySem.V(); - } -} -}; - - -void testSemaphore( int semInitCnt, int extraThreads ) { - semaphore my_sem(semInitCnt); - // tbb::task_scheduler_init init(tbb::task_scheduler_init::deferred); - int nThreads = semInitCnt + extraThreads; - vector maxVals(nThreads); - vector totTimes(nThreads); - int nIters = 10; - Body myBody(nThreads, nIters, my_sem, maxVals, totTimes); - - REMARK( " sem(%d) with %d extra threads\n", semInitCnt, extraThreads); - pCount = 0; - NativeParallelFor(nThreads, myBody); - if(extraThreads == 0) { - double allPWaits = 0; - for(vector::const_iterator j = totTimes.begin(); j != totTimes.end(); ++j) { - allPWaits += *j; - } - allPWaits /= static_cast(nThreads * nIters); - REMARK("Average wait for P() in uncontested case for nThreads = %d is %g\n", nThreads, allPWaits); - } - ASSERT(!pCount, "not all threads decremented pCount"); - int maxCount = -1; - for(vector::const_iterator i=maxVals.begin(); i!= maxVals.end();++i) { - maxCount = max(maxCount,*i); - } - ASSERT(maxCount <= semInitCnt,"too many threads in semaphore-protected increment"); - if(maxCount < semInitCnt) { - REMARK("Not enough threads in semaphore-protected region (%d < %d)\n", static_cast(maxCount), semInitCnt); - } -} - -// Power of 2, the most tokens that can be in flight. -#define MAX_TOKENS 32 -enum FilterType { imaProducer, imaConsumer }; -class FilterBase : NoAssign { -protected: - FilterType ima; - unsigned totTokens; // total number of tokens to be emitted, only used by producer - tbb::atomic& myTokens; - tbb::atomic& otherTokens; - unsigned myWait; - semaphore &mySem; - semaphore &nextSem; - unsigned* myBuffer; - unsigned* nextBuffer; - unsigned curToken; -public: - FilterBase( FilterType ima_ - ,unsigned totTokens_ - ,tbb::atomic& myTokens_ - ,tbb::atomic& otherTokens_ - ,unsigned myWait_ - ,semaphore &mySem_ - ,semaphore &nextSem_ - ,unsigned* myBuffer_ - ,unsigned* nextBuffer_ - ) - : ima(ima_),totTokens(totTokens_),myTokens(myTokens_),otherTokens(otherTokens_),myWait(myWait_),mySem(mySem_), - nextSem(nextSem_),myBuffer(myBuffer_),nextBuffer(nextBuffer_) - { - curToken = 0; - } - void Produce(const int tid); - void Consume(const int tid); - void operator()(const int tid) { if(ima == imaConsumer) Consume(tid); else Produce(tid); } -}; - -class ProduceConsumeBody { - FilterBase** myFilters; - public: - ProduceConsumeBody(FilterBase** myFilters_) : myFilters(myFilters_) {} - void operator()(const int tid) const { - myFilters[tid]->operator()(tid); - } -}; - -// send a bunch of non-Null "tokens" to consumer, then a NULL. -void FilterBase::Produce(const int /*tid*/) { - nextBuffer[0] = 0; // just in case we provide no tokens - sBarrier.wait(); - while(totTokens) { - while(!myTokens) - mySem.P(); - // we have a slot available. - --myTokens; // moving this down reduces spurious wakeups - --totTokens; - if(totTokens) - nextBuffer[curToken&(MAX_TOKENS-1)] = curToken*3+1; - else - nextBuffer[curToken&(MAX_TOKENS-1)] = (unsigned)NULL; - ++curToken; - Harness::Sleep(myWait); - unsigned temp = ++otherTokens; - if(temp == 1) - nextSem.V(); - } - nextSem.V(); // final wakeup -} - -void FilterBase::Consume(const int /*tid*/) { - unsigned myToken; - sBarrier.wait(); - do { - while(!myTokens) - mySem.P(); - // we have a slot available. - --myTokens; // moving this down reduces spurious wakeups - myToken = myBuffer[curToken&(MAX_TOKENS-1)]; - if(myToken) { - ASSERT(myToken == curToken*3+1, "Error in received token"); - ++curToken; - Harness::Sleep(myWait); - unsigned temp = ++otherTokens; - if(temp == 1) - nextSem.V(); - } - } while(myToken); - // end of processing - ASSERT(curToken + 1 == totTokens, "Didn't receive enough tokens"); -} - -// -- test of producer/consumer with atomic buffer cnt and semaphore -// nTokens are total number of tokens through the pipe -// pWait is the wait time for the producer -// cWait is the wait time for the consumer -void testProducerConsumer( unsigned totTokens, unsigned nTokens, unsigned pWait, unsigned cWait) { - semaphore pSem; - semaphore cSem; - tbb::atomic pTokens; - tbb::atomic cTokens; - cTokens = 0; - unsigned cBuffer[MAX_TOKENS]; - FilterBase* myFilters[2]; // one producer, one consumer - REMARK("Testing producer/consumer with %lu total tokens, %lu tokens at a time, producer wait(%lu), consumer wait (%lu)\n", totTokens, nTokens, pWait, cWait); - ASSERT(nTokens <= MAX_TOKENS, "Not enough slots for tokens"); - myFilters[0] = new FilterBase(imaProducer, totTokens, pTokens, cTokens, pWait, cSem, pSem, (unsigned *)NULL, &(cBuffer[0])); - myFilters[1] = new FilterBase(imaConsumer, totTokens, cTokens, pTokens, cWait, pSem, cSem, cBuffer, (unsigned *)NULL); - pTokens = nTokens; - ProduceConsumeBody myBody(myFilters); - sBarrier.initialize(2); - NativeParallelFor(2, myBody); - delete myFilters[0]; - delete myFilters[1]; -} - -int TestMain() { - REMARK("Started\n"); - if(MaxThread > 0) { - for(int semSize = 1; semSize <= MaxThread; ++semSize) { - for(int exThreads = 0; exThreads <= MaxThread - semSize; ++exThreads) { - testSemaphore( semSize, exThreads ); - } - } - } - // Test producer/consumer with varying execution times and buffer sizes - // ( total tokens, tokens in buffer, sleep for producer, sleep for consumer ) - testProducerConsumer( 10, 2, 5, 5 ); - testProducerConsumer( 10, 2, 20, 5 ); - testProducerConsumer( 10, 2, 5, 20 ); - testProducerConsumer( 10, 1, 5, 5 ); - testProducerConsumer( 20, 10, 5, 20 ); - testProducerConsumer( 64, 32, 1, 20 ); - return Harness::Done; -} diff --git a/deal.II/contrib/tbb/tbb30_104oss/src/test/test_std_thread.cpp b/deal.II/contrib/tbb/tbb30_104oss/src/test/test_std_thread.cpp deleted file mode 100644 index 503260699d..0000000000 --- a/deal.II/contrib/tbb/tbb30_104oss/src/test/test_std_thread.cpp +++ /dev/null @@ -1,41 +0,0 @@ -/* - Copyright 2005-2010 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. -*/ - -#define TBB_IMPLEMENT_CPP0X 1 -#include "tbb/compat/thread" -#define THREAD std::thread -#define THIS_THREAD std::this_thread -#define THIS_THREAD_SLEEP THIS_THREAD::sleep_for -#include "test_thread.h" -#include "harness.h" - -int TestMain () { - CheckSignatures(); - RunTests(); - return Harness::Done; -} diff --git a/deal.II/contrib/tbb/tbb30_104oss/src/test/test_task.cpp b/deal.II/contrib/tbb/tbb30_104oss/src/test/test_task.cpp deleted file mode 100644 index 197f16800a..0000000000 --- a/deal.II/contrib/tbb/tbb30_104oss/src/test/test_task.cpp +++ /dev/null @@ -1,989 +0,0 @@ -/* - Copyright 2005-2010 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. -*/ - -#include "tbb/task.h" -#include "tbb/atomic.h" -#include "tbb/tbb_thread.h" -#include "harness_assert.h" -#include - -//------------------------------------------------------------------------ -// Helper for verifying that old use cases of spawn syntax still work. -//------------------------------------------------------------------------ -tbb::task* GetTaskPtr( int& counter ) { - ++counter; - return NULL; -} - -//------------------------------------------------------------------------ -// Test for task::spawn_children and task_list -//------------------------------------------------------------------------ - -class UnboundedlyRecursiveOnUnboundedStealingTask : public tbb::task { - typedef UnboundedlyRecursiveOnUnboundedStealingTask this_type; - - this_type *m_Parent; - const int m_Depth; - volatile bool m_GoAhead; - - // Well, virtually unboundedly, for any practical purpose - static const int max_depth = 1000000; - -public: - UnboundedlyRecursiveOnUnboundedStealingTask( this_type *parent_ = NULL, int depth_ = max_depth ) - : m_Parent(parent_) - , m_Depth(depth_) - , m_GoAhead(true) - {} - - /*override*/ - tbb::task* execute() { - // Using large padding array sppeds up reaching stealing limit - const int paddingSize = 16 * 1024; - volatile char padding[paddingSize]; - if( !m_Parent || (m_Depth > 0 && m_Parent->m_GoAhead) ) { - if ( m_Parent ) { - // We are stolen, let our parent to start waiting for us - m_Parent->m_GoAhead = false; - } - tbb::task &t = *new( tbb::task::allocate_child() ) this_type(this, m_Depth - 1); - set_ref_count( 2 ); - spawn( t ); - // Give a willing thief a chance to steal - for( int i = 0; i < 1000000 && m_GoAhead; ++i ) { - ++padding[i % paddingSize]; - __TBB_Yield(); - } - // If our child has not been stolen yet, then prohibit it siring ones - // of its own (when this thread executes it inside the next wait_for_all) - m_GoAhead = false; - wait_for_all(); - } - return NULL; - } -}; // UnboundedlyRecursiveOnUnboundedStealingTask - -tbb::atomic Count; - -class RecursiveTask: public tbb::task { - const int m_ChildCount; - const int m_Depth; - //! Spawn tasks in list. Exact method depends upon m_Depth&bit_mask. - void SpawnList( tbb::task_list& list, int bit_mask ) { - if( m_Depth&bit_mask ) { - // Take address to check that signature of spawn(task_list&) is static. - void (*s)(tbb::task_list&) = &tbb::task::spawn; - (*s)(list); - ASSERT( list.empty(), NULL ); - wait_for_all(); - } else { - spawn_and_wait_for_all(list); - ASSERT( list.empty(), NULL ); - } - } -public: - RecursiveTask( int child_count, int depth_ ) : m_ChildCount(child_count), m_Depth(depth_) {} - /*override*/ tbb::task* execute() { - ++Count; - if( m_Depth>0 ) { - tbb::task_list list; - ASSERT( list.empty(), NULL ); - for( int k=0; k=0 && m_Depth>=0, NULL ); - if( m_Depth>0 ) { - recycle_as_safe_continuation(); - set_ref_count( m_ChildCount+1 ); - int k=0; - for( int j=0; jspawn(t); - } - ASSERT(k==m_ChildCount,NULL); - --m_Depth; - __TBB_Yield(); - ASSERT( state()==recycle && ref_count()>0, NULL); - } - return NULL; - } -}; - -void TestSafeContinuation( int nthread ) { - REMARK("testing task::recycle_as_safe_continuation for %d threads\n",nthread); - tbb::task_scheduler_init init(nthread); - for( int j=8; j<33; ++j ) { - TaskGenerator& p = *new( tbb::task::allocate_root() ) TaskGenerator(j,5); - tbb::task::spawn_root_and_wait(p); - } -} - -//------------------------------------------------------------------------ -// Test affinity interface -//------------------------------------------------------------------------ -tbb::atomic TotalCount; - -struct AffinityTask: public tbb::task { - const tbb::task::affinity_id expected_affinity_id; - bool noted; - /** Computing affinities is NOT supported by TBB, and may disappear in the future. - It is done here for sake of unit testing. */ - AffinityTask( int expected_affinity_id_ ) : - expected_affinity_id(tbb::task::affinity_id(expected_affinity_id_)), - noted(false) - { - set_affinity(expected_affinity_id); - ASSERT( 0u-expected_affinity_id>0u, "affinity_id not an unsigned integral type?" ); - ASSERT( affinity()==expected_affinity_id, NULL ); - } - /*override*/ tbb::task* execute() { - ++TotalCount; - return NULL; - } - /*override*/ void note_affinity( affinity_id id ) { - // There is no guarantee in TBB that a task runs on its affinity thread. - // However, the current implementation does accidentally guarantee it - // under certain conditions, such as the conditions here. - // We exploit those conditions for sake of unit testing. - ASSERT( id!=expected_affinity_id, NULL ); - ASSERT( !noted, "note_affinity_id called twice!" ); - ASSERT ( &tbb::task::self() == (tbb::task*)this, "Wrong innermost running task" ); - noted = true; - } -}; - -/** Note: This test assumes a lot about the internal implementation of affinity. - Do NOT use this as an example of good programming practice with TBB */ -void TestAffinity( int nthread ) { - TotalCount = 0; - int n = tbb::task_scheduler_init::default_num_threads(); - if( n>nthread ) - n = nthread; - tbb::task_scheduler_init init(n); - tbb::empty_task* t = new( tbb::task::allocate_root() ) tbb::empty_task; - tbb::task::affinity_id affinity_id = t->affinity(); - ASSERT( affinity_id==0, NULL ); - // Set ref_count for n-1 children, plus 1 for the wait. - t->set_ref_count(n); - // Spawn n-1 affinitized children. - for( int i=1; iallocate_child()) AffinityTask(i) ); - if( n>1 ) { - // Keep master from stealing - while( TotalCount!=n-1 ) - __TBB_Yield(); - } - // Wait for the children - t->wait_for_all(); - int k = 0; - GetTaskPtr(k)->destroy(*t); - ASSERT(k==1,NULL); -} - -struct NoteAffinityTask: public tbb::task { - bool noted; - NoteAffinityTask( int id ) : noted(false) - { - set_affinity(tbb::task::affinity_id(id)); - } - ~NoteAffinityTask () { - ASSERT (noted, "note_affinity has not been called"); - } - /*override*/ tbb::task* execute() { - return NULL; - } - /*override*/ void note_affinity( affinity_id /*id*/ ) { - noted = true; - ASSERT ( &tbb::task::self() == (tbb::task*)this, "Wrong innermost running task" ); - } -}; - -// This test checks one of the paths inside the scheduler by affinitizing the child task -// to non-existent thread so that it is proxied in the local task pool but not retrieved -// by another thread. -// If no workers requested, the extra slot #2 is allocated for a worker thread to serve -// "enqueued" tasks. In this test, it is used only for the affinity purpose. -void TestNoteAffinityContext() { - tbb::task_scheduler_init init(1); - tbb::empty_task* t = new( tbb::task::allocate_root() ) tbb::empty_task; - t->set_ref_count(2); - // This master in the absence of workers will have an affinity id of 1. - // So use another number to make the task get proxied. - tbb::task::spawn( *new(t->allocate_child()) NoteAffinityTask(2) ); - t->wait_for_all(); - tbb::task::destroy(*t); -} - -//------------------------------------------------------------------------ -// Test that recovery actions work correctly for task::allocate_* methods -// when a task's constructor throws an exception. -//------------------------------------------------------------------------ - -#if TBB_USE_EXCEPTIONS -static int TestUnconstructibleTaskCount; - -struct ConstructionFailure { -}; - -#if _MSC_VER && !defined(__INTEL_COMPILER) - // Suppress pointless "unreachable code" warning. - #pragma warning (push) - #pragma warning (disable: 4702) -#endif - -//! Task that cannot be constructed. -template -struct UnconstructibleTask: public tbb::empty_task { - char space[N]; - UnconstructibleTask() { - throw ConstructionFailure(); - } -}; - -#if _MSC_VER && !defined(__INTEL_COMPILER) - #pragma warning (pop) -#endif - -#define TRY_BAD_CONSTRUCTION(x) \ - { \ - try { \ - new(x) UnconstructibleTask; \ - } catch( const ConstructionFailure& ) { \ - ASSERT( parent()==original_parent, NULL ); \ - ASSERT( ref_count()==original_ref_count, "incorrectly changed ref_count" );\ - ++TestUnconstructibleTaskCount; \ - } \ - } - -template -struct RootTaskForTestUnconstructibleTask: public tbb::task { - tbb::task* execute() { - tbb::task* original_parent = parent(); - ASSERT( original_parent!=NULL, NULL ); - int original_ref_count = ref_count(); - TRY_BAD_CONSTRUCTION( allocate_root() ); - TRY_BAD_CONSTRUCTION( allocate_child() ); - TRY_BAD_CONSTRUCTION( allocate_continuation() ); - TRY_BAD_CONSTRUCTION( allocate_additional_child_of(*this) ); - return NULL; - } -}; - -template -void TestUnconstructibleTask() { - TestUnconstructibleTaskCount = 0; - tbb::task_scheduler_init init; - tbb::task* t = new( tbb::task::allocate_root() ) RootTaskForTestUnconstructibleTask; - tbb::task::spawn_root_and_wait(*t); - ASSERT( TestUnconstructibleTaskCount==4, NULL ); -} -#endif /* TBB_USE_EXCEPTIONS */ - -//------------------------------------------------------------------------ -// Test for alignment problems with task objects. -//------------------------------------------------------------------------ - -#if _MSC_VER && !defined(__INTEL_COMPILER) - // Workaround for pointless warning "structure was padded due to __declspec(align()) - #pragma warning (push) - #pragma warning (disable: 4324) -#endif - -//! Task with members of type T. -/** The task recursively creates tasks. */ -template -class TaskWithMember: public tbb::task { - T x; - T y; - unsigned char count; - /*override*/ tbb::task* execute() { - x = y; - if( count>0 ) { - set_ref_count(2); - tbb::task* t = new( tbb::task::allocate_child() ) TaskWithMember(count-1); - spawn_and_wait_for_all(*t); - } - return NULL; - } -public: - TaskWithMember( unsigned char n ) : count(n) {} -}; - -#if _MSC_VER && !defined(__INTEL_COMPILER) - #pragma warning (pop) -#endif - -template -void TestAlignmentOfOneClass() { - typedef TaskWithMember task_type; - tbb::task* t = new( tbb::task::allocate_root() ) task_type(10); - tbb::task::spawn_root_and_wait(*t); -} - -#include "harness_m128.h" - -void TestAlignment() { - REMARK("testing alignment\n"); - tbb::task_scheduler_init init; - // Try types that have variety of alignments - TestAlignmentOfOneClass(); - TestAlignmentOfOneClass(); - TestAlignmentOfOneClass(); - TestAlignmentOfOneClass(); - TestAlignmentOfOneClass(); - TestAlignmentOfOneClass(); - TestAlignmentOfOneClass(); -#if HAVE_m128 - TestAlignmentOfOneClass<__m128>(); -#endif /* HAVE_m128 */ -} - -//------------------------------------------------------------------------ -// Test for recursing on left while spawning on right -//------------------------------------------------------------------------ - -int Fib( int n ); - -struct RightFibTask: public tbb::task { - int* y; - const int n; - RightFibTask( int* y_, int n_ ) : y(y_), n(n_) {} - task* execute() { - *y = Fib(n-1); - return 0; - } -}; - -int Fib( int n ) { - if( n<2 ) { - return n; - } else { - // y actually does not need to be initialized. It is initialized solely to suppress - // a gratuitous warning "potentially uninitialized local variable". - int y=-1; - tbb::task* root_task = new( tbb::task::allocate_root() ) tbb::empty_task; - root_task->set_ref_count(2); - tbb::task::spawn( *new( root_task->allocate_child() ) RightFibTask(&y,n) ); - int x = Fib(n-2); - root_task->wait_for_all(); - tbb::task::destroy(*root_task); - return y+x; - } -} - -void TestLeftRecursion( int p ) { - REMARK("testing non-spawned roots for %d threads\n",p); - tbb::task_scheduler_init init(p); - int sum = 0; - for( int i=0; i<100; ++i ) - sum +=Fib(10); - ASSERT( sum==5500, NULL ); -} - -//------------------------------------------------------------------------ -// Test for computing with DAG of tasks. -//------------------------------------------------------------------------ - -class DagTask: public tbb::task { - typedef unsigned long long number_t; - const int i, j; - number_t sum_from_left, sum_from_above; - void check_sum( number_t sum ) { - number_t expected_sum = 1; - for( int k=i+1; k<=i+j; ++k ) - expected_sum *= k; - for( int k=1; k<=j; ++k ) - expected_sum /= k; - ASSERT(sum==expected_sum, NULL); - } -public: - DagTask *successor_to_below, *successor_to_right; - DagTask( int i_, int j_ ) : i(i_), j(j_), sum_from_left(0), sum_from_above(0) {} - task* execute() { - __TBB_ASSERT( ref_count()==0, NULL ); - number_t sum = i==0 && j==0 ? 1 : sum_from_left+sum_from_above; - check_sum(sum); - ++execution_count; - if( DagTask* t = successor_to_right ) { - t->sum_from_left = sum; - if( t->decrement_ref_count()==0 ) - // Test using spawn to evaluate DAG - spawn( *t ); - } - if( DagTask* t = successor_to_below ) { - t->sum_from_above = sum; - if( t->decrement_ref_count()==0 ) - // Test using bypass to evaluate DAG - return t; - } - return NULL; - } - ~DagTask() {++destruction_count;} - static tbb::atomic execution_count; - static tbb::atomic destruction_count; -}; - -tbb::atomic DagTask::execution_count; -tbb::atomic DagTask::destruction_count; - -void TestDag( int p ) { - REMARK("testing evaluation of DAG for %d threads\n",p); - tbb::task_scheduler_init init(p); - DagTask::execution_count=0; - DagTask::destruction_count=0; - const int n = 10; - DagTask* a[n][n]; - for( int i=0; isuccessor_to_below = i+1successor_to_right = j+1set_ref_count((i>0)+(j>0)); - } - a[n-1][n-1]->increment_ref_count(); - a[n-1][n-1]->spawn_and_wait_for_all(*a[0][0]); - ASSERT( DagTask::execution_count == n*n - 1, NULL ); - tbb::task::destroy(*a[n-1][n-1]); - ASSERT( DagTask::destruction_count > n*n - p, NULL ); - while ( DagTask::destruction_count != n*n ) - __TBB_Yield(); -} - -#include "harness_barrier.h" - -class RelaxedOwnershipTask: public tbb::task { - tbb::task &m_taskToSpawn, - &m_taskToDestroy, - &m_taskToExecute; - static Harness::SpinBarrier m_barrier; - - tbb::task* execute () { - tbb::task &p = *parent(); - tbb::task &r = *new( tbb::task::allocate_root() ) tbb::empty_task; - r.set_ref_count( 1 ); - m_barrier.wait(); - p.spawn( *new(p.allocate_child()) tbb::empty_task ); - p.spawn( *new(task::allocate_additional_child_of(p)) tbb::empty_task ); - p.spawn( m_taskToSpawn ); - p.destroy( m_taskToDestroy ); - r.spawn_and_wait_for_all( m_taskToExecute ); - p.destroy( r ); - return NULL; - } -public: - RelaxedOwnershipTask ( tbb::task& toSpawn, tbb::task& toDestroy, tbb::task& toExecute ) - : m_taskToSpawn(toSpawn) - , m_taskToDestroy(toDestroy) - , m_taskToExecute(toExecute) - {} - static void SetBarrier ( int numThreads ) { m_barrier.initialize( numThreads ); } -}; - -Harness::SpinBarrier RelaxedOwnershipTask::m_barrier; - -void TestRelaxedOwnership( int p ) { - if ( p < 2 ) - return; - - if( unsigned(p)>tbb::tbb_thread::hardware_concurrency() ) - return; - - REMARK("testing tasks exercising relaxed ownership freedom for %d threads\n", p); - tbb::task_scheduler_init init(p); - RelaxedOwnershipTask::SetBarrier(p); - tbb::task &r = *new( tbb::task::allocate_root() ) tbb::empty_task; - tbb::task_list tl; - for ( int i = 0; i < p; ++i ) { - tbb::task &tS = *new( r.allocate_child() ) tbb::empty_task, - &tD = *new( r.allocate_child() ) tbb::empty_task, - &tE = *new( r.allocate_child() ) tbb::empty_task; - tl.push_back( *new( r.allocate_child() ) RelaxedOwnershipTask(tS, tD, tE) ); - } - r.set_ref_count( 5 * p + 1 ); - int k=0; - GetTaskPtr(k)->spawn( tl ); - ASSERT(k==1,NULL); - r.wait_for_all(); - r.destroy( r ); -} - -//------------------------------------------------------------------------ -// Test for running TBB scheduler on user-created thread. -//------------------------------------------------------------------------ - -void RunSchedulerInstanceOnUserThread( int n_child ) { - tbb::task* e = new( tbb::task::allocate_root() ) tbb::empty_task; - e->set_ref_count(1+n_child); - for( int i=0; iallocate_child()) tbb::empty_task ); - e->wait_for_all(); - e->destroy(*e); -} - -void TestUserThread( int p ) { - tbb::task_scheduler_init init(p); - // Try with both 0 and 1 children. Only the latter scenario permits stealing. - for( int n_child=0; n_child<2; ++n_child ) { - tbb::tbb_thread t( RunSchedulerInstanceOnUserThread, n_child ); - t.join(); - } -} - - -class TaskWithChildToSteal : public tbb::task { - const int m_Depth; - volatile bool m_GoAhead; - -public: - TaskWithChildToSteal( int depth_ ) - : m_Depth(depth_) - , m_GoAhead(false) - {} - - /*override*/ - tbb::task* execute() { - m_GoAhead = true; - if ( m_Depth > 0 ) { - TaskWithChildToSteal &t = *new( tbb::task::allocate_child() ) TaskWithChildToSteal(m_Depth - 1); - t.SpawnAndWaitOnParent(); - } - else - Harness::Sleep(50); // The last task in chain sleeps for 50 ms - return NULL; - } - - void SpawnAndWaitOnParent() { - parent()->set_ref_count( 2 ); - parent()->spawn( *this ); - while (!this->m_GoAhead ) - __TBB_Yield(); - parent()->wait_for_all(); - } -}; // TaskWithChildToSteal - -void TestDispatchLoopResponsiveness() { - REMARK("testing that dispatch loops do not go into eternal sleep when all remaining children are stolen\n"); - // Recursion depth values test the following sorts of dispatch loops - // 0 - master's outermost - // 1 - worker's nested - // 2 - master's nested - tbb::task_scheduler_init init(2); - tbb::task &r = *new( tbb::task::allocate_root() ) tbb::empty_task; - for ( int depth = 0; depth < 3; ++depth ) { - TaskWithChildToSteal &t = *new( r.allocate_child() ) TaskWithChildToSteal(depth); - t.SpawnAndWaitOnParent(); - } - r.destroy(r); - // The success criteria of this test is not hanging -} - -void TestWaitDiscriminativenessWithoutStealing() { - REMARK( "testing that task::wait_for_all is specific to the root it is called on (no workers)\n" ); - // The test relies on the strict LIFO scheduling order in the absence of workers - tbb::task_scheduler_init init(1); - tbb::task &r1 = *new( tbb::task::allocate_root() ) tbb::empty_task; - tbb::task &r2 = *new( tbb::task::allocate_root() ) tbb::empty_task; - const int NumChildren = 10; - r1.set_ref_count( NumChildren + 1 ); - r2.set_ref_count( NumChildren + 1 ); - for( int i=0; i < NumChildren; ++i ) { - tbb::empty_task &t1 = *new( r1.allocate_child() ) tbb::empty_task; - tbb::empty_task &t2 = *new( r2.allocate_child() ) tbb::empty_task; - tbb::task::spawn(t1); - tbb::task::spawn(t2); - } - r2.wait_for_all(); - ASSERT( r2.ref_count() <= 1, "Not all children of r2 executed" ); - ASSERT( r1.ref_count() > 1, "All children of r1 prematurely executed" ); - r1.wait_for_all(); - ASSERT( r1.ref_count() <= 1, "Not all children of r1 executed" ); - r1.destroy(r1); - r2.destroy(r2); -} - - -using tbb::internal::spin_wait_until_eq; - -//! Deterministic emulation of a long running task -class LongRunningTask : public tbb::task { - volatile bool& m_CanProceed; - - tbb::task* execute() { - spin_wait_until_eq( m_CanProceed, true ); - return NULL; - } -public: - LongRunningTask ( volatile bool& canProceed ) : m_CanProceed(canProceed) {} -}; - -void TestWaitDiscriminativenessWithStealing() { - if( tbb::tbb_thread::hardware_concurrency() < 2 ) - return; - REMARK( "testing that task::wait_for_all is specific to the root it is called on (one worker)\n" ); - volatile bool canProceed = false; - tbb::task_scheduler_init init(2); - tbb::task &r1 = *new( tbb::task::allocate_root() ) tbb::empty_task; - tbb::task &r2 = *new( tbb::task::allocate_root() ) tbb::empty_task; - r1.set_ref_count( 2 ); - r2.set_ref_count( 2 ); - tbb::task& t1 = *new( r1.allocate_child() ) tbb::empty_task; - tbb::task& t2 = *new( r2.allocate_child() ) LongRunningTask(canProceed); - tbb::task::spawn(t2); - tbb::task::spawn(t1); - r1.wait_for_all(); - ASSERT( r1.ref_count() <= 1, "Not all children of r1 executed" ); - ASSERT( r2.ref_count() == 2, "All children of r2 prematurely executed" ); - canProceed = true; - r2.wait_for_all(); - ASSERT( r2.ref_count() <= 1, "Not all children of r2 executed" ); - r1.destroy(r1); - r2.destroy(r2); -} - -struct MasterBody : NoAssign, Harness::NoAfterlife { - static Harness::SpinBarrier my_barrier; - - class BarrenButLongTask : public tbb::task { - volatile bool& m_Started; - volatile bool& m_CanProceed; - - tbb::task* execute() { - m_Started = true; - spin_wait_until_eq( m_CanProceed, true ); - volatile int k = 0; - for ( int i = 0; i < 1000000; ++i ) ++k; - return NULL; - } - public: - BarrenButLongTask ( volatile bool& started, volatile bool& can_proceed ) - : m_Started(started), m_CanProceed(can_proceed) - {} - }; - - class BinaryRecursiveTask : public tbb::task { - int m_Depth; - - tbb::task* execute() { - if( !m_Depth ) - return NULL; - set_ref_count(3); - spawn( *new( tbb::task::allocate_child() ) BinaryRecursiveTask(m_Depth - 1) ); - spawn( *new( tbb::task::allocate_child() ) BinaryRecursiveTask(m_Depth - 1) ); - wait_for_all(); - return NULL; - } - - void note_affinity( affinity_id ) { - __TBB_ASSERT( false, "These tasks cannot be stolen" ); - } - public: - BinaryRecursiveTask ( int depth_ ) : m_Depth(depth_) {} - }; - - void operator() ( int id ) const { - if ( id ) { - tbb::task_scheduler_init init(2); - volatile bool child_started = false, - can_proceed = false; - tbb::task& r = *new( tbb::task::allocate_root() ) tbb::empty_task; - r.set_ref_count(2); - r.spawn( *new(r.allocate_child()) BarrenButLongTask(child_started, can_proceed) ); - spin_wait_until_eq( child_started, true ); - my_barrier.wait(); - can_proceed = true; - r.wait_for_all(); - r.destroy(r); - } - else { - my_barrier.wait(); - tbb::task_scheduler_init init(1); - Count = 0; - int depth = 16; - BinaryRecursiveTask& r = *new( tbb::task::allocate_root() ) BinaryRecursiveTask(depth); - tbb::task::spawn_root_and_wait(r); - } - } -public: - MasterBody ( int num_masters ) { my_barrier.initialize(num_masters); } -}; - -Harness::SpinBarrier MasterBody::my_barrier; - -/** Ensures that tasks spawned by a master thread or one of the workers servicing - it cannot be stolen by another master thread. **/ -void TestMastersIsolation ( int p ) { - // The test requires at least 3-way parallelism to work correctly - if ( p > 2 && tbb::task_scheduler_init::default_num_threads() >= p ) { - tbb::task_scheduler_init init(p); - NativeParallelFor( p, MasterBody(p) ); - } -} - -//------------------------------------------------------------------------ -// Test for tbb::task::enqueue -//------------------------------------------------------------------------ - -const int PairsPerTrack = 100; - -class EnqueuedTask : public tbb::task { - task* my_successor; - int my_enqueue_order; - int* my_track; - tbb::task* execute() { - // Capture execution order in the very beginning - int execution_order = 2 - my_successor->decrement_ref_count(); - // Create some local work. - TaskGenerator& p = *new( tbb::task::allocate_root() ) TaskGenerator(2,2); - tbb::task::spawn_root_and_wait(p); - if( execution_order==2 ) { // the "slower" of two peer tasks - ++nCompletedPairs; - // Of course execution order can differ from dequeue order. - // But there is no better approximation at hand; and a single worker - // will execute in dequeue order, which is enough for our check. - if (my_enqueue_order==execution_order) - ++nOrderedPairs; - FireTwoTasks(my_track); - destroy(*my_successor); - } - return NULL; - } -public: - EnqueuedTask( task* successor, int enq_order, int* track ) - : my_successor(successor), my_enqueue_order(enq_order), my_track(track) {} - - // Create and enqueue two tasks - static void FireTwoTasks( int* track ) { - int progress = ++*track; - if( progress < PairsPerTrack ) { - task* successor = new (tbb::task::allocate_root()) tbb::empty_task; - successor->set_ref_count(2); - enqueue( *new (tbb::task::allocate_root()) EnqueuedTask(successor, 1, track) ); - enqueue( *new (tbb::task::allocate_root()) EnqueuedTask(successor, 2, track) ); - } - } - - static tbb::atomic nCompletedPairs; - static tbb::atomic nOrderedPairs; -}; - -tbb::atomic EnqueuedTask::nCompletedPairs; -tbb::atomic EnqueuedTask::nOrderedPairs; - -const int nTracks = 10; -static int TaskTracks[nTracks]; -const int stall_threshold = 100000; - -void TimedYield( double pause_time ); - -class ProgressMonitor { -public: - void operator() ( ) { - int track_snapshot[nTracks]; - int stall_count = 0, uneven_progress_count = 0, last_progress_mask = 0; - for(int i=0; i 2 ) { - ++uneven_progress_count; - ASSERT(uneven_progress_count < 5, "some enqueued tasks seem stalling; no simultaneous progress?"); - } - } while( !completed ); - } -}; - -void TestEnqueue( int p ) { - REMARK("testing task::enqueue for %d threads\n", p); - for(int mode=0;mode<3;++mode) { - tbb::task_scheduler_init init(p); - EnqueuedTask::nCompletedPairs = EnqueuedTask::nOrderedPairs = 0; - for(int i=0; iset_ref_count(100); - for( int i=0; i<100; ++i ) - tbb::task::enqueue( *new (root->allocate_child()) tbb::empty_task ); - init.terminate(); // master thread deregistered - } - thr.join(); - ASSERT(EnqueuedTask::nCompletedPairs==nTracks*PairsPerTrack, NULL); - ASSERT(EnqueuedTask::nOrderedPairs(); - TestUnconstructibleTask<10000>(); -#endif - TestAlignment(); - TestNoteAffinityContext(); - TestDispatchLoopResponsiveness(); - TestWaitDiscriminativenessWithoutStealing(); - TestWaitDiscriminativenessWithStealing(); - for( int p=MinThread; p<=MaxThread; ++p ) { - TestSpawnChildren( p ); - TestSpawnRootList( p ); - TestSafeContinuation( p ); - TestEnqueue( p ); - TestLeftRecursion( p ); - TestDag( p ); - TestAffinity( p ); - TestUserThread( p ); - TestStealLimit( p ); - TestRelaxedOwnership( p ); -#if __TBB_ARENA_PER_MASTER - TestMastersIsolation( p ); -#endif /* __TBB_ARENA_PER_MASTER */ - } - return Harness::Done; -} - -#include "tbb/tick_count.h" -void TimedYield( double pause_time ) { - tbb::tick_count start = tbb::tick_count::now(); - while( (tbb::tick_count::now()-start).seconds() < pause_time ) - __TBB_Yield(); -} - diff --git a/deal.II/contrib/tbb/tbb30_104oss/src/test/test_task_assertions.cpp b/deal.II/contrib/tbb/tbb30_104oss/src/test/test_task_assertions.cpp deleted file mode 100644 index b5b998422e..0000000000 --- a/deal.II/contrib/tbb/tbb30_104oss/src/test/test_task_assertions.cpp +++ /dev/null @@ -1,103 +0,0 @@ -/* - Copyright 2005-2010 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. -*/ - -// Test correctness of forceful TBB initialization before any dynamic initialization -// of static objects inside the library took place. -namespace tbb { -namespace internal { - // Forward declaration of the TBB general initialization routine from task.cpp - void DoOneTimeInitializations(); -}} - -struct StaticInitializationChecker { - StaticInitializationChecker () { tbb::internal::DoOneTimeInitializations(); } -} theChecker; - -//------------------------------------------------------------------------ -// Test that important assertions in class task fail as expected. -//------------------------------------------------------------------------ - -#include "harness_inject_scheduler.h" - -#define HARNESS_NO_PARSE_COMMAND_LINE 1 -#include "harness.h" -#include "harness_bad_expr.h" - -#if TRY_BAD_EXPR_ENABLED -//! Task that will be abused. -tbb::task* volatile AbusedTask; - -//! Number of times that AbuseOneTask -int AbuseOneTaskRan; - -//! Body used to create task in thread 0 and abuse it in thread 1. -struct AbuseOneTask { - void operator()( int ) const { - tbb::task_scheduler_init init; - // Thread 1 attempts to incorrectly use the task created by thread 0. - tbb::task_list list; - // spawn_root_and_wait over empty list should vacuously succeed. - tbb::task::spawn_root_and_wait(list); - - // Check that spawn_root_and_wait fails on non-empty list. - list.push_back(*AbusedTask); - - // Try abusing recycle_as_continuation - TRY_BAD_EXPR(AbusedTask->recycle_as_continuation(), "execute" ); - TRY_BAD_EXPR(AbusedTask->recycle_as_safe_continuation(), "execute" ); - TRY_BAD_EXPR(AbusedTask->recycle_to_reexecute(), "execute" ); - ++AbuseOneTaskRan; - } -}; - -//! Test various __TBB_ASSERT assertions related to class tbb::task. -void TestTaskAssertions() { - // Catch assertion failures - tbb::set_assertion_handler( AssertionFailureHandler ); - tbb::task_scheduler_init init; - // Create task to be abused - AbusedTask = new( tbb::task::allocate_root() ) tbb::empty_task; - NativeParallelFor( 1, AbuseOneTask() ); - ASSERT( AbuseOneTaskRan==1, NULL ); - AbusedTask->destroy(*AbusedTask); - // Restore normal assertion handling - tbb::set_assertion_handler( NULL ); -} - -int TestMain () { - TestTaskAssertions(); - return Harness::Done; -} - -#else /* !TRY_BAD_EXPR_ENABLED */ - -int TestMain () { - return Harness::Skipped; -} - -#endif /* !TRY_BAD_EXPR_ENABLED */ diff --git a/deal.II/contrib/tbb/tbb30_104oss/src/test/test_task_auto_init.cpp b/deal.II/contrib/tbb/tbb30_104oss/src/test/test_task_auto_init.cpp deleted file mode 100644 index 261b1df6ec..0000000000 --- a/deal.II/contrib/tbb/tbb30_104oss/src/test/test_task_auto_init.cpp +++ /dev/null @@ -1,196 +0,0 @@ -/* - Copyright 2005-2010 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. -*/ - -// Testing automatic initialization of TBB task scheduler, so do not use task_scheduler_init anywhere. - -#include "tbb/task.h" - -#define HARNESS_NO_PARSE_COMMAND_LINE 1 -#include "harness.h" -#include "tbb/atomic.h" - -static tbb::atomic g_NumTestsExecuted; - -#define TEST_PROLOGUE() ++g_NumTestsExecuted - -// Global data used in testing use cases with cross-thread usage of TBB objects -static tbb::task *g_Root1 = NULL, - *g_Root2 = NULL, - *g_Root3 = NULL, - *g_Task = NULL; -static tbb::task_group_context* g_Ctx = NULL; - - -void TestTaskSelf () { - TEST_PROLOGUE(); - tbb::task& t = tbb::task::self(); - ASSERT( !t.parent() && t.ref_count() == 1 && !t.affinity(), "Master's default task properties changed?" ); -} - -void TestRootAllocation () { - TEST_PROLOGUE(); - tbb::task &r = *new( tbb::task::allocate_root() ) tbb::empty_task; - tbb::task::spawn_root_and_wait(r); -} - -inline void ExecuteChildAndCleanup ( tbb::task &r, tbb::task &t ) { - r.set_ref_count(2); - r.spawn_and_wait_for_all(t); - r.destroy(r); -} - -void TestChildAllocation () { - TEST_PROLOGUE(); - tbb::task &t = *new( g_Root1->allocate_child() ) tbb::empty_task; - ExecuteChildAndCleanup( *g_Root1, t ); -} - -void TestAdditionalChildAllocation () { - TEST_PROLOGUE(); - tbb::task &t = *new( g_Root2->allocate_additional_child_of(*g_Root2) ) tbb::empty_task; - ExecuteChildAndCleanup( *g_Root2, t ); -} - -void TestTaskGroupContextCreation () { - TEST_PROLOGUE(); - tbb::task_group_context ctx; - tbb::task &r = *new( tbb::task::allocate_root(ctx) ) tbb::empty_task; - tbb::task::spawn_root_and_wait(r); -} - -void TestRootAllocationWithContext () { - TEST_PROLOGUE(); - tbb::task* root = new( tbb::task::allocate_root(*g_Ctx) ) tbb::empty_task; - tbb::task::spawn_root_and_wait(*root); -} - -void TestSpawn () { - TEST_PROLOGUE(); - g_Task->spawn(*g_Task); -} - -void TestWaitForAll () { - TEST_PROLOGUE(); - g_Root3->wait_for_all(); - g_Root3->destroy( *g_Root3 ); -} - -typedef void (*TestFnPtr)(); - -const TestFnPtr TestFuncsTable[] = { - TestTaskSelf, TestRootAllocation, TestChildAllocation, TestAdditionalChildAllocation, - TestTaskGroupContextCreation, TestRootAllocationWithContext, TestSpawn, TestWaitForAll }; - -const int NumTestFuncs = sizeof(TestFuncsTable) / sizeof(TestFnPtr); - -struct TestThreadBody : NoAssign, Harness::NoAfterlife { - // Each invocation of operator() happens in a fresh thread with zero-based ID - // id, and checks a specific auto-initialization scenario. - void operator() ( int id ) const { - ASSERT( id >= 0 && id < NumTestFuncs, "Test diver: NativeParallelFor is used incorrectly" ); - TestFuncsTable[id](); - } -}; - - -#include "../tbb/tls.h" - -void UseAFewNewTlsKeys () { - tbb::internal::tls tls1, tls2, tls3, tls4; - tls1 = tls2 = tls3 = tls4 = -1; -} - -using tbb::internal::spin_wait_until_eq; - -volatile bool FafStarted = false, - FafCanFinish = false, - FafCompleted = false; - -//! This task is supposed to be executed during termination of an auto-initialized master thread -class FireAndForgetTask : public tbb::task { - tbb::task* execute () { - // Let another master thread proceed requesting new TLS keys - FafStarted = true; - UseAFewNewTlsKeys(); - // Wait while another master thread dirtied its new TLS slots - spin_wait_until_eq( FafCanFinish, true ); - FafCompleted = true; - return NULL; - } -public: // to make gcc 3.2.3 happy - ~FireAndForgetTask() { - ASSERT(FafCompleted, "FireAndForgetTask got erroneously cancelled?"); - } -}; - -#include "harness_barrier.h" -Harness::SpinBarrier driver_barrier(2); - -struct DriverThreadBody : NoAssign, Harness::NoAfterlife { - void operator() ( int id ) const { - ASSERT( id < 2, "Only two test driver threads are expected" ); - // a barrier is required to ensure both threads started; otherwise the test may deadlock: - // the first thread would execute FireAndForgetTask at shutdown and wait for FafCanFinish, - // while the second thread wouldn't even start waiting for the loader lock hold by the first one. - if ( id == 0 ) { - driver_barrier.wait(); - // Prepare global data - g_Root1 = new( tbb::task::allocate_root() ) tbb::empty_task; - g_Root2 = new( tbb::task::allocate_root() ) tbb::empty_task; - g_Root3 = new( tbb::task::allocate_root() ) tbb::empty_task; - g_Task = new( g_Root3->allocate_child() ) tbb::empty_task; - g_Root3->set_ref_count(2); - // Run tests - NativeParallelFor( NumTestFuncs, TestThreadBody() ); - ASSERT( g_NumTestsExecuted == NumTestFuncs, "Test driver: Wrong number of tests executed" ); - - // This test checks the validity of temporarily restoring the value of - // the last TLS slot for a given key during the termination of an - // auto-initialized master thread (in governor::auto_terminate). - // If anything goes wrong, generic_scheduler::cleanup_master() will assert. - // The context for this task must be valid till the task completion. - tbb::task &r = *new( tbb::task::allocate_root(*g_Ctx) ) FireAndForgetTask; - r.spawn(r); - } - else { - tbb::task_group_context ctx; - g_Ctx = &ctx; - driver_barrier.wait(); - spin_wait_until_eq( FafStarted, true ); - UseAFewNewTlsKeys(); - FafCanFinish = true; - spin_wait_until_eq( FafCompleted, true ); - } - } -}; - -int TestMain () { - // Do not use any TBB functionality in the main thread! - NativeParallelFor( 2, DriverThreadBody() ); - return Harness::Done; -} diff --git a/deal.II/contrib/tbb/tbb30_104oss/src/test/test_task_group.cpp b/deal.II/contrib/tbb/tbb30_104oss/src/test/test_task_group.cpp deleted file mode 100644 index 4d687370c2..0000000000 --- a/deal.II/contrib/tbb/tbb30_104oss/src/test/test_task_group.cpp +++ /dev/null @@ -1,848 +0,0 @@ -/* - Copyright 2005-2010 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. -*/ - -//! task_handle cannot be instantiated with a function ptr without explicit cast -#define __TBB_FUNC_PTR_AS_TEMPL_PARAM_BROKEN ((__linux__ || __APPLE__) && __INTEL_COMPILER && __INTEL_COMPILER < 1100) || __SUNPRO_CC -#define __TBB_UNQUALIFIED_CALL_OF_DTOR_BROKEN (__GNUC__==3 && __GNUC_MINOR__<=3) - -#ifndef TBBTEST_USE_TBB - #define TBBTEST_USE_TBB 1 -#endif - -#if !TBBTEST_USE_TBB - #if defined(_MSC_VER) && _MSC_VER < 1600 - #ifdef TBBTEST_USE_TBB - #undef TBBTEST_USE_TBB - #endif - #define TBBTEST_USE_TBB 1 - #endif -#endif - -#if TBBTEST_USE_TBB - - #include "tbb/compat/ppl.h" - #include "tbb/task_scheduler_init.h" - - #if _MSC_VER - typedef tbb::internal::uint32_t uint_t; - #else - typedef uint32_t uint_t; - #endif - -#else /* !TBBTEST_USE_TBB */ - - #if defined(_MSC_VER) - #pragma warning(disable: 4100 4180) - #endif - - #include - - typedef unsigned int uint_t; - - #define __TBB_SILENT_CANCELLATION_BROKEN (_MSC_VER == 1600) - -#endif /* !TBBTEST_USE_TBB */ - - -#include "tbb/atomic.h" -#include "harness_concurrency_tracker.h" - -unsigned g_MaxConcurrency = 0; - -typedef tbb::atomic atomic_t; -typedef Concurrency::task_handle handle_type; - -//------------------------------------------------------------------------ -// Tests for the thread safety of the task_group manipulations -//------------------------------------------------------------------------ - -#include "harness_barrier.h" - -enum SharingMode { - VagabondGroup = 1, - ParallelWait = 2 -}; - -class SharedGroupBodyImpl : NoCopy, Harness::NoAfterlife { - static const uint_t c_numTasks0 = 4096, - c_numTasks1 = 1024; - - const uint_t m_numThreads; - const uint_t m_sharingMode; - - Concurrency::task_group *m_taskGroup; - atomic_t m_tasksSpawned, - m_threadsReady; - Harness::SpinBarrier m_barrier; - - static atomic_t s_tasksExecuted; - - struct TaskFunctor { - SharedGroupBodyImpl *m_pOwner; - void operator () () const { - if ( m_pOwner->m_sharingMode & ParallelWait ) { - while ( Harness::ConcurrencyTracker::PeakParallelism() < m_pOwner->m_numThreads ) - __TBB_Yield(); - } - ++s_tasksExecuted; - } - }; - - TaskFunctor m_taskFunctor; - - void Spawn ( uint_t numTasks ) { - for ( uint_t i = 0; i < numTasks; ++i ) { - ++m_tasksSpawned; - Harness::ConcurrencyTracker ct; - m_taskGroup->run( m_taskFunctor ); - } - ++m_threadsReady; - } - - void DeleteTaskGroup () { - delete m_taskGroup; - m_taskGroup = NULL; - } - - void Wait () { - while ( m_threadsReady != m_numThreads ) - __TBB_Yield(); - const uint_t numSpawned = c_numTasks0 + c_numTasks1 * (m_numThreads - 1); - ASSERT ( m_tasksSpawned == numSpawned, "Wrong number of spawned tasks. The test is broken" ); - REMARK("Max spawning parallelism is %u out of %u", Harness::ConcurrencyTracker::PeakParallelism(), g_MaxConcurrency); - if ( m_sharingMode & ParallelWait ) { - m_barrier.wait( &Harness::ConcurrencyTracker::Reset ); - { - Harness::ConcurrencyTracker ct; - m_taskGroup->wait(); - } - if ( Harness::ConcurrencyTracker::PeakParallelism() == 1 ) - REPORT ( "Warning: No parallel waiting detected in TestParallelWait\n" ); - m_barrier.wait(); - } - else - m_taskGroup->wait(); - ASSERT ( m_tasksSpawned == numSpawned, "No tasks should be spawned after wait starts. The test is broken" ); - ASSERT ( s_tasksExecuted == numSpawned, "Not all spawned tasks were executed" ); - } - -public: - SharedGroupBodyImpl ( uint_t numThreads, uint_t sharingMode = 0 ) - : m_numThreads(numThreads) - , m_sharingMode(sharingMode) - , m_taskGroup(NULL) - , m_barrier(numThreads) - { - ASSERT ( m_numThreads > 1, "SharedGroupBody tests require concurrency" ); - ASSERT ( !(m_sharingMode & VagabondGroup) || m_numThreads == 2, "In vagabond mode SharedGroupBody must be used with 2 threads only" ); - Harness::ConcurrencyTracker::Reset(); - s_tasksExecuted = 0; - m_tasksSpawned = 0; - m_threadsReady = 0; - m_taskFunctor.m_pOwner = this; - } - - void Run ( uint_t idx ) { -#if TBBTEST_USE_TBB - tbb::task_scheduler_init init; -#endif - AssertLive(); - if ( idx == 0 ) { - ASSERT ( !m_taskGroup && !m_tasksSpawned, "SharedGroupBody must be reset before reuse"); - m_taskGroup = new Concurrency::task_group; - Spawn( c_numTasks0 ); - Wait(); - if ( m_sharingMode & VagabondGroup ) - m_barrier.wait(); - else - DeleteTaskGroup(); - } - else { - while ( m_tasksSpawned == 0 ) - __TBB_Yield(); - ASSERT ( m_taskGroup, "Task group is not initialized"); - Spawn (c_numTasks1); - if ( m_sharingMode & ParallelWait ) - Wait(); - if ( m_sharingMode & VagabondGroup ) { - ASSERT ( idx == 1, "In vagabond mode SharedGroupBody must be used with 2 threads only" ); - m_barrier.wait(); - DeleteTaskGroup(); - } - } - AssertLive(); - } -}; - -atomic_t SharedGroupBodyImpl::s_tasksExecuted; - -class SharedGroupBody : NoAssign, Harness::NoAfterlife { - bool m_bOwner; - mutable SharedGroupBodyImpl *m_pImpl; -public: - SharedGroupBody ( uint_t numThreads, uint_t sharingMode = 0 ) - : m_bOwner(true) - , m_pImpl( new SharedGroupBodyImpl(numThreads, sharingMode) ) - {} - SharedGroupBody ( const SharedGroupBody& src ) - : NoAssign() - , Harness::NoAfterlife() - , m_bOwner(false) - , m_pImpl(src.m_pImpl) - {} - ~SharedGroupBody () { - if ( m_bOwner ) - delete m_pImpl; - } - void operator() ( uint_t idx ) const { m_pImpl->Run(idx); } -}; - -void TestParallelSpawn () { - NativeParallelFor( g_MaxConcurrency, SharedGroupBody(g_MaxConcurrency) ); -} - -void TestParallelWait () { - NativeParallelFor( g_MaxConcurrency, SharedGroupBody(g_MaxConcurrency, ParallelWait) ); -} - -// Tests non-stack-bound task group (the group that is allocated by one thread and destroyed by the other) -void TestVagabondGroup () { - NativeParallelFor( 2, SharedGroupBody(2, VagabondGroup) ); -} - -//------------------------------------------------------------------------ -// Common requisites of the Fibonacci tests -//------------------------------------------------------------------------ - -const uint_t N = 20; -const uint_t F = 6765; - -atomic_t g_Sum; - -#define FIB_TEST_PROLOGUE() \ - const unsigned numRepeats = g_MaxConcurrency * (TBB_USE_DEBUG ? 4 : 16); \ - Harness::ConcurrencyTracker::Reset() - -#define FIB_TEST_EPILOGUE(sum) \ - ASSERT( sum == numRepeats * F, NULL ); \ - REMARK("Realized parallelism in Fib test is %u out of %u", Harness::ConcurrencyTracker::PeakParallelism(), g_MaxConcurrency) - -//------------------------------------------------------------------------ -// Test for a complex tree of task groups -// -// The test executes a tree of task groups of the same sort with asymmetric -// descendant nodes distribution at each level at each level. -// -// The chores are specified as functor objects. Each task group contains only one chore. -//------------------------------------------------------------------------ - -template -struct FibTask : NoAssign, Harness::NoAfterlife { - uint_t* m_pRes; - const uint_t m_Num; - FibTask( uint_t* y, uint_t n ) : m_pRes(y), m_Num(n) {} - void operator() () const { - *m_pRes = Func(m_Num); - } -}; - -uint_t Fib_SpawnRightChildOnly ( uint_t n ) { - Harness::ConcurrencyTracker ct; - if( n<2 ) { - return n; - } else { - uint_t y = ~0u; - Concurrency::task_group tg; - tg.run( FibTask(&y, n-1) ); - uint_t x = Fib_SpawnRightChildOnly(n-2); - tg.wait(); - return y+x; - } -} - -void TestFib1 () { - FIB_TEST_PROLOGUE(); - uint_t sum = 0; - for( unsigned i = 0; i < numRepeats; ++i ) - sum += Fib_SpawnRightChildOnly(N); - FIB_TEST_EPILOGUE(sum); -} - - -//------------------------------------------------------------------------ -// Test for a mixed tree of task groups. -// -// The test executes a tree with multiple task of one sort at the first level, -// each of which originates in its turn a binary tree of descendant task groups. -// -// The chores are specified both as functor objects and as function pointers -//------------------------------------------------------------------------ - -uint_t Fib_SpawnBothChildren( uint_t n ) { - Harness::ConcurrencyTracker ct; - if( n<2 ) { - return n; - } else { - uint_t y = ~0u, - x = ~0u; - Concurrency::task_group tg; - tg.run( FibTask(&x, n-2) ); - tg.run( FibTask(&y, n-1) ); - tg.wait(); - return y + x; - } -} - -void RunFib2 () { - g_Sum += Fib_SpawnBothChildren(N); -} - -void TestFib2 () { - FIB_TEST_PROLOGUE(); - g_Sum = 0; - Concurrency::task_group rg; - for( unsigned i = 0; i < numRepeats - 1; ++i ) - rg.run( &RunFib2 ); - rg.wait(); - rg.run( &RunFib2 ); - rg.wait(); - FIB_TEST_EPILOGUE(g_Sum); -} - - -//------------------------------------------------------------------------ -// Test for a complex tree of task groups -// The chores are specified as task handles for recursive functor objects. -//------------------------------------------------------------------------ - -class FibTask_SpawnRightChildOnly : NoAssign, Harness::NoAfterlife { - uint_t* m_pRes; - mutable uint_t m_Num; - -public: - FibTask_SpawnRightChildOnly( uint_t* y, uint_t n ) : m_pRes(y), m_Num(n) {} - void operator() () const { - Harness::ConcurrencyTracker ct; - AssertLive(); - if( m_Num < 2 ) { - *m_pRes = m_Num; - } else { - uint_t y = ~0u; - Concurrency::task_group tg; - Concurrency::task_handle h = FibTask_SpawnRightChildOnly(&y, m_Num-1); - tg.run( h ); - m_Num -= 2; - tg.run_and_wait( *this ); - *m_pRes += y; - } - } -}; - -uint_t RunFib3 ( uint_t n ) { - uint_t res = ~0u; - FibTask_SpawnRightChildOnly func(&res, n); - func(); - return res; -} - -void TestTaskHandle () { - FIB_TEST_PROLOGUE(); - uint_t sum = 0; - for( unsigned i = 0; i < numRepeats; ++i ) - sum += RunFib3(N); - FIB_TEST_EPILOGUE(sum); -} - -//------------------------------------------------------------------------ -// Test for a mixed tree of task groups. -// The chores are specified as task handles for both functor objects and function pointers -//------------------------------------------------------------------------ - -template -class FibTask_SpawnBothChildren : NoAssign, Harness::NoAfterlife { - uint_t* m_pRes; - uint_t m_Num; -public: - FibTask_SpawnBothChildren( uint_t* y, uint_t n ) : m_pRes(y), m_Num(n) {} - void operator() () const { - Harness::ConcurrencyTracker ct; - AssertLive(); - if( m_Num < 2 ) { - *m_pRes = m_Num; - } else { - uint_t x = ~0u, // initialized only to suppress warning - y = ~0u; - task_group_type tg; - Concurrency::task_handle h1 = FibTask_SpawnBothChildren(&y, m_Num-1), - h2 = FibTask_SpawnBothChildren(&x, m_Num-2); - tg.run( h1 ); - tg.run( h2 ); - tg.wait(); - *m_pRes = x + y; - } - } -}; - -template -void RunFib4 () { - uint_t res = ~0u; - FibTask_SpawnBothChildren func(&res, N); - func(); - g_Sum += res; -} - -template -void TestTaskHandle2 () { - FIB_TEST_PROLOGUE(); - g_Sum = 0; - task_group_type rg; - const unsigned hSize = sizeof(handle_type); - char *handles = new char [numRepeats * hSize]; - handle_type *h = NULL; - for( unsigned i = 0; ; ++i ) { - h = (handle_type*)(handles + i * hSize); -#if __TBB_FUNC_PTR_AS_TEMPL_PARAM_BROKEN - new ( h ) handle_type((void(*)())RunFib4); -#else - new ( h ) handle_type(RunFib4); -#endif - if ( i == numRepeats - 1 ) - break; - rg.run( *h ); -#if TBB_USE_EXCEPTIONS && !__TBB_THROW_ACROSS_MODULE_BOUNDARY_BROKEN - bool caught = false; - try { - rg.run( *h ); - } - catch ( Concurrency::invalid_multiple_scheduling& e ) { - ASSERT( e.what(), "Error message is absent" ); - caught = true; - } - catch ( ... ) { - ASSERT ( __TBB_EXCEPTION_TYPE_INFO_BROKEN, "Unrecognized exception" ); - } - ASSERT ( caught, "Expected invalid_multiple_scheduling exception is missing" ); -#endif /* TBB_USE_EXCEPTIONS && !__TBB_THROW_ACROSS_MODULE_BOUNDARY_BROKEN */ - } - rg.run_and_wait( *h ); - for( unsigned i = 0; i < numRepeats; ++i ) -#if __TBB_UNQUALIFIED_CALL_OF_DTOR_BROKEN - ((handle_type*)(handles + i * hSize))->Concurrency::task_handle::~task_handle(); -#else - ((handle_type*)(handles + i * hSize))->~handle_type(); -#endif - delete []handles; - FIB_TEST_EPILOGUE(g_Sum); -} - -#if __TBB_LAMBDAS_PRESENT -//------------------------------------------------------------------------ -// Test for a mixed tree of task groups. -// The chores are specified as lambdas -//------------------------------------------------------------------------ - -void TestFibWithLambdas () { - REMARK ("Lambdas test"); - FIB_TEST_PROLOGUE(); - atomic_t sum; - sum = 0; - Concurrency::task_group rg; - for( unsigned i = 0; i < numRepeats; ++i ) - rg.run( [&](){sum += Fib_SpawnBothChildren(N);} ); - rg.wait(); - FIB_TEST_EPILOGUE(sum); -} - -//------------------------------------------------------------------------ -// Test for make_task. -// The chores are specified as lambdas converted to task_handles. -//------------------------------------------------------------------------ - -void TestFibWithMakeTask () { - REMARK ("Make_task test"); - atomic_t sum; - sum = 0; - Concurrency::task_group rg; - const auto &h1 = Concurrency::make_task( [&](){sum += Fib_SpawnBothChildren(N);} ); - const auto &h2 = Concurrency::make_task( [&](){sum += Fib_SpawnBothChildren(N);} ); - rg.run( h1 ); - rg.run_and_wait( h2 ); - ASSERT( sum == 2 * F, NULL ); -} -#endif /* __TBB_LAMBDAS_PRESENT */ - - -//------------------------------------------------------------------------ -// Tests for exception handling and cancellation behavior. -//------------------------------------------------------------------------ - -class test_exception : public std::exception -{ - const char* m_strDescription; -public: - test_exception ( const char* descr ) : m_strDescription(descr) {} - - const char* what() const throw() { return m_strDescription; } -}; - -#if TBB_USE_CAPTURED_EXCEPTION - #include "tbb/tbb_exception.h" - typedef tbb::captured_exception TestException; -#else - typedef test_exception TestException; -#endif - -#include - -#define NUM_CHORES 512 -#define NUM_GROUPS 64 -#define SKIP_CHORES (NUM_CHORES/4) -#define SKIP_GROUPS (NUM_GROUPS/4) -#define EXCEPTION_DESCR1 "Test exception 1" -#define EXCEPTION_DESCR2 "Test exception 2" - -atomic_t g_ExceptionCount; -atomic_t g_TaskCount; -unsigned g_ExecutedAtCancellation; -bool g_Rethrow; -bool g_Throw; -#if __TBB_SILENT_CANCELLATION_BROKEN - volatile bool g_CancellationPropagationInProgress; - #define CATCH_ANY() \ - __TBB_CATCH( ... ) { \ - if ( g_CancellationPropagationInProgress ) { \ - if ( g_Throw ) { \ - exceptionCaught = true; \ - ++g_ExceptionCount; \ - } \ - } else \ - ASSERT( false, "Unknown exception" ); \ - } -#else - #define CATCH_ANY() __TBB_CATCH( ... ) { ASSERT( __TBB_EXCEPTION_TYPE_INFO_BROKEN, "Unknown exception" ); } -#endif - -inline -void ResetGlobals ( bool bThrow, bool bRethrow ) { - g_Throw = bThrow; - g_Rethrow = bRethrow; -#if __TBB_SILENT_CANCELLATION_BROKEN - g_CancellationPropagationInProgress = false; -#endif - g_ExceptionCount = 0; - g_TaskCount = 0; - Harness::ConcurrencyTracker::Reset(); -} - -class ThrowingTask : NoAssign, Harness::NoAfterlife { - atomic_t &m_TaskCount; -public: - ThrowingTask( atomic_t& counter ) : m_TaskCount(counter) {} - void operator() () const { - Harness::ConcurrencyTracker ct; - AssertLive(); - if ( g_Throw ) { - if ( ++m_TaskCount == SKIP_CHORES ) - __TBB_THROW( test_exception(EXCEPTION_DESCR1) ); - __TBB_Yield(); - } - else { - ++g_TaskCount; - while( !Concurrency::is_current_task_group_canceling() ) - __TBB_Yield(); - } - } -}; - -void LaunchChildren () { - atomic_t count; - count = 0; - Concurrency::task_group g; - bool exceptionCaught = false; - for( unsigned i = 0; i < NUM_CHORES; ++i ) - g.run( ThrowingTask(count) ); - Concurrency::task_group_status status = Concurrency::not_complete; - __TBB_TRY { - status = g.wait(); - } __TBB_CATCH ( TestException& e ) { -#if TBB_USE_EXCEPTIONS - ASSERT( e.what(), "Empty what() string" ); - ASSERT( __TBB_EXCEPTION_TYPE_INFO_BROKEN || strcmp(e.what(), EXCEPTION_DESCR1) == 0, "Unknown exception" ); -#endif /* TBB_USE_EXCEPTIONS */ - exceptionCaught = true; - ++g_ExceptionCount; - } CATCH_ANY(); - ASSERT( !g_Throw || exceptionCaught || status == Concurrency::canceled, "No exception in the child task group" ); - if ( g_Rethrow && g_ExceptionCount > SKIP_GROUPS ) { -#if __TBB_SILENT_CANCELLATION_BROKEN - g_CancellationPropagationInProgress = true; -#endif - __TBB_THROW( test_exception(EXCEPTION_DESCR2) ); - } -} - -#if TBB_USE_EXCEPTIONS -void TestEh1 () { - ResetGlobals( true, false ); - Concurrency::task_group rg; - for( unsigned i = 0; i < NUM_GROUPS; ++i ) - // TBB version does not require taking function address - rg.run( &LaunchChildren ); - try { - rg.wait(); - } catch ( ... ) { - ASSERT( false, "Unexpected exception" ); - } - ASSERT( g_ExceptionCount <= NUM_GROUPS, "Too many exceptions from the child groups. The test is broken" ); - ASSERT( g_ExceptionCount == NUM_GROUPS, "Not all child groups threw the exception" ); -} - -void TestEh2 () { - ResetGlobals( true, true ); - Concurrency::task_group rg; - bool exceptionCaught = false; - for( unsigned i = 0; i < NUM_GROUPS; ++i ) - // TBB version does not require taking function address - rg.run( &LaunchChildren ); - try { - rg.wait(); - } catch ( TestException& e ) { - ASSERT( e.what(), "Empty what() string" ); - ASSERT( __TBB_EXCEPTION_TYPE_INFO_BROKEN || strcmp(e.what(), EXCEPTION_DESCR2) == 0, "Unknown exception" ); - ASSERT ( !rg.is_canceling(), "wait() has not reset cancellation state" ); - exceptionCaught = true; - } CATCH_ANY(); - ASSERT( exceptionCaught, "No exception thrown from the root task group" ); - ASSERT( g_ExceptionCount >= SKIP_GROUPS, "Too few exceptions from the child groups. The test is broken" ); - ASSERT( g_ExceptionCount <= NUM_GROUPS - SKIP_GROUPS, "Too many exceptions from the child groups. The test is broken" ); - ASSERT( g_ExceptionCount < NUM_GROUPS - SKIP_GROUPS, "None of the child groups was cancelled" ); -} -#endif /* TBB_USE_EXCEPTIONS */ - -//------------------------------------------------------------------------ -// Tests for manual cancellation of the task_group hierarchy -//------------------------------------------------------------------------ - -void TestCancellation1 () { - ResetGlobals( false, false ); - Concurrency::task_group rg; - for( unsigned i = 0; i < NUM_GROUPS; ++i ) - // TBB version does not require taking function address - rg.run( &LaunchChildren ); - ASSERT ( !Concurrency::is_current_task_group_canceling(), "Unexpected cancellation" ); - ASSERT ( !rg.is_canceling(), "Unexpected cancellation" ); -#if __TBB_SILENT_CANCELLATION_BROKEN - g_CancellationPropagationInProgress = true; -#endif - while ( g_MaxConcurrency > 1 && g_TaskCount == 0 ) - __TBB_Yield(); - rg.cancel(); - g_ExecutedAtCancellation = g_TaskCount; - ASSERT ( rg.is_canceling(), "No cancellation reported" ); - rg.wait(); - ASSERT( g_TaskCount <= NUM_GROUPS * NUM_CHORES, "Too many tasks reported. The test is broken" ); - ASSERT( g_TaskCount < NUM_GROUPS * NUM_CHORES, "No tasks were cancelled. Cancellation model changed?" ); - ASSERT( g_TaskCount <= g_ExecutedAtCancellation + Harness::ConcurrencyTracker::PeakParallelism(), "Too many tasks survived cancellation" ); -} - -//------------------------------------------------------------------------ -// Tests for manual cancellation of the structured_task_group hierarchy -//------------------------------------------------------------------------ - -void StructuredLaunchChildren () { - atomic_t count; - count = 0; - Concurrency::structured_task_group g; - bool exceptionCaught = false; - typedef Concurrency::task_handle handle_type; - static const unsigned hSize = sizeof(handle_type); - char handles[NUM_CHORES * hSize]; - for( unsigned i = 0; i < NUM_CHORES; ++i ) { - handle_type *h = (handle_type*)(handles + i * hSize); - new ( h ) handle_type( ThrowingTask(count) ); - g.run( *h ); - } - __TBB_TRY { - g.wait(); - } __TBB_CATCH( TestException& e ) { -#if TBB_USE_EXCEPTIONS - ASSERT( e.what(), "Empty what() string" ); - ASSERT( __TBB_EXCEPTION_TYPE_INFO_BROKEN || strcmp(e.what(), EXCEPTION_DESCR1) == 0, "Unknown exception" ); -#endif /* TBB_USE_EXCEPTIONS */ -#if __TBB_SILENT_CANCELLATION_BROKEN - ASSERT ( !g.is_canceling() || g_CancellationPropagationInProgress, "wait() has not reset cancellation state" ); -#else - ASSERT ( !g.is_canceling(), "wait() has not reset cancellation state" ); -#endif - exceptionCaught = true; - ++g_ExceptionCount; - } CATCH_ANY(); - ASSERT( !g_Throw || exceptionCaught, "No exception in the child task group" ); - for( unsigned i = 0; i < NUM_CHORES; ++i ) - ((handle_type*)(handles + i * hSize))->~handle_type(); - if ( g_Rethrow && g_ExceptionCount > SKIP_GROUPS ) { -#if __TBB_SILENT_CANCELLATION_BROKEN - g_CancellationPropagationInProgress = true; -#endif - __TBB_THROW( test_exception(EXCEPTION_DESCR2) ); - } -} - -class StructuredCancellationTestDriver { - static const unsigned hSize = sizeof(handle_type); - char m_handles[NUM_CHORES * hSize]; - -public: - void Launch ( Concurrency::structured_task_group& rg ) { - ResetGlobals( false, false ); - for( unsigned i = 0; i < NUM_GROUPS; ++i ) { - handle_type *h = (handle_type*)(m_handles + i * hSize); - new ( h ) handle_type( StructuredLaunchChildren ); - rg.run( *h ); - } - ASSERT ( !Concurrency::is_current_task_group_canceling(), "Unexpected cancellation" ); - ASSERT ( !rg.is_canceling(), "Unexpected cancellation" ); -#if __TBB_SILENT_CANCELLATION_BROKEN - g_CancellationPropagationInProgress = true; -#endif - while ( g_MaxConcurrency > 1 && g_TaskCount == 0 ) - __TBB_Yield(); - } - - void Finish () { - for( unsigned i = 0; i < NUM_GROUPS; ++i ) - ((handle_type*)(m_handles + i * hSize))->~handle_type(); - ASSERT( g_TaskCount <= NUM_GROUPS * NUM_CHORES, "Too many tasks reported. The test is broken" ); - ASSERT( g_TaskCount < NUM_GROUPS * NUM_CHORES, "No tasks were cancelled. Cancellation model changed?" ); - ASSERT( g_TaskCount <= g_ExecutedAtCancellation + g_MaxConcurrency, "Too many tasks survived cancellation" ); - } -}; // StructuredCancellationTestDriver - -void TestStructuredCancellation1 () { - StructuredCancellationTestDriver driver; - Concurrency::structured_task_group sg; - driver.Launch( sg ); - sg.cancel(); - g_ExecutedAtCancellation = g_TaskCount; - ASSERT ( sg.is_canceling(), "No cancellation reported" ); - sg.wait(); - driver.Finish(); -} - -#if TBB_USE_EXCEPTIONS -#if defined(_MSC_VER) - #pragma warning (disable: 4127) -#endif - -template -void TestStructuredCancellation2 () { - bool exception_occurred = false, - unexpected_exception = false; - StructuredCancellationTestDriver driver; - try { - Concurrency::structured_task_group tg; - driver.Launch( tg ); - if ( Throw ) - throw int(); // Initiate stack unwinding - } - catch ( const Concurrency::missing_wait& e ) { - ASSERT( e.what(), "Error message is absent" ); - exception_occurred = true; - unexpected_exception = Throw; - } - catch ( int ) { - exception_occurred = true; - unexpected_exception = !Throw; - } - catch ( ... ) { - exception_occurred = unexpected_exception = true; - } - ASSERT( exception_occurred, NULL ); - ASSERT( !unexpected_exception, NULL ); - driver.Finish(); -} -#endif /* TBB_USE_EXCEPTIONS */ - -void EmptyFunction () {} - -void TestStructuredWait () { - Concurrency::structured_task_group sg; - handle_type h(EmptyFunction); - sg.run(h); - sg.wait(); - handle_type h2(EmptyFunction); - sg.run(h2); - sg.wait(); -} - -int TestMain () { - REMARK ("Testing %s task_group functionality\n", TBBTEST_USE_TBB ? "TBB" : "PPL"); - for( int p=MinThread; p<=MaxThread; ++p ) { - g_MaxConcurrency = p; -#if TBBTEST_USE_TBB - tbb::task_scheduler_init init(p); -#else - Concurrency::SchedulerPolicy sp( 4, - Concurrency::SchedulerKind, Concurrency::ThreadScheduler, - Concurrency::MinConcurrency, 1, - Concurrency::MaxConcurrency , p, - Concurrency::TargetOversubscriptionFactor, 1); - Concurrency::Scheduler *s = Concurrency::Scheduler::Create( sp ); -#endif /* !TBBTEST_USE_TBB */ - if ( p > 1 ) { - TestParallelSpawn(); - TestParallelWait(); - TestVagabondGroup(); - } - TestFib1(); - TestFib2(); - TestTaskHandle(); - TestTaskHandle2(); - TestTaskHandle2(); -#if __TBB_LAMBDAS_PRESENT - TestFibWithLambdas(); - TestFibWithMakeTask(); -#endif - TestCancellation1(); - TestStructuredCancellation1(); -#if TBB_USE_EXCEPTIONS && !__TBB_THROW_ACROSS_MODULE_BOUNDARY_BROKEN - TestEh1(); - TestEh2(); - TestStructuredWait(); - TestStructuredCancellation2(); - TestStructuredCancellation2(); -#endif /* TBB_USE_EXCEPTIONS && !__TBB_THROW_ACROSS_MODULE_BOUNDARY_BROKEN */ -#if !TBBTEST_USE_TBB - s->Release(); -#endif - } -#if __TBB_THROW_ACROSS_MODULE_BOUNDARY_BROKEN - REPORT("Known issue: exception handling tests are skipped.\n"); -#endif - return Harness::Done; -} diff --git a/deal.II/contrib/tbb/tbb30_104oss/src/test/test_task_leaks.cpp b/deal.II/contrib/tbb/tbb30_104oss/src/test/test_task_leaks.cpp deleted file mode 100644 index 8d5c012d06..0000000000 --- a/deal.II/contrib/tbb/tbb30_104oss/src/test/test_task_leaks.cpp +++ /dev/null @@ -1,243 +0,0 @@ -/* - Copyright 2005-2010 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. -*/ - -/* The test uses "single produces multiple consumers" (SPMC )pattern to check - if the memory of the tasks stolen by consumer threads is returned to the - producer thread and is reused. - - The test consists of a series of iterations, which execute a task tree. - the test fails is the memory consumption is not stabilized during some - number of iterations. - - After the memory consumption stabilized the memory state is perturbed by - switching producer thread, and the check is repeated. -*/ - -#define __TBB_COUNT_TASK_NODES 1 -#include "harness_inject_scheduler.h" - -#include "tbb/atomic.h" -#include "harness_assert.h" -#include - - -// Test configuration parameters - -//! Maximal number of test iterations -const int MaxIterations = 600; -//! Number of iterations during which the memory consumption must stabilize -const int AsymptoticRange = 100; -//! Number of times the memory state is perturbed to repeat the check -const int NumProducerSwitches = 2; -//! Number of iterations after which the success of producer switch is checked -const int ProducerCheckTimeout = 10; -//! Number of initial iteration used to collect statistics to be used in later checks -const int InitialStatsIterations = 20; - -tbb::atomic Count; -tbb::atomic Exchanger; -tbb::internal::scheduler* Producer; - -#include "tbb/task_scheduler_init.h" - -#define HARNESS_DEFAULT_MIN_THREADS -1 -#include "harness.h" - -using namespace tbb; -using namespace tbb::internal; - -class ChangeProducer: public tbb::task { -public: - /*override*/ tbb::task* execute() { - if( is_stolen_task() ) { - Producer = internal::governor::local_scheduler(); - } - return NULL; - } -}; - -class TaskGenerator: public tbb::task { - const int my_child_count; - int my_depth; -public: - TaskGenerator(int child_count, int depth) : my_child_count(child_count), my_depth(depth) { - ASSERT(my_child_count>1, "The TaskGenerator should produce at least two children"); - } - /*override*/ tbb::task* execute() { - if( my_depth>0 ) { - int child_count = my_child_count; - scheduler* my_sched = internal::governor::local_scheduler(); - tbb::task& c = *new( tbb::task::allocate_continuation() ) tbb::empty_task; - c.set_ref_count( child_count ); - recycle_as_child_of(c); - --child_count; - if( Producer==my_sched ) { - // produce a task and put it into Exchanger - tbb::task* t = new( c.allocate_child() ) tbb::empty_task; - --child_count; - t = Exchanger.fetch_and_store(t); - if( t ) spawn(*t); - } else { - tbb::task* t = Exchanger.fetch_and_store(NULL); - if( t ) spawn(*t); - } - while( child_count ) { - tbb::task* t = new( c.allocate_child() ) TaskGenerator(my_child_count, my_depth-1); - if( my_depth >4 ) enqueue(*t); - else spawn(*t); - --child_count; - } - --my_depth; - return this; - } else { - tbb::task* t = Exchanger.fetch_and_store(NULL); - if( t ) spawn(*t); - return NULL; - } - } -}; - -#include "harness_memory.h" -#if _MSC_VER==1500 && !defined(__INTEL_COMPILER) - // VS2008/VC9 seems to have an issue - #pragma warning( push ) - #pragma warning( disable: 4985 ) -#endif -#include -#if _MSC_VER==1500 && !defined(__INTEL_COMPILER) - #pragma warning( pop ) -#endif - -void RunTaskGenerators( bool switchProducer = false, bool checkProducer = false ) { - if( switchProducer ) - Producer = NULL; - tbb::task* dummy_root = new( tbb::task::allocate_root() ) tbb::empty_task; - dummy_root->set_ref_count( 2 ); - // If no producer, start elections; some worker will take the role - if( Producer ) - dummy_root->spawn( *new( dummy_root->allocate_child() ) tbb::empty_task ); - else - dummy_root->spawn( *new( dummy_root->allocate_child() ) ChangeProducer ); - if( checkProducer && !Producer ) - REPORT("Warning: producer has not changed after 10 attempts; running on a single core?\n"); - for( int j=0; j<100; ++j ) { - if( j&1 ) { - tbb::task& t = *new( tbb::task::allocate_root() ) TaskGenerator(/*child_count=*/4, /*depth=*/6); - tbb::task::spawn_root_and_wait(t); - } else { - tbb::task& t = *new (dummy_root->allocate_additional_child_of(*dummy_root)) - TaskGenerator(/*child_count=*/4, /*depth=*/6); - tbb::task::enqueue(t); - } - } - dummy_root->wait_for_all(); - dummy_root->destroy( *dummy_root ); -} - -//! Tests whether task scheduler allows thieves to hoard task objects. -/** The test takes a while to run, so we run it only with the default - number of threads. */ -void TestTaskReclamation() { - REMARK("testing task reclamation\n"); - - size_t initial_amount_of_memory = 0; - double task_count_sum = 0; - double task_count_sum_square = 0; - double average, sigma; - - tbb::task_scheduler_init init (MinThread); - REMARK("Starting with %d threads\n", MinThread); - // For now, the master will produce "additional" tasks; later a worker will replace it; - Producer = internal::governor::local_scheduler(); - int N = InitialStatsIterations; - // First N iterations fill internal buffers and collect initial statistics - for( int i=0; i 0) - initial_amount_of_memory = m; - - intptr_t n = internal::governor::local_scheduler()->get_task_node_count( /*count_arena_workers=*/true ); - task_count_sum += n; - task_count_sum_square += n*n; - - REMARK( "Consumed %ld bytes and %ld objects (iteration=%d)\n", long(m), long(n), i ); - } - // Calculate statistical values - average = task_count_sum / N; - sigma = sqrt( (task_count_sum_square - task_count_sum*task_count_sum/N)/N ); - REMARK("Average task count: %g, sigma: %g, sum: %g, square sum:%g \n", average, sigma, task_count_sum, task_count_sum_square); - - int last_error_iteration = 0, - producer_switch_iteration = 0, - producer_switches = 0; - bool switchProducer = false, - checkProducer = false; - for( int i=0; i < MaxIterations; ++i ) { - // These iterations check for excessive memory use and unreasonable task count - RunTaskGenerators( switchProducer, checkProducer ); - - intptr_t n = internal::governor::local_scheduler()->get_task_node_count( /*count_arena_workers=*/true ); - size_t m = GetMemoryUsage(); - - if( (m-initial_amount_of_memory > 0) && (n > average+4*sigma) ) { - // Use 4*sigma interval (for normal distribution, 3*sigma contains ~99% of values). - REMARK( "Warning: possible leak of up to %ld bytes; currently %ld cached task objects (iteration=%d)\n", - static_cast(m-initial_amount_of_memory), long(n), i ); - last_error_iteration = i; - initial_amount_of_memory = m; - } else { - REMARK( "Consumed %ld bytes and %ld objects (iteration=%d)\n", long(m), long(n), i ); - } - if ( i == last_error_iteration + AsymptoticRange ) { - if ( producer_switches++ == NumProducerSwitches ) - break; - else { - last_error_iteration = producer_switch_iteration = i; - switchProducer = true; - } - } - else { - switchProducer = false; - checkProducer = producer_switch_iteration && (i == producer_switch_iteration + ProducerCheckTimeout); - } - } - ASSERT( last_error_iteration < MaxIterations - AsymptoticRange, "The amount of allocated tasks keeps growing. Leak is possible." ); -} - -int TestMain () { - if( !GetMemoryUsage() ) { - REMARK("GetMemoryUsage is not implemented for this platform\n"); - return Harness::Skipped; - } - TestTaskReclamation(); - return Harness::Done; -} - diff --git a/deal.II/contrib/tbb/tbb30_104oss/src/test/test_task_scheduler_init.cpp b/deal.II/contrib/tbb/tbb30_104oss/src/test/test_task_scheduler_init.cpp deleted file mode 100644 index 1b953c57cf..0000000000 --- a/deal.II/contrib/tbb/tbb30_104oss/src/test/test_task_scheduler_init.cpp +++ /dev/null @@ -1,151 +0,0 @@ -/* - Copyright 2005-2010 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. -*/ - -#include "tbb/task_scheduler_init.h" -#include -#include "harness_assert.h" - -#include - -#if !TBB_USE_EXCEPTIONS && _MSC_VER - // Suppress "C++ exception handler used, but unwind semantics are not enabled" warning in STL headers - #pragma warning (push) - #pragma warning (disable: 4530) -#endif - -#include - -#if !TBB_USE_EXCEPTIONS && _MSC_VER - #pragma warning (pop) -#endif - -#include "harness.h" - -//! Test that task::initialize and task::terminate work when doing nothing else. -/** maxthread is treated as the "maximum" number of worker threads. */ -void InitializeAndTerminate( int maxthread ) { - __TBB_TRY { - for( int i=0; i<200; ++i ) { - switch( i&3 ) { - default: { - tbb::task_scheduler_init init( std::rand() % maxthread + 1 ); - ASSERT(init.is_active(), NULL); - break; - } - case 0: { - tbb::task_scheduler_init init; - ASSERT(init.is_active(), NULL); - break; - } - case 1: { - tbb::task_scheduler_init init( tbb::task_scheduler_init::automatic ); - ASSERT(init.is_active(), NULL); - break; - } - case 2: { - tbb::task_scheduler_init init( tbb::task_scheduler_init::deferred ); - ASSERT(!init.is_active(), "init should not be active; initialization was deferred"); - init.initialize( std::rand() % maxthread + 1 ); - ASSERT(init.is_active(), NULL); - init.terminate(); - ASSERT(!init.is_active(), "init should not be active; it was terminated"); - break; - } - } - } - } __TBB_CATCH( std::runtime_error& error ) { -#if TBB_USE_EXCEPTIONS - REPORT("ERROR: %s\n", error.what() ); -#endif /* TBB_USE_EXCEPTIONS */ - } -} - -#if _WIN64 -namespace std { // 64-bit Windows compilers have not caught up with 1998 ISO C++ standard - using ::srand; -} -#endif /* _WIN64 */ - -struct ThreadedInit { - void operator()( int ) const { - InitializeAndTerminate(MaxThread); - } -}; - -#if _MSC_VER -#include "tbb/machine/windows_api.h" -#include -#endif /* _MSC_VER */ - -#include "harness_concurrency_tracker.h" -#include "tbb/parallel_for.h" -#include "tbb/blocked_range.h" - -typedef tbb::blocked_range Range; - -class ConcurrencyTrackingBody { -public: - void operator() ( const Range& ) const { - Harness::ConcurrencyTracker ct; - for ( volatile int i = 0; i < 1000000; ++i ) - ; - } -}; - -/** The test will fail in particular if task_scheduler_init mistakenly hooks up - auto-initialization mechanism. **/ -void AssertExplicitInitIsNotSupplanted () { - int hardwareConcurrency = tbb::task_scheduler_init::default_num_threads(); - tbb::task_scheduler_init init(1); - Harness::ConcurrencyTracker::Reset(); - tbb::parallel_for( Range(0, hardwareConcurrency * 2, 1), ConcurrencyTrackingBody(), tbb::simple_partitioner() ); - ASSERT( Harness::ConcurrencyTracker::PeakParallelism() == 1, - "Manual init provided more threads than requested. See also the comment at the beginning of main()." ); -} - -int TestMain () { - // Do not use tbb::task_scheduler_init directly in the scope of main's body, - // as a static variable, or as a member of a static variable. -#if _MSC_VER && !__TBB_NO_IMPLICIT_LINKAGE - #ifdef _DEBUG - ASSERT(!GetModuleHandle(_T("tbb.dll")) && GetModuleHandle(_T("tbb_debug.dll")), - "test linked with wrong (non-debug) tbb library"); - #else - ASSERT(!GetModuleHandle(_T("tbb_debug.dll")) && GetModuleHandle(_T("tbb.dll")), - "test linked with wrong (debug) tbb library"); - #endif -#endif /* _MSC_VER && !__TBB_NO_IMPLICIT_LINKAGE */ - std::srand(2); - InitializeAndTerminate(MaxThread); - for( int p=MinThread; p<=MaxThread; ++p ) { - REMARK("testing with %d threads\n", p ); - NativeParallelFor( p, ThreadedInit() ); - } - AssertExplicitInitIsNotSupplanted(); - return Harness::Done; -} diff --git a/deal.II/contrib/tbb/tbb30_104oss/src/test/test_task_scheduler_observer.cpp b/deal.II/contrib/tbb/tbb30_104oss/src/test/test_task_scheduler_observer.cpp deleted file mode 100644 index 99936f893a..0000000000 --- a/deal.II/contrib/tbb/tbb30_104oss/src/test/test_task_scheduler_observer.cpp +++ /dev/null @@ -1,131 +0,0 @@ -/* - Copyright 2005-2010 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. -*/ - -#include "tbb/task_scheduler_observer.h" - -typedef uintptr_t FlagType; -const int MaxFlagIndex = sizeof(FlagType)*8-1; - -class MyObserver: public tbb::task_scheduler_observer { - FlagType flags; - /*override*/ void on_scheduler_entry( bool is_worker ); - /*override*/ void on_scheduler_exit( bool is_worker ); -public: - MyObserver( FlagType flags_ ) : flags(flags_) { - observe(true); - } -}; - -#include "harness_assert.h" -#include "tbb/atomic.h" - -tbb::atomic EntryCount; -tbb::atomic ExitCount; - -struct State { - FlagType MyFlags; - bool IsMaster; - State() : MyFlags(), IsMaster() {} -}; - -#include "../tbb/tls.h" -tbb::internal::tls LocalState; - -void MyObserver::on_scheduler_entry( bool is_worker ) { - State& state = *LocalState; - ASSERT( is_worker==!state.IsMaster, NULL ); -#if !__TBB_ARENA_PER_MASTER - ASSERT( (state.MyFlags & flags)==0, NULL ); -#endif /* !__TBB_ARENA_PER_MASTER */ - ++EntryCount; - state.MyFlags |= flags; -} - -void MyObserver::on_scheduler_exit( bool is_worker ) { - State& state = *LocalState; - ASSERT( is_worker==!state.IsMaster, NULL ); - ++ExitCount; - state.MyFlags &= ~flags; -} - -#include "tbb/task.h" - -class FibTask: public tbb::task { - const int n; - FlagType flags; -public: - FibTask( int n_, FlagType flags_ ) : n(n_), flags(flags_) {} - /*override*/ tbb::task* execute() { - ASSERT( !(~LocalState->MyFlags & flags), NULL ); - if( n>=2 ) { - set_ref_count(3); - spawn(*new( tbb::task::allocate_child() ) FibTask(n-1,flags)); - spawn_and_wait_for_all(*new( tbb::task::allocate_child() ) FibTask(n-2,flags)); - } - return NULL; - } -}; - -void DoFib( FlagType flags ) { - tbb::task* t = new( tbb::task::allocate_root() ) FibTask(10,flags); - tbb::task::spawn_root_and_wait(*t); -} - -#include "tbb/task_scheduler_init.h" -#include "harness.h" - -class DoTest { - int nthread; -public: - DoTest( int n ) : nthread(n) {} - void operator()( int i ) const { - LocalState->IsMaster = true; - if( i==0 ) { - tbb::task_scheduler_init init(nthread); - DoFib(0); - } else { - FlagType f = i<=MaxFlagIndex? 1<0, "on_scheduler_entry not exercised" ); - ASSERT( ExitCount>0, "on_scheduler_exit not exercised" ); - return Harness::Done; -} diff --git a/deal.II/contrib/tbb/tbb30_104oss/src/test/test_tbb_condition_variable.cpp b/deal.II/contrib/tbb/tbb30_104oss/src/test/test_tbb_condition_variable.cpp deleted file mode 100644 index 74f2d6d9ea..0000000000 --- a/deal.II/contrib/tbb/tbb30_104oss/src/test/test_tbb_condition_variable.cpp +++ /dev/null @@ -1,35 +0,0 @@ -/* - Copyright 2005-2010 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. -*/ - -#include "test_condition_variable.h" - -int TestMain() { - REMARK( "testing with tbb condvar\n" ); - DoCondVarTest(); - return Harness::Done; -} diff --git a/deal.II/contrib/tbb/tbb30_104oss/src/test/test_tbb_header.cpp b/deal.II/contrib/tbb/tbb30_104oss/src/test/test_tbb_header.cpp deleted file mode 100644 index ffffdc64fe..0000000000 --- a/deal.II/contrib/tbb/tbb30_104oss/src/test/test_tbb_header.cpp +++ /dev/null @@ -1,185 +0,0 @@ -/* - Copyright 2005-2010 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 test ensures that tbb.h brings in all the public TBB interface definitions, - and if all the necessary symbols are exported from the library. - - Most of the checks happen at the compilation or link phases. -**/ - -#include "tbb/tbb.h" - -static volatile size_t g_sink; - -#define TestTypeDefinitionPresence( Type ) g_sink = sizeof(tbb::Type); -#define TestTypeDefinitionPresence2(TypeStart, TypeEnd) g_sink = sizeof(tbb::TypeStart,TypeEnd); -#define TestFuncDefinitionPresence(Fn, Args, ReturnType) { ReturnType (*pfn)Args = &tbb::Fn; (void)pfn; } - -struct Body { - void operator() () const {} -}; -struct Body1 { - void operator() ( int ) const {} -}; -struct Body1a { - int operator() ( const tbb::blocked_range&, const int ) const { return 0; } -}; -struct Body1b { - int operator() ( const int, const int ) const { return 0; } -}; -struct Body2 { - Body2 () {} - Body2 ( const Body2&, tbb::split ) {} - void operator() ( const tbb::blocked_range& ) const {} - void join( const Body2& ) {} -}; -struct Body3 { - Body3 () {} - Body3 ( const Body3&, tbb::split ) {} - void operator() ( const tbb::blocked_range2d&, tbb::pre_scan_tag ) const {} - void operator() ( const tbb::blocked_range2d&, tbb::final_scan_tag ) const {} - void reverse_join( Body3& ) {} - void assign( const Body3& ) {} -}; - -#if !__TBB_TEST_SECONDARY - -#define HARNESS_NO_PARSE_COMMAND_LINE 1 -#include "harness.h" - -// Test if all the necessary symbols are exported for the exceptions thrown by TBB. -// Missing exports result either in link error or in runtime assertion failure. -#include "tbb/tbb_exception.h" - -template -void TestExceptionClassExports ( const E& exc, tbb::internal::exception_id eid ) { - // The assertion here serves to shut up warnings about "eid not used". - ASSERT( eid ); - TestTypeDefinitionPresence( atomic ); - TestTypeDefinitionPresence( cache_aligned_allocator ); - TestTypeDefinitionPresence( tbb_hash_compare ); - TestTypeDefinitionPresence2(concurrent_hash_map ); - TestTypeDefinitionPresence2(concurrent_unordered_map ); - TestTypeDefinitionPresence( concurrent_bounded_queue ); - TestTypeDefinitionPresence( deprecated::concurrent_queue ); - TestTypeDefinitionPresence( strict_ppl::concurrent_queue ); - TestTypeDefinitionPresence( combinable ); - TestTypeDefinitionPresence( concurrent_vector ); - TestTypeDefinitionPresence( enumerable_thread_specific ); - TestTypeDefinitionPresence( mutex ); - TestTypeDefinitionPresence( null_mutex ); - TestTypeDefinitionPresence( null_rw_mutex ); - TestTypeDefinitionPresence( queuing_mutex ); - TestTypeDefinitionPresence( queuing_rw_mutex ); - TestTypeDefinitionPresence( recursive_mutex ); - TestTypeDefinitionPresence( spin_mutex ); - TestTypeDefinitionPresence( spin_rw_mutex ); - TestTypeDefinitionPresence( critical_section ); - TestTypeDefinitionPresence( reader_writer_lock ); - TestTypeDefinitionPresence( tbb_exception ); - TestTypeDefinitionPresence( captured_exception ); - TestTypeDefinitionPresence( movable_exception ); -#if !TBB_USE_CAPTURED_EXCEPTION - TestTypeDefinitionPresence( internal::tbb_exception_ptr ); -#endif /* !TBB_USE_CAPTURED_EXCEPTION */ - TestTypeDefinitionPresence( blocked_range3d ); - TestFuncDefinitionPresence( parallel_invoke, (const Body&, const Body&), void ); - TestFuncDefinitionPresence( parallel_do, (int*, int*, const Body1&), void ); - TestFuncDefinitionPresence( parallel_for_each, (int*, int*, const Body1&), void ); - TestFuncDefinitionPresence( parallel_for, (int, int, int, const Body1&), void ); - TestFuncDefinitionPresence( parallel_for, (const tbb::blocked_range&, const Body2&, const tbb::simple_partitioner&), void ); - TestFuncDefinitionPresence( parallel_reduce, (const tbb::blocked_range&, const int&, const Body1a&, const Body1b&, const tbb::auto_partitioner&), int ); - TestFuncDefinitionPresence( parallel_reduce, (const tbb::blocked_range&, Body2&, tbb::affinity_partitioner&), void ); - TestFuncDefinitionPresence( parallel_scan, (const tbb::blocked_range2d&, Body3&, const tbb::auto_partitioner&), void ); - TestFuncDefinitionPresence( parallel_sort, (int*, int*), void ); - TestTypeDefinitionPresence( pipeline ); - TestFuncDefinitionPresence( parallel_pipeline, (size_t, const tbb::filter_t&), void ); - TestTypeDefinitionPresence( task ); - TestTypeDefinitionPresence( empty_task ); - TestTypeDefinitionPresence( task_list ); - TestTypeDefinitionPresence( task_group_context ); - TestTypeDefinitionPresence( task_group ); - TestTypeDefinitionPresence( task_handle ); - TestTypeDefinitionPresence( task_scheduler_init ); - TestTypeDefinitionPresence( task_scheduler_observer ); - TestTypeDefinitionPresence( tbb_thread ); - TestTypeDefinitionPresence( tbb_allocator ); - TestTypeDefinitionPresence( zero_allocator ); - TestTypeDefinitionPresence( tick_count ); -#if !__TBB_TEST_SECONDARY - TestExceptionClassesExports(); - return Harness::Done; -#endif -} diff --git a/deal.II/contrib/tbb/tbb30_104oss/src/test/test_tbb_thread.cpp b/deal.II/contrib/tbb/tbb30_104oss/src/test/test_tbb_thread.cpp deleted file mode 100644 index 962dd408f2..0000000000 --- a/deal.II/contrib/tbb/tbb30_104oss/src/test/test_tbb_thread.cpp +++ /dev/null @@ -1,40 +0,0 @@ -/* - Copyright 2005-2010 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. -*/ - -#define THREAD tbb::tbb_thread -#define THIS_THREAD tbb::this_tbb_thread -#define THIS_THREAD_SLEEP THIS_THREAD::sleep -#include "test_thread.h" -#include "harness.h" - -/* we want to test tbb::tbb_thread */ -int TestMain () { - CheckSignatures(); - RunTests(); - return Harness::Done; -} diff --git a/deal.II/contrib/tbb/tbb30_104oss/src/test/test_tbb_version.cpp b/deal.II/contrib/tbb/tbb30_104oss/src/test/test_tbb_version.cpp deleted file mode 100644 index d6b13f0f97..0000000000 --- a/deal.II/contrib/tbb/tbb30_104oss/src/test/test_tbb_version.cpp +++ /dev/null @@ -1,253 +0,0 @@ -/* - Copyright 2005-2010 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. -*/ - -#include "tbb/tbb_stddef.h" - -#include -#include - -#if !TBB_USE_EXCEPTIONS && _MSC_VER - // Suppress "C++ exception handler used, but unwind semantics are not enabled" warning in STL headers - #pragma warning (push) - #pragma warning (disable: 4530) -#endif - -#include -#include -#include - -#if !TBB_USE_EXCEPTIONS && _MSC_VER - #pragma warning (pop) -#endif - -#include "tbb/task_scheduler_init.h" - -#define HARNESS_CUSTOM_MAIN 1 -#define HARNESS_NO_PARSE_COMMAND_LINE 1 -#define HARNESS_NO_MAIN_ARGS 0 -#include "harness.h" - -#if defined (_WIN32) || defined (_WIN64) -#define TEST_SYSTEM_COMMAND "test_tbb_version.exe @" -#define putenv _putenv -#else -#define TEST_SYSTEM_COMMAND "./test_tbb_version.exe @" -#endif - -enum string_required { - required, - not_required - }; - -typedef std::pair string_pair; - -void initialize_strings_vector(std::vector * vector); - -const char stderr_stream[] = "version_test.err"; -const char stdout_stream[] = "version_test.out"; - -HARNESS_EXPORT -int main(int argc, char *argv[] ) { -/* We first introduced runtime version identification in 3014 */ -#if TBB_INTERFACE_VERSION>=3014 - // For now, just test that run-time TBB version matches the compile-time version, - // since otherwise the subsequent test of "TBB: INTERFACE VERSION" string will fail anyway. - // We need something more clever in future. - ASSERT(tbb::TBB_runtime_interface_version()==TBB_INTERFACE_VERSION, - "Running with the library of different version than the test was compiled against"); -#endif - __TBB_TRY { - FILE *stream_out; - FILE *stream_err; - char psBuffer[512]; - - if(argc>1 && argv[1][0] == '@' ) { - stream_err = freopen( stderr_stream, "w", stderr ); - if( stream_err == NULL ){ - REPORT( "Internal test error (freopen)\n" ); - exit( 1 ); - } - stream_out = freopen( stdout_stream, "w", stdout ); - if( stream_out == NULL ){ - REPORT( "Internal test error (freopen)\n" ); - exit( 1 ); - } - { - tbb::task_scheduler_init init(1); - } - fclose( stream_out ); - fclose( stream_err ); - exit(0); - } - //1st step check that output is empty if TBB_VERSION is not defined. - if ( getenv("TBB_VERSION") ){ - REPORT( "TBB_VERSION defined, skipping step 1 (empty output check)\n" ); - }else{ - if( ( system(TEST_SYSTEM_COMMAND) ) != 0 ){ - REPORT( "Error (step 1): Internal test error\n" ); - exit( 1 ); - } - //Checking output streams - they should be empty - stream_err = fopen( stderr_stream, "r" ); - if( stream_err == NULL ){ - REPORT( "Error (step 1):Internal test error (stderr open)\n" ); - exit( 1 ); - } - while( !feof( stream_err ) ) { - if( fgets( psBuffer, 512, stream_err ) != NULL ){ - REPORT( "Error (step 1): stderr should be empty\n" ); - exit( 1 ); - } - } - fclose( stream_err ); - stream_out = fopen( stdout_stream, "r" ); - if( stream_out == NULL ){ - REPORT( "Error (step 1):Internal test error (stdout open)\n" ); - exit( 1 ); - } - while( !feof( stream_out ) ) { - if( fgets( psBuffer, 512, stream_out ) != NULL ){ - REPORT( "Error (step 1): stdout should be empty\n" ); - exit( 1 ); - } - } - fclose( stream_out ); - } - - //Setting TBB_VERSION in case it is not set - if ( !getenv("TBB_VERSION") ){ - putenv(const_cast("TBB_VERSION=1")); - } - - if( ( system(TEST_SYSTEM_COMMAND) ) != 0 ){ - REPORT( "Error (step 2):Internal test error\n" ); - exit( 1 ); - } - //Checking pipe - it should contain version data - std::vector strings_vector; - std::vector ::iterator strings_iterator; - - initialize_strings_vector( &strings_vector ); - strings_iterator = strings_vector.begin(); - - stream_out = fopen( stdout_stream, "r" ); - if( stream_out == NULL ){ - REPORT( "Error (step 2):Internal test error (stdout open)\n" ); - exit( 1 ); - } - while( !feof( stream_out ) ) { - if( fgets( psBuffer, 512, stream_out ) != NULL ){ - REPORT( "Error (step 2): stdout should be empty\n" ); - exit( 1 ); - } - } - fclose( stream_out ); - - stream_err = fopen( stderr_stream, "r" ); - if( stream_err == NULL ){ - REPORT( "Error (step 1):Internal test error (stderr open)\n" ); - exit( 1 ); - } - - int skip_line = 0; - - while( !feof( stream_err ) ) { - if( fgets( psBuffer, 512, stream_err ) != NULL ){ - do{ - if ( strings_iterator == strings_vector.end() ){ - REPORT( "Error: version string dictionary ended prematurely.\n" ); - REPORT( "No match for: \t%s", psBuffer ); - exit( 1 ); - } - if ( strstr( psBuffer, strings_iterator->first.c_str() ) == NULL ){ - if( strings_iterator->second == required ){ - REPORT( "Error: version strings do not match.\n" ); - REPORT( "Expected \"%s\" not found in:\n\t%s", strings_iterator->first.c_str(), psBuffer ); - exit( 1 ); - }else{ - //Do we need to print in case there is no non-required string? - skip_line = 1; - } - }else{ - skip_line = 0; - } - if ( strings_iterator != strings_vector.end() ) strings_iterator ++; - }while( skip_line ); - } - } - fclose( stream_err ); - } __TBB_CATCH(...) { - ASSERT( 0,"unexpected exception" ); - } - REPORT("done\n"); - return 0; -} - - -// Fill dictionary with version strings for platforms -void initialize_strings_vector(std::vector * vector) -{ - vector->push_back(string_pair("TBB: VERSION\t\t3.0", required)); // check TBB_VERSION - vector->push_back(string_pair("TBB: INTERFACE VERSION\t5003", required)); // check TBB_INTERFACE_VERSION - vector->push_back(string_pair("TBB: BUILD_DATE", required)); - vector->push_back(string_pair("TBB: BUILD_HOST", required)); - vector->push_back(string_pair("TBB: BUILD_OS", required)); -#if _WIN32||_WIN64 -#if !__MINGW32__ - vector->push_back(string_pair("TBB: BUILD_CL", required)); -#endif - vector->push_back(string_pair("TBB: BUILD_COMPILER", required)); -#elif __APPLE__ - vector->push_back(string_pair("TBB: BUILD_KERNEL", required)); - vector->push_back(string_pair("TBB: BUILD_GCC", required)); - vector->push_back(string_pair("TBB: BUILD_COMPILER", not_required)); //if( getenv("COMPILER_VERSION") ) -#elif __sun - vector->push_back(string_pair("TBB: BUILD_KERNEL", required)); - vector->push_back(string_pair("TBB: BUILD_SUNCC", required)); - vector->push_back(string_pair("TBB: BUILD_COMPILER", not_required)); //if( getenv("COMPILER_VERSION") ) -#else //We use version_info_linux.sh for unsupported OSes - vector->push_back(string_pair("TBB: BUILD_KERNEL", required)); - vector->push_back(string_pair("TBB: BUILD_GCC", required)); - vector->push_back(string_pair("TBB: BUILD_COMPILER", not_required)); //if( getenv("COMPILER_VERSION") ) - vector->push_back(string_pair("TBB: BUILD_GLIBC", required)); - vector->push_back(string_pair("TBB: BUILD_LD", required)); -#endif - vector->push_back(string_pair("TBB: BUILD_TARGET", required)); - vector->push_back(string_pair("TBB: BUILD_COMMAND", required)); - vector->push_back(string_pair("TBB: TBB_USE_DEBUG", required)); - vector->push_back(string_pair("TBB: TBB_USE_ASSERT", required)); - vector->push_back(string_pair("TBB: DO_ITT_NOTIFY", required)); - vector->push_back(string_pair("TBB: ITT", not_required)); //#ifdef DO_ITT_NOTIFY - vector->push_back(string_pair("TBB: ALLOCATOR", required)); - vector->push_back(string_pair("TBB: RML", not_required)); - vector->push_back(string_pair("TBB: Intel(R) RML library built:", not_required)); - vector->push_back(string_pair("TBB: Intel(R) RML library version:", not_required)); - vector->push_back(string_pair("TBB: SCHEDULER", required)); - - return; -} diff --git a/deal.II/contrib/tbb/tbb30_104oss/src/test/test_thread.h b/deal.II/contrib/tbb/tbb30_104oss/src/test/test_thread.h deleted file mode 100644 index 888eeef85b..0000000000 --- a/deal.II/contrib/tbb/tbb30_104oss/src/test/test_thread.h +++ /dev/null @@ -1,290 +0,0 @@ -/* - Copyright 2005-2010 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. -*/ - -#include "tbb/tbb_thread.h" -#include "tbb/atomic.h" - -#define HARNESS_NO_PARSE_COMMAND_LINE 1 -#include "harness_report.h" -#include "harness_assert.h" - -static const int THRDS = 3; -static const int THRDS_DETACH = 2; -static tbb::atomic sum; -static tbb::atomic BaseCount; -static THREAD::id real_ids[THRDS+THRDS_DETACH]; - -class Base { - mutable int copy_throws; - friend void RunTests(); - friend void CheckExceptionSafety(); - void operator=( const Base& ); // Deny access -protected: - Base() : copy_throws(100) {++BaseCount;} - Base( const Base& c ) : copy_throws(c.copy_throws) { - if( --copy_throws<=0 ) - __TBB_THROW(0); - ++BaseCount; - } - ~Base() {--BaseCount;} -}; - -template -class Data: Base { - Data(); // Deny access - explicit Data(int v) : value(v) {} - - friend void RunTests(); - friend void CheckExceptionSafety(); -public: - int value; -}; - - -#include "harness_barrier.h" - -class ThreadFunc: Base { - ThreadFunc() {} - - static Harness::SpinBarrier init_barrier; - - friend void RunTests(); -public: - void operator()(){ - real_ids[0] = THIS_THREAD::get_id(); - init_barrier.wait(); - - sum.fetch_and_add(1); - } - void operator()(int num){ - real_ids[num] = THIS_THREAD::get_id(); - init_barrier.wait(); - - sum.fetch_and_add(num); - } - void operator()(int num, Data<0> dx) { - real_ids[num] = THIS_THREAD::get_id(); - - const double WAIT = .1; - const double SHORT_TOLERANCE = 1e-8; -#if _WIN32 || _WIN64 - const double LONG_TOLERANCE = 0.120; // maximal scheduling quantum for Windows Server -#else - const double LONG_TOLERANCE = 0.200; // reasonable upper bound -#endif - tbb::tick_count t0 = tbb::tick_count::now(); - tbb::this_tbb_thread::sleep( tbb::tick_count::interval_t(WAIT) ); - tbb::tick_count t1 = tbb::tick_count::now(); - double delta = (t1-t0).seconds() - WAIT; - if(delta+SHORT_TOLERANCE <= 0.0) - REPORT("ERROR: Sleep interval too short (%g outside short tolerance(%g))\n", (t1-t0).seconds(), WAIT - SHORT_TOLERANCE); - if(delta > LONG_TOLERANCE) - REPORT("WARNING: Sleep interval too long (%g outside long tolerance(%g))\n", (t1-t0).seconds(), WAIT + LONG_TOLERANCE); - - init_barrier.wait(); - - sum.fetch_and_add(num); - sum.fetch_and_add(dx.value); - } - void operator()(Data<0> d) { - tbb::this_tbb_thread::sleep( tbb::tick_count::interval_t(d.value*1.) ); - } -}; - -Harness::SpinBarrier ThreadFunc::init_barrier(THRDS); - -void CheckRelations( const THREAD::id ids[], int n, bool duplicates_allowed ) { - for( int i=0; i=y), NULL ); - ASSERT( (x>y)==!(x<=y), NULL ); - ASSERT( (xy)==1, NULL ); - ASSERT( x!=y || i==j || duplicates_allowed, NULL ); - for( int k=0; k&) {} - void operator()(const Data<1>&, const Data<2>&) {} - friend void CheckExceptionSafety(); -}; - -#if TBB_USE_EXCEPTIONS -void CheckExceptionSafety() { - int original_count = BaseCount; - // d loops over number of copies before throw occurs - for( int d=1; d<=3; ++d ) { - // Try all combinations of throw/nothrow for f, x, and y's copy constructor. - for( int i=0; i<8; ++i ) { - { - const AnotherThreadFunc f = AnotherThreadFunc(); - if( i&1 ) f.copy_throws = d; - const Data<1> x(0); - if( i&2 ) x.copy_throws = d; - const Data<2> y(0); - if( i&4 ) y.copy_throws = d; - bool exception_caught = false; - for( int j=0; j<3; ++j ) { - try { - switch(j) { - case 0: {THREAD t(f); t.join();} break; - case 1: {THREAD t(f,x); t.join();} break; - case 2: {THREAD t(f,x,y); t.join();} break; - } - } catch(...) { - exception_caught = true; - } - ASSERT( !exception_caught||(i&((1<<(j+1))-1))!=0, NULL ); - } - } -// Intel Compiler sometimes fails to destroy all implicitly generated copies -// of an object when a copy constructor throws an exception. -// Problem was reported as Quad issue 482935. -// This #if should be removed or tightened when the bug is fixed. -#if !((_WIN32 || _WIN64) && defined(__INTEL_COMPILER)) - ASSERT( BaseCount==original_count, "object leak detected" ); -#endif - } - } -} -#endif /* TBB_USE_EXCEPTIONS */ - -#include - -void RunTests() { - - ThreadFunc t; - Data<0> d100(100), d1(1), d0(0); - THREAD::id id; - THREAD::id id0, uniq_ids[THRDS]; - - THREAD thrs[THRDS]; - THREAD thr; - THREAD thr0(t); - THREAD thr1(t, 2); - THREAD thr2(t, 1, d100); - - ASSERT( thr0.get_id() != id, NULL ); - id0 = thr0.get_id(); - tbb::move(thrs[0], thr0); - ASSERT( thr0.get_id() == id, NULL ); - ASSERT( thrs[0].get_id() == id0, NULL ); - - THREAD::native_handle_type h1 = thr1.native_handle(); - THREAD::native_handle_type h2 = thr2.native_handle(); - THREAD::id id1 = thr1.get_id(); - THREAD::id id2 = thr2.get_id(); - tbb::swap(thr1, thr2); - ASSERT( thr1.native_handle() == h2, NULL ); - ASSERT( thr2.native_handle() == h1, NULL ); - ASSERT( thr1.get_id() == id2, NULL ); - ASSERT( thr2.get_id() == id1, NULL ); - thr1.swap(thr2); - ASSERT( thr1.native_handle() == h1, NULL ); - ASSERT( thr2.native_handle() == h2, NULL ); - ASSERT( thr1.get_id() == id1, NULL ); - ASSERT( thr2.get_id() == id2, NULL ); - thr1.swap(thr2); - - tbb::move(thrs[1], thr1); - ASSERT( thr1.get_id() == id, NULL ); - - tbb::move(thrs[2], thr2); - ASSERT( thr2.get_id() == id, NULL ); - - for (int i=0; i 0, NULL); -} - -typedef bool (*id_relation)( THREAD::id, THREAD::id ); - -id_relation CheckSignatures() { - id_relation r[6] = {&tbb::operator==, - &tbb::operator!=, - &tbb::operator<, - &tbb::operator>, - &tbb::operator<=, - &tbb::operator>=}; - return r[1]; -} diff --git a/deal.II/contrib/tbb/tbb30_104oss/src/test/test_tick_count.cpp b/deal.II/contrib/tbb/tbb30_104oss/src/test/test_tick_count.cpp deleted file mode 100644 index c4360a0b09..0000000000 --- a/deal.II/contrib/tbb/tbb30_104oss/src/test/test_tick_count.cpp +++ /dev/null @@ -1,148 +0,0 @@ -/* - Copyright 2005-2010 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. -*/ - -#include "tbb/tick_count.h" -#include "harness.h" -#include - -//! Assert that two times in seconds are very close. -void AssertNear( double x, double y ) { - ASSERT( -1.0E-10 <= x-y && x-y <=1.0E-10, NULL ); -} - -//! Test arithmetic operators on tick_count::interval_t -void TestArithmetic( const tbb::tick_count& t0, const tbb::tick_count& t1, const tbb::tick_count& t2 ) { - tbb::tick_count::interval_t i= t1-t0; - tbb::tick_count::interval_t j = t2-t1; - tbb::tick_count::interval_t k = t2-t0; - AssertSameType( tbb::tick_count::interval_t(), i-j ); - AssertSameType( tbb::tick_count::interval_t(), i+j ); - ASSERT( i.seconds()>1E-9, NULL ); - ASSERT( j.seconds()>1E-9, NULL ); - ASSERT( k.seconds()>2E-9, NULL ); - AssertNear( (i+j).seconds(), k.seconds() ); - AssertNear( (k-j).seconds(), i.seconds() ); - AssertNear( ((k-j)+(j-i)).seconds(), k.seconds()-i.seconds() ); - tbb::tick_count::interval_t sum; - sum += i; - sum += j; - AssertNear( sum.seconds(), k.seconds() ); - sum -= i; - AssertNear( sum.seconds(), j.seconds() ); - sum -= j; - AssertNear( sum.seconds(), 0.0 ); -} - -//------------------------------------------------------------------------ -// Test for overhead in calls to tick_count -//------------------------------------------------------------------------ - -//! Wait for given duration. -/** The duration parameter is in units of seconds. */ -static void WaitForDuration( double duration ) { - tbb::tick_count start = tbb::tick_count::now(); - while( (tbb::tick_count::now()-start).seconds() < duration ) - continue; -} - -//! Test that average timer overhead is within acceptable limit. -/** The 'tolerance' value inside the test specifies the limit. */ -void TestSimpleDelay( int ntrial, double duration, double tolerance ) { - double total_worktime = 0; - // Iteration -1 warms up the code cache. - for( int trial=-1; trial=0 ) { - total_worktime += (t1-t0).seconds(); - } - } - // Compute average worktime and average delta - double worktime = total_worktime/ntrial; - double delta = worktime-duration; - REMARK("worktime=%g delta=%g tolerance=%g\n", worktime, delta, tolerance); - - // Check that delta is acceptable - if( delta<0 ) - REPORT("ERROR: delta=%g < 0\n",delta); - if( delta>tolerance ) - REPORT("%s: delta=%g > %g=tolerance where duration=%g\n",delta>3*tolerance?"ERROR":"Warning",delta,tolerance,duration); -} - -//------------------------------------------------------------------------ -// Test for subtracting calls to tick_count from different threads. -//------------------------------------------------------------------------ - -#include "tbb/atomic.h" -const int MAX_NTHREAD = 1000; -static tbb::atomic Counter; -static volatile bool Flag; -static tbb::tick_count tick_count_array[MAX_NTHREAD]; - -struct TickCountDifferenceBody { - void operator()( int id ) const { - if( --Counter==0 ) Flag = true; - while( !Flag ) continue; - tick_count_array[id] = tbb::tick_count::now(); - } -}; - -//! Test that two tick_count values recorded on different threads can be meaningfully subtracted. -void TestTickCountDifference( int n ) { - double tolerance = 3E-4; - for( int trial=0; trial<10; ++trial ) { - Counter = n; - Flag = false; - NativeParallelFor( n, TickCountDifferenceBody() ); - ASSERT( Counter==0, NULL ); - for( int i=0; itolerance ) { - REPORT("%s: cross-thread tick_count difference = %g > %g = tolerance\n", - diff>3*tolerance?"ERROR":"Warning",diff,tolerance); - } - } - } -} - -int TestMain () { - tbb::tick_count t0 = tbb::tick_count::now(); - TestSimpleDelay(/*ntrial=*/1000000,/*duration=*/0, /*tolerance=*/2E-6); - tbb::tick_count t1 = tbb::tick_count::now(); - TestSimpleDelay(/*ntrial=*/10, /*duration=*/0.125,/*tolerance=*/5E-6); - tbb::tick_count t2 = tbb::tick_count::now(); - TestArithmetic(t0,t1,t2); - - for( int n=MinThread; n<=MaxThread; ++n ) { - TestTickCountDifference(n); - } - return Harness::Done; -} diff --git a/deal.II/contrib/tbb/tbb30_104oss/src/test/test_yield.cpp b/deal.II/contrib/tbb/tbb30_104oss/src/test/test_yield.cpp deleted file mode 100644 index 301e485384..0000000000 --- a/deal.II/contrib/tbb/tbb30_104oss/src/test/test_yield.cpp +++ /dev/null @@ -1,73 +0,0 @@ -/* - Copyright 2005-2010 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. -*/ - -// Test that __TBB_Yield works. -// On Red Hat EL4 U1, it does not work, because sched_yield is broken. - -#include "tbb/tbb_machine.h" -#include "tbb/tick_count.h" -#include "harness.h" - -static volatile long CyclicCounter; -static volatile bool Quit; -double SingleThreadTime; - -struct RoundRobin: NoAssign { - const int number_of_threads; - RoundRobin( long p ) : number_of_threads(p) {} - void operator()( long k ) const { - tbb::tick_count t0 = tbb::tick_count::now(); - for( long i=0; i<10000; ++i ) { - // Wait for previous thread to notify us - for( int j=0; CyclicCounter!=k && !Quit; ++j ) { - __TBB_Yield(); - if( j%100==0 ) { - tbb::tick_count t1 = tbb::tick_count::now(); - if( (t1-t0).seconds()>=1.0*number_of_threads ) { - REPORT("Warning: __TBB_Yield failing to yield with %d threads (or system is heavily loaded)\n",number_of_threads); - Quit = true; - return; - } - } - } - // Notify next thread that it can run - CyclicCounter = (k+1)%number_of_threads; - } - } -}; - -int TestMain () { - for( int p=MinThread; p<=MaxThread; ++p ) { - REMARK("testing with %d threads\n", p ); - CyclicCounter = 0; - Quit = false; - NativeParallelFor( long(p), RoundRobin(p) ); - } - return Harness::Done; -} -