From: <ric...@us...> - 2011-09-29 20:36:45
|
Revision: 1118 http://loki-lib.svn.sourceforge.net/loki-lib/?rev=1118&view=rev Author: rich_sposato Date: 2011-09-29 20:36:38 +0000 (Thu, 29 Sep 2011) Log Message: ----------- Moved some code in main.cpp to separate files. Modified Paths: -------------- trunk/test/ThreadLocal/ThreadLocal.cbp trunk/test/ThreadLocal/main.cpp Added Paths: ----------- trunk/test/ThreadLocal/ThreadPool.cpp trunk/test/ThreadLocal/ThreadPool.hpp trunk/test/ThreadLocal/ThreadTests.cpp Modified: trunk/test/ThreadLocal/ThreadLocal.cbp =================================================================== --- trunk/test/ThreadLocal/ThreadLocal.cbp 2011-09-29 19:56:39 UTC (rev 1117) +++ trunk/test/ThreadLocal/ThreadLocal.cbp 2011-09-29 20:36:38 UTC (rev 1118) @@ -7,21 +7,24 @@ <Option compiler="gcc" /> <Build> <Target title="Debug_GCC"> - <Option output="obj\Debug_GCC\ThreadLocal" prefix_auto="1" extension_auto="1" /> - <Option object_output="obj\Debug_GCC\" /> + <Option output="obj/Debug_GCC/ThreadLocal" prefix_auto="1" extension_auto="1" /> + <Option object_output="obj/Debug_GCC/" /> <Option type="1" /> <Option compiler="gcc" /> <Compiler> <Add option="-Wmain" /> <Add option="-pedantic" /> - <Add option="-W" /> <Add option="-g" /> - <Add directory="..\..\include" /> + <Add option="-W -lc" /> + <Add directory="../../include" /> </Compiler> + <Linker> + <Add library="/usr/lib/libpthread.a" /> + </Linker> </Target> <Target title="Release_GCC"> - <Option output="obj\Release_GCC\ThreadLocal" prefix_auto="1" extension_auto="1" /> - <Option object_output="obj\Release_GCC\" /> + <Option output="obj/Release_GCC/ThreadLocal" prefix_auto="1" extension_auto="1" /> + <Option object_output="obj/Release_GCC/" /> <Option type="1" /> <Option compiler="gcc" /> <Compiler> @@ -41,6 +44,7 @@ <code_completion /> <debugger /> <lib_finder disable_auto="1" /> + <envvars /> </Extensions> </Project> </CodeBlocks_project_file> Added: trunk/test/ThreadLocal/ThreadPool.cpp =================================================================== --- trunk/test/ThreadLocal/ThreadPool.cpp (rev 0) +++ trunk/test/ThreadLocal/ThreadPool.cpp 2011-09-29 20:36:38 UTC (rev 1118) @@ -0,0 +1,117 @@ +//////////////////////////////////////////////////////////////////////////////// +// +// ThreadLocal test program for The Loki Library +// Copyright (c) 2009 by Richard Sposato +// The copyright on this file is protected under the terms of the MIT license. +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +// SOFTWARE. +// +//////////////////////////////////////////////////////////////////////////////// + +// ---------------------------------------------------------------------------- + +#include "ThreadPool.hpp" + +#include <sstream> +#include <iostream> + +// ---------------------------------------------------------------------------- + +Thread::Thread( CallFunction func, void * parm ) + : pthread_() + , func_( func ) + , parm_( parm ) +{ +} + +// ---------------------------------------------------------------------------- + +void Thread::AssignTask( CallFunction func, void * parm ) +{ + func_ = func; + parm_ = parm; +} + +// ---------------------------------------------------------------------------- + +int Thread::Start( void ) +{ + return LOKI_pthread_create( &pthread_, NULL, func_, parm_ ); +} + +// ---------------------------------------------------------------------------- + +int Thread::WaitForThread( void ) const +{ + return LOKI_pthread_join( pthread_ ); +} + +// ---------------------------------------------------------------------------- + +ThreadPool::ThreadPool( void ) : m_threads() +{ +} + +// ---------------------------------------------------------------------------- + +ThreadPool::~ThreadPool( void ) +{ + for ( size_t ii = 0; ii < m_threads.size(); ++ii ) + { + delete m_threads.at(ii); + } +} + +// ---------------------------------------------------------------------------- + +void ThreadPool::Create( size_t threadCount, Thread::CallFunction function ) +{ + for( size_t ii = 0; ii < threadCount; ii++ ) + { + ::std::stringstream buffer; + buffer << "Creating thread " << ii << ::std::endl; + ::std::cout << buffer.rdbuf(); + Thread * thread = new Thread( function, + reinterpret_cast< void * >( ii + 1 ) ); + m_threads.push_back( thread ); + } +} + +// ---------------------------------------------------------------------------- + +void ThreadPool::Start( void ) +{ + for ( size_t ii = 0; ii < m_threads.size(); ii++ ) + { + ::std::stringstream buffer; + buffer << "Starting thread " << ii << ::std::endl; + ::std::cout << buffer.rdbuf(); + m_threads.at( ii )->Start(); + } +} + +// ---------------------------------------------------------------------------- + +void ThreadPool::Join( void ) const +{ + for ( size_t ii = 0; ii < m_threads.size(); ii++ ) + m_threads.at( ii )->WaitForThread(); +} + +// ---------------------------------------------------------------------------- Added: trunk/test/ThreadLocal/ThreadPool.hpp =================================================================== --- trunk/test/ThreadLocal/ThreadPool.hpp (rev 0) +++ trunk/test/ThreadLocal/ThreadPool.hpp 2011-09-29 20:36:38 UTC (rev 1118) @@ -0,0 +1,119 @@ +//////////////////////////////////////////////////////////////////////////////// +// +// ThreadLocal test program for The Loki Library +// Copyright (c) 2009 by Richard Sposato +// The copyright on this file is protected under the terms of the MIT license. +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +// SOFTWARE. +// +//////////////////////////////////////////////////////////////////////////////// + + +// ---------------------------------------------------------------------------- + +#include <vector> + +#if !defined( NULL ) + #define NULL 0 +#endif + +// define nullptr even though new compilers will have this keyword just so we +// have a consistent and easy way of identifying which uses of 0 mean null. +#if !defined( nullptr ) + #define nullptr NULL +#endif + +#if defined(_WIN32) + + #include <process.h> + #include <windows.h> + + typedef unsigned int ( WINAPI * ThreadFunction_ )( void * ); + + #define LOKI_pthread_t HANDLE + + #define LOKI_pthread_create( handle, attr, func, arg ) \ + ( int )( ( *handle = ( HANDLE ) _beginthreadex ( NULL, 0, ( ThreadFunction_ )func, arg, 0, NULL ) ) == NULL ) + + #define LOKI_pthread_join( thread ) \ + ( ( WaitForSingleObject( ( thread ), INFINITE ) != WAIT_OBJECT_0 ) || !CloseHandle( thread ) ) + +#else + + #include <pthread.h> + + #define LOKI_pthread_t \ + pthread_t + #define LOKI_pthread_create(handle,attr,func,arg) \ + pthread_create(handle,attr,func,arg) + #define LOKI_pthread_join(thread) \ + pthread_join(thread, NULL) + +#endif + +// ---------------------------------------------------------------------------- + +class Thread +{ +public: + + typedef void * ( * CallFunction )( void * ); + + Thread( CallFunction func, void * parm ); + + void AssignTask( CallFunction func, void * parm ); + + int Start( void ); + + int WaitForThread( void ) const; + +private: + + LOKI_pthread_t pthread_; + + CallFunction func_; + + void * parm_; + +}; + +// ---------------------------------------------------------------------------- + +class ThreadPool +{ +public: + + ThreadPool( void ); + + ~ThreadPool( void ); + + void Create( size_t threadCount, Thread::CallFunction function ); + + void Start( void ); + + void Join( void ) const; + +private: + + typedef ::std::vector< Thread * > Threads; + + Threads m_threads; +}; + +// ---------------------------------------------------------------------------- Added: trunk/test/ThreadLocal/ThreadTests.cpp =================================================================== --- trunk/test/ThreadLocal/ThreadTests.cpp (rev 0) +++ trunk/test/ThreadLocal/ThreadTests.cpp 2011-09-29 20:36:38 UTC (rev 1118) @@ -0,0 +1,246 @@ +//////////////////////////////////////////////////////////////////////////////// +// +// ThreadLocal test program for The Loki Library +// Copyright (c) 2009 by Richard Sposato +// The copyright on this file is protected under the terms of the MIT license. +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +// SOFTWARE. +// +//////////////////////////////////////////////////////////////////////////////// + +// ---------------------------------------------------------------------------- + +#include "ThreadPool.hpp" + +#include <loki/ThreadLocal.h> + +#include <vector> +#include <sstream> +#include <iostream> + +#include <cassert> + + +// ---------------------------------------------------------------------------- + +typedef ::std::vector< unsigned int > IntVector; + +static LOKI_THREAD_LOCAL unsigned int StandaloneStaticValue = 0; + +static const unsigned int ThreadCount = 4; + +// ---------------------------------------------------------------------------- + +IntVector & GetIntVector( void ) +{ + unsigned int v = 0; + static IntVector addresses( ThreadCount, v ); + return addresses; +} + +// ---------------------------------------------------------------------------- + +void * AddToIntVector( void * p ) +{ + assert( 0 == StandaloneStaticValue ); + const unsigned int ii = reinterpret_cast< unsigned int >( p ); + assert( 0 < ii ); + assert( ii < ThreadCount + 1 ); + StandaloneStaticValue = ii; + IntVector & v = GetIntVector(); + v[ ii - 1 ] = StandaloneStaticValue; + assert( ii == StandaloneStaticValue ); + assert( v[ ii - 1 ] == StandaloneStaticValue ); + return nullptr; +} + +// ---------------------------------------------------------------------------- + +bool TestThreadLocalStaticValue( void ) +{ + assert( StandaloneStaticValue == 0 ); + { + ThreadPool pool; + pool.Create( ThreadCount, &AddToIntVector ); + pool.Start(); + pool.Join(); + } + + bool allDifferent = true; + IntVector & v = GetIntVector(); + for ( unsigned int i1 = 0; i1 < ThreadCount - 1; ++i1 ) + { + const unsigned int v1 = v[ i1 ]; + for ( unsigned int i2 = i1 + 1; i2 < ThreadCount; ++i2 ) + { + const unsigned int v2 = v[ i2 ]; + if ( v1 == v2 ) + { + allDifferent = false; + break; + } + } + if ( !allDifferent ) + break; + } + assert( StandaloneStaticValue == 0 ); + + return allDifferent; +} + +// ---------------------------------------------------------------------------- + +unsigned int & GetFunctionThreadLocalValue( void ) +{ + static LOKI_THREAD_LOCAL unsigned int FunctionStaticValue = 0; + return FunctionStaticValue; +} + +// ---------------------------------------------------------------------------- + +void * ChangeFunctionStaticValue( void * p ) +{ + unsigned int & thatValue = GetFunctionThreadLocalValue(); + assert( 0 == thatValue ); + const unsigned int ii = reinterpret_cast< unsigned int >( p ); + assert( 0 < ii ); + assert( ii < ThreadCount + 1 ); + thatValue = ii + ThreadCount; + IntVector & v = GetIntVector(); + v[ ii - 1 ] = thatValue + ThreadCount; + assert( ii + ThreadCount == thatValue ); + assert( v[ ii - 1 ] == thatValue + ThreadCount ); + return nullptr; +} + +// ---------------------------------------------------------------------------- + +bool TestThreadLocalFunctionStaticValue( void ) +{ + assert( GetFunctionThreadLocalValue() == 0 ); + + IntVector & v = GetIntVector(); + for ( unsigned int i0 = 0; i0 < v.size(); ++i0 ) + { + v[ i0 ] = 0; + } + + { + ThreadPool pool; + pool.Create( ThreadCount, &ChangeFunctionStaticValue ); + pool.Start(); + pool.Join(); + } + + bool allDifferent = true; + for ( unsigned int i1 = 0; i1 < ThreadCount - 1; ++i1 ) + { + const unsigned int v1 = v[ i1 ]; + for ( unsigned int i2 = i1 + 1; i2 < ThreadCount; ++i2 ) + { + const unsigned int v2 = v[ i2 ]; + if ( v1 == v2 ) + { + allDifferent = false; + break; + } + } + if ( !allDifferent ) + break; + } + assert( GetFunctionThreadLocalValue() == 0 ); + + return allDifferent; +} + +// ---------------------------------------------------------------------------- + +class ThreadAware +{ +public: + + static inline void SetValue( unsigned int value ) { ClassThreadLocal = value; } + + static inline unsigned int GetValue( void ) { return ClassThreadLocal; } + +private: + + static LOKI_THREAD_LOCAL unsigned int ClassThreadLocal; + +}; + +LOKI_THREAD_LOCAL unsigned int ThreadAware::ClassThreadLocal = 0; + +// ---------------------------------------------------------------------------- + +void * ChangeClassStaticValue( void * p ) +{ + assert( ThreadAware::GetValue() == 0 ); + const unsigned int ii = reinterpret_cast< unsigned int >( p ); + assert( 0 < ii ); + assert( ii < ThreadCount + 1 ); + ThreadAware::SetValue( ii + 2 * ThreadCount ); + IntVector & v = GetIntVector(); + v[ ii - 1 ] = ThreadAware::GetValue(); + assert( v[ ii - 1 ] == ThreadAware::GetValue() ); + assert( ThreadAware::GetValue() == ii + 2 * ThreadCount ); + return nullptr; +} + +// ---------------------------------------------------------------------------- + +bool TestThreadLocalClassStaticValue( void ) +{ + assert( ThreadAware::GetValue() == 0 ); + + IntVector & v = GetIntVector(); + for ( unsigned int i0 = 0; i0 < v.size(); ++i0 ) + { + v[ i0 ] = 0; + } + + { + ThreadPool pool; + pool.Create( ThreadCount, &ChangeClassStaticValue ); + pool.Start(); + pool.Join(); + } + + bool allDifferent = true; + for ( unsigned int i1 = 0; i1 < ThreadCount - 1; ++i1 ) + { + const unsigned int v1 = v[ i1 ]; + for ( unsigned int i2 = i1 + 1; i2 < ThreadCount; ++i2 ) + { + const unsigned int v2 = v[ i2 ]; + if ( v1 == v2 ) + { + allDifferent = false; + break; + } + } + if ( !allDifferent ) + break; + } + assert( ThreadAware::GetValue() == 0 ); + + return allDifferent; +} + +// ---------------------------------------------------------------------------- Modified: trunk/test/ThreadLocal/main.cpp =================================================================== --- trunk/test/ThreadLocal/main.cpp 2011-09-29 19:56:39 UTC (rev 1117) +++ trunk/test/ThreadLocal/main.cpp 2011-09-29 20:36:38 UTC (rev 1118) @@ -4,367 +4,48 @@ // Copyright (c) 2009 by Richard Sposato // The copyright on this file is protected under the terms of the MIT license. // -// Permission to use, copy, modify, distribute and sell this software for any -// purpose is hereby granted without fee, provided that the above copyright -// notice appear in all copies and that both that copyright notice and this -// permission notice appear in supporting documentation. +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: // -// The author makes no representations about the suitability of this software -// for any purpose. It is provided "as is" without express or implied warranty. +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. // +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +// SOFTWARE. +// //////////////////////////////////////////////////////////////////////////////// -// $Id$ +// ---------------------------------------------------------------------------- +#include <cstdlib> -// ---------------------------------------------------------------------------- +#include <iostream> -#include <loki/ThreadLocal.h> -#include <loki/Threads.h> - -#include <vector> -#include <sstream> -#include <iostream> - - using namespace ::std; - -#if !defined( NULL ) - #define NULL 0 -#endif - -// define nullptr even though new compilers will have this keyword just so we -// have a consistent and easy way of identifying which uses of 0 mean null. -#if !defined( nullptr ) - #define nullptr NULL -#endif - -#if defined(_WIN32) - #include <process.h> - #include <windows.h> +extern bool TestThreadLocalClassStaticValue( void ); - typedef unsigned int ( WINAPI * ThreadFunction_ )( void * ); +extern bool TestThreadLocalFunctionStaticValue( void ); - #define LOKI_pthread_t HANDLE +extern bool TestThreadLocalStaticValue( void ); - #define LOKI_pthread_create( handle, attr, func, arg ) \ - ( int )( ( *handle = ( HANDLE ) _beginthreadex ( NULL, 0, ( ThreadFunction_ )func, arg, 0, NULL ) ) == NULL ) - #define LOKI_pthread_join( thread ) \ - ( ( WaitForSingleObject( ( thread ), INFINITE ) != WAIT_OBJECT_0 ) || !CloseHandle( thread ) ) - -#else - - #define LOKI_pthread_t \ - pthread_t - #define LOKI_pthread_create(handle,attr,func,arg) \ - pthread_create(handle,attr,func,arg) - #define LOKI_pthread_join(thread) \ - pthread_join(thread, NULL) - -#endif - // ---------------------------------------------------------------------------- -class Thread +int main( int argc, const char * const argv[] ) { -public: - - typedef void * ( * CallFunction )( void * ); - - Thread( CallFunction func, void * parm ) - : pthread_() - , func_( func ) - , parm_( parm ) - { - } - - void AssignTask( CallFunction func, void * parm ) - { - func_ = func; - parm_ = parm; - } - - int Start( void ) - { - return LOKI_pthread_create( &pthread_, NULL, func_, parm_ ); - } - - int WaitForThread( void ) const - { - return LOKI_pthread_join( pthread_ ); - } - -private: - LOKI_pthread_t pthread_; - CallFunction func_; - void * parm_; -}; - -// ---------------------------------------------------------------------------- - -class ThreadPool -{ -public: - ThreadPool( void ) : m_threads() - { - } - - void Create( size_t threadCount, Thread::CallFunction function ) - { - for( size_t ii = 0; ii < threadCount; ii++ ) - { - stringstream buffer; - buffer << "Creating thread " << ii << endl; - cout << buffer.rdbuf(); - Thread * thread = new Thread( function, - reinterpret_cast< void * >( ii + 1 ) ); - m_threads.push_back( thread ); - } - } - - void Start( void ) - { - for ( size_t ii = 0; ii < m_threads.size(); ii++ ) - { - stringstream buffer; - buffer << "Starting thread " << ii << endl; - cout << buffer.rdbuf(); - m_threads.at( ii )->Start(); - } - } - - void Join( void ) const - { - for ( size_t ii = 0; ii < m_threads.size(); ii++ ) - m_threads.at( ii )->WaitForThread(); - } - - ~ThreadPool( void ) - { - for ( size_t ii = 0; ii < m_threads.size(); ii++ ) - { - delete m_threads.at(ii); - } - } - -private: - typedef std::vector< Thread * > Threads; - - Threads m_threads; -}; - -// ---------------------------------------------------------------------------- + (void)argc; + (void)argv; -typedef ::std::vector< unsigned int > IntVector; - -static LOKI_THREAD_LOCAL unsigned int StandaloneStaticValue = 0; - -static const unsigned int ThreadCount = 4; - -// ---------------------------------------------------------------------------- - -IntVector & GetIntVector( void ) -{ - unsigned int v = 0; - static IntVector addresses( ThreadCount, v ); - return addresses; -} - -// ---------------------------------------------------------------------------- - -void * AddToIntVector( void * p ) -{ - assert( 0 == StandaloneStaticValue ); - const unsigned int ii = reinterpret_cast< unsigned int >( p ); - assert( 0 < ii ); - assert( ii < ThreadCount + 1 ); - StandaloneStaticValue = ii; - IntVector & v = GetIntVector(); - v[ ii - 1 ] = StandaloneStaticValue; - assert( ii == StandaloneStaticValue ); - assert( v[ ii - 1 ] == StandaloneStaticValue ); - return nullptr; -} - -// ---------------------------------------------------------------------------- - -bool TestThreadLocalStaticValue( void ) -{ - assert( StandaloneStaticValue == 0 ); - { - ThreadPool pool; - pool.Create( ThreadCount, &AddToIntVector ); - pool.Start(); - pool.Join(); - } - - bool allDifferent = true; - IntVector & v = GetIntVector(); - for ( unsigned int i1 = 0; i1 < ThreadCount - 1; ++i1 ) - { - const unsigned int v1 = v[ i1 ]; - for ( unsigned int i2 = i1 + 1; i2 < ThreadCount; ++i2 ) - { - const unsigned int v2 = v[ i2 ]; - if ( v1 == v2 ) - { - allDifferent = false; - break; - } - } - if ( !allDifferent ) - break; - } - assert( StandaloneStaticValue == 0 ); - - return allDifferent; -} - -// ---------------------------------------------------------------------------- - -unsigned int & GetFunctionThreadLocalValue( void ) -{ - static LOKI_THREAD_LOCAL unsigned int FunctionStaticValue = 0; - return FunctionStaticValue; -} - -// ---------------------------------------------------------------------------- - -void * ChangeFunctionStaticValue( void * p ) -{ - unsigned int & thatValue = GetFunctionThreadLocalValue(); - assert( 0 == thatValue ); - const unsigned int ii = reinterpret_cast< unsigned int >( p ); - assert( 0 < ii ); - assert( ii < ThreadCount + 1 ); - thatValue = ii + ThreadCount; - IntVector & v = GetIntVector(); - v[ ii - 1 ] = thatValue + ThreadCount; - assert( ii + ThreadCount == thatValue ); - assert( v[ ii - 1 ] == thatValue + ThreadCount ); - return nullptr; -} - -// ---------------------------------------------------------------------------- - -bool TestThreadLocalFunctionStaticValue( void ) -{ - assert( GetFunctionThreadLocalValue() == 0 ); - - IntVector & v = GetIntVector(); - for ( unsigned int i0 = 0; i0 < v.size(); ++i0 ) - { - v[ i0 ] = 0; - } - - { - ThreadPool pool; - pool.Create( ThreadCount, &ChangeFunctionStaticValue ); - pool.Start(); - pool.Join(); - } - - bool allDifferent = true; - for ( unsigned int i1 = 0; i1 < ThreadCount - 1; ++i1 ) - { - const unsigned int v1 = v[ i1 ]; - for ( unsigned int i2 = i1 + 1; i2 < ThreadCount; ++i2 ) - { - const unsigned int v2 = v[ i2 ]; - if ( v1 == v2 ) - { - allDifferent = false; - break; - } - } - if ( !allDifferent ) - break; - } - assert( GetFunctionThreadLocalValue() == 0 ); - - return allDifferent; -} - -// ---------------------------------------------------------------------------- - -class ThreadAware -{ -public: - - static inline void SetValue( unsigned int value ) { ClassThreadLocal = value; } - - static inline unsigned int GetValue( void ) { return ClassThreadLocal; } - -private: - - static LOKI_THREAD_LOCAL unsigned int ClassThreadLocal; - -}; - -LOKI_THREAD_LOCAL unsigned int ThreadAware::ClassThreadLocal = 0; - -// ---------------------------------------------------------------------------- - -void * ChangeClassStaticValue( void * p ) -{ - assert( ThreadAware::GetValue() == 0 ); - const unsigned int ii = reinterpret_cast< unsigned int >( p ); - assert( 0 < ii ); - assert( ii < ThreadCount + 1 ); - ThreadAware::SetValue( ii + 2 * ThreadCount ); - IntVector & v = GetIntVector(); - v[ ii - 1 ] = ThreadAware::GetValue(); - assert( v[ ii - 1 ] == ThreadAware::GetValue() ); - assert( ThreadAware::GetValue() == ii + 2 * ThreadCount ); - return nullptr; -} - -// ---------------------------------------------------------------------------- - -bool TestThreadLocalClassStaticValue( void ) -{ - assert( ThreadAware::GetValue() == 0 ); - - IntVector & v = GetIntVector(); - for ( unsigned int i0 = 0; i0 < v.size(); ++i0 ) - { - v[ i0 ] = 0; - } - - { - ThreadPool pool; - pool.Create( ThreadCount, &ChangeClassStaticValue ); - pool.Start(); - pool.Join(); - } - - bool allDifferent = true; - for ( unsigned int i1 = 0; i1 < ThreadCount - 1; ++i1 ) - { - const unsigned int v1 = v[ i1 ]; - for ( unsigned int i2 = i1 + 1; i2 < ThreadCount; ++i2 ) - { - const unsigned int v2 = v[ i2 ]; - if ( v1 == v2 ) - { - allDifferent = false; - break; - } - } - if ( !allDifferent ) - break; - } - assert( ThreadAware::GetValue() == 0 ); - - return allDifferent; -} - -// ---------------------------------------------------------------------------- - -int main( int argc, const char * const argv[] ) -{ bool okay = true; cout << "Starting ThreadLocal tests." << endl; cout << "If any tests fail, or any assertions fail," << endl This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |