A lock (mutex) primitive.
#define TEST_RUNTIME 600 // seconds, needed for NighlyMemoryCheck
#include "test.h"
#include <lunchbox/atomic.h>
#include <lunchbox/clock.h>
#include <lunchbox/debug.h>
#include <lunchbox/init.h>
#include <lunchbox/lock.h>
#include <lunchbox/omp.h>
#include <lunchbox/spinLock.h>
#include <lunchbox/timedLock.h>
#include <iostream>
#define MAXTHREADS 256
#define TIME 500 // ms
bool _running = false;
{
public:
Thread() : lock( 0 ), ops( 0 ) {}
T* lock;
size_t ops;
virtual void run()
{
ops = 0;
while( LB_LIKELY( _running ))
{
lock->set();
#ifndef _MSC_VER
TEST( lock->isSet( ));
#endif
lock->unset();
++ops;
}
}
};
template< class T > void _test()
{
T* lock = new T;
lock->set();
#ifdef LUNCHBOX_USE_OPENMP
MAXTHREADS );
#else
const size_t nThreads = 16;
#endif
Thread< T > threads[MAXTHREADS];
for( size_t i = 1; i <= nThreads; i = i << 1 )
{
_running = true;
for( size_t j = 0; j < i; ++j )
{
threads[j].lock = lock;
TEST( threads[j].start( ));
}
lock->unset();
_running = false;
for( size_t j = 0; j < i; ++j )
TEST( threads[j].join( ));
TEST( !lock->isSet( ));
lock->set();
size_t ops = 0;
for( size_t j = 0; j < nThreads; ++j )
ops += threads[j].ops;
<< std::setw(12) << 3 * ops / time
<< ", " << std::setw(3) << i << std::endl;
}
delete lock;
}
int main( int argc, char **argv )
{
std::cout << " Class, ops/ms, threads" << std::endl;
_test< lunchbox::SpinLock >();
std::cout << std::endl;
_test< lunchbox::Lock >();
std::cout << std::endl;
_test< lunchbox::TimedLock >();
return EXIT_SUCCESS;
}