2009-01-18 16:59:24 +01:00
/*
ThreadWrapperJoin ( Test ) - wait blocking on termination of a thread
Copyright ( C ) Lumiera . org
2008 , Hermann Vosseler < Ichthyostega @ web . de >
This program is free software ; you can redistribute it and / or
modify it under the terms of the GNU General Public License as
published by the Free Software Foundation ; either version 2 of the
License , or ( at your option ) any later version .
This program 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 this program ; if not , write to the Free Software
Foundation , Inc . , 675 Mass Ave , Cambridge , MA 0213 9 , USA .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
# include "lib/test/run.hpp"
2009-09-24 23:02:40 +02:00
# include "lib/symbol.hpp"
2009-01-18 16:59:24 +01:00
# include "backend/thread-wrapper.hpp"
# include "lib/error.hpp"
# include "lib/sync.hpp"
# include <tr1/functional>
using std : : tr1 : : bind ;
using test : : Test ;
2009-02-01 01:01:44 +01:00
namespace backend {
namespace test {
2009-01-18 16:59:24 +01:00
/**************************************************************************
* @ test use the Lumiera backend to create some new threads , additionally
2010-01-20 18:45:48 +01:00
* passing an condition variable for waiting on thread termination .
2009-01-18 16:59:24 +01:00
* Actually this is implemented as creating and passing a JoinHandle .
2010-01-20 18:45:48 +01:00
*
2009-02-01 01:01:44 +01:00
* @ see backend : : Thread
2009-01-18 16:59:24 +01:00
* @ see threads . h
*/
class ThreadWrapperJoin_test : public Test
{
virtual void
run ( Arg )
{
simpleUse ( ) ;
wrongUse ( ) ;
}
2010-01-20 18:45:48 +01:00
volatile int aValue_ ; ///< state to be modified by the other thread
2009-01-18 16:59:24 +01:00
void
theAction ( int secretValue ) ///< to be run in a new thread...
{
2009-02-01 01:01:44 +01:00
usleep ( 100000 ) ; // pause 100ms prior to modifying
2009-01-18 16:59:24 +01:00
aValue_ = secretValue + 42 ;
}
void
simpleUse ( )
{
aValue_ = 0 ;
int mySecret = ( rand ( ) % 1000 ) - 500 ;
JoinHandle waitingHandle ;
Thread ( " test Thread joining " ,
bind ( & ThreadWrapperJoin_test : : theAction , this , mySecret ) ,
2010-01-20 18:45:48 +01:00
waitingHandle ) ;
2009-01-18 16:59:24 +01:00
// note binding and thread wrapper already destroyed
waitingHandle . join ( ) ; // blocks until theAction() is done
2010-01-20 18:45:48 +01:00
CHECK ( aValue_ = = mySecret + 42 ) ;
2009-01-18 16:59:24 +01:00
}
void
wrongUse ( )
{
JoinHandle waitingHandle ;
Thread ( " test Thread joining-1 " ,
2010-01-20 18:45:48 +01:00
bind ( & ThreadWrapperJoin_test : : theAction , this , 111 ) ) ;
2009-01-18 16:59:24 +01:00
// note we "forget" to pass the JoinHandle
2010-01-20 18:45:48 +01:00
try
{
waitingHandle . join ( ) ; // protocol error: handle wasn't passed for starting a Thread;
2009-09-04 08:53:03 +02:00
NOTREACHED ( ) ;
2009-01-18 16:59:24 +01:00
}
catch ( lumiera : : error : : Logic & logo )
{ lumiera_error ( ) ; }
Thread ( " test Thread joining-2 " ,
bind ( & ThreadWrapperJoin_test : : theAction , this , 222 ) ,
waitingHandle ) ; // this time we pass it....
# ifdef DEBUG
/////////////////////////////////////////////////////////////////////////////////////////////TODO: better way of detecting debug builds
2009-06-05 05:35:24 +02:00
# if false /////////////////////////////////////////////////////////////////////////////////////////////TODO: re-enable assertions to throw, and make this configurable
2009-01-18 16:59:24 +01:00
try
{
Thread ( " test Thread joining-3 " ,
bind ( & ThreadWrapperJoin_test : : theAction , this , 333 ) ,
waitingHandle ) ; // but then pass it again for another thread....
2009-09-04 08:53:03 +02:00
NOTREACHED ( ) ;
2009-01-18 16:59:24 +01:00
}
catch ( . . . )
{
2010-01-20 18:45:48 +01:00
CHECK ( lumiera_error ( ) = = lumiera : : error : : LUMIERA_ERROR_ASSERTION ) ;
2009-01-18 16:59:24 +01:00
}
2009-06-05 05:35:24 +02:00
# endif
2009-01-18 16:59:24 +01:00
# endif
// note: the waitingHandle goes out of scope here,
// which unblocks the second thread. The first thread wasn't blocked,
// while the third thread wasn't created at all.
2010-01-20 18:45:48 +01:00
waitingHandle . join ( ) ; // just making the above thing pass, JoinHandle thows when not joined and going out of scope
// the semantics herer need to be defined (auto joining? see thread-wrapper.hpp)
2009-01-18 16:59:24 +01:00
}
2010-01-19 18:46:32 +01:00
public :
ThreadWrapperJoin_test ( )
{ lumiera_threadpool_init ( ) ; }
~ ThreadWrapperJoin_test ( )
{ lumiera_threadpool_destroy ( ) ; }
2009-01-18 16:59:24 +01:00
} ;
/** Register this test class... */
LAUNCHER ( ThreadWrapperJoin_test , " function common " ) ;
} // namespace test
2009-02-01 01:01:44 +01:00
} // namespace backend