blob: b31eefac3e0a61209b0524ae0a08d911340acd89 [file] [log] [blame]
/*
*
* Copyright (c) 2004
* John Maddock
*
* Use, modification and distribution are subject to the
* Boost Software License, Version 1.0. (See accompanying file
* LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
*
*/
/*
* LOCATION: see http://www.boost.org for most recent version.
* FILE static_mutex_test.cpp
* VERSION see <boost/version.hpp>
* DESCRIPTION: test program for boost::static_mutex.
*/
#include <iostream>
#include <boost/regex/pending/static_mutex.hpp>
#include <boost/thread/thread.hpp>
#include <boost/timer.hpp>
//
// we cannot use the regular Boost.Test in here: it is not thread safe
// and calls to BOOST_TEST will eventually crash on some compilers
// (Borland certainly) due to race conditions inside the Boost.Test lib.
//
#define BOOST_TEST(pred) if(!(pred)) failed_test(__FILE__, __LINE__, BOOST_STRINGIZE(pred));
int total_failures = 0;
void failed_test(const char* file, int line, const char* pred)
{
static boost::static_mutex mut = BOOST_STATIC_MUTEX_INIT ;
boost::static_mutex::scoped_lock guard(mut);
++total_failures;
std::cout << "Failed test in \"" << file << "\" at line " << line << ": " << pred << std::endl;
}
void print_cycles(int c)
{
static boost::static_mutex mut = BOOST_STATIC_MUTEX_INIT ;
boost::static_mutex::scoped_lock guard(mut);
std::cout << "Thread exited after " << c << " cycles." << std::endl;
}
bool sufficient_time()
{
// return true if enough time has passed since the tests began:
static boost::static_mutex mut = BOOST_STATIC_MUTEX_INIT ;
boost::static_mutex::scoped_lock guard(mut);
static boost::timer t;
// is 10 seconds enough?
return t.elapsed() >= 10.0;
}
// define three trivial test proceedures:
bool t1()
{
static boost::static_mutex mut = BOOST_STATIC_MUTEX_INIT ;
static int has_lock = 0;
static int data = 10000;
boost::static_mutex::scoped_lock guard(mut);
BOOST_TEST(++has_lock == 1);
BOOST_TEST(guard.locked());
BOOST_TEST(guard);
bool result = (--data > 0) ? true : false;
BOOST_TEST(--has_lock == 0);
return result;
}
bool t2()
{
static boost::static_mutex mut = BOOST_STATIC_MUTEX_INIT ;
static int has_lock = 0;
static int data = 10000;
boost::static_mutex::scoped_lock guard(mut, false);
BOOST_TEST(0 == guard.locked());
BOOST_TEST(!guard);
guard.lock();
BOOST_TEST(++has_lock == 1);
BOOST_TEST(guard.locked());
BOOST_TEST(guard);
bool result = (--data > 0) ? true : false;
BOOST_TEST(--has_lock == 0);
guard.unlock();
BOOST_TEST(0 == guard.locked());
BOOST_TEST(!guard);
return result;
}
bool t3()
{
static boost::static_mutex mut = BOOST_STATIC_MUTEX_INIT ;
static int has_lock = 0;
static int data = 10000;
boost::static_mutex::scoped_lock guard(mut);
BOOST_TEST(++has_lock == 1);
BOOST_TEST(guard.locked());
BOOST_TEST(guard);
bool result = (--data > 0) ? true : false;
BOOST_TEST(--has_lock == 0);
return result;
}
// define their thread procs:
void thread1_proc()
{
int cycles = 0;
while(!sufficient_time())
{
t1();
t2();
++cycles;
}
print_cycles(cycles);
}
void thread2_proc()
{
int cycles = 0;
while(!sufficient_time())
{
t2();
t3();
++cycles;
}
print_cycles(cycles);
}
void thread3_proc()
{
int cycles = 0;
while(!sufficient_time())
{
t1();
t3();
++cycles;
}
print_cycles(cycles);
}
// make sure that at least one of our test proceedures
// is called during program startup:
struct startup1
{
startup1()
{
t1();
}
~startup1()
{
t1();
}
};
startup1 up1;
int main()
{
(void)up1;
std::list<boost::shared_ptr<boost::thread> > threads;
for(int i = 0; i < 2; ++i)
{
try{
threads.push_back(boost::shared_ptr<boost::thread>(new boost::thread(&thread1_proc)));
}
catch(const std::exception& e)
{
std::cerr << "<note>Thread creation failed with message: " << e.what() << "</note>" << std::endl;
}
}
for(int i = 0; i < 2; ++i)
{
try{
threads.push_back(boost::shared_ptr<boost::thread>(new boost::thread(&thread2_proc)));
}
catch(const std::exception& e)
{
std::cerr << "<note>Thread creation failed with message: " << e.what() << "</note>" << std::endl;
}
}
for(int i = 0; i < 2; ++i)
{
try{
threads.push_back(boost::shared_ptr<boost::thread>(new boost::thread(&thread3_proc)));
}
catch(const std::exception& e)
{
std::cerr << "<note>Thread creation failed with message: " << e.what() << "</note>" << std::endl;
}
}
std::list<boost::shared_ptr<boost::thread> >::const_iterator a(threads.begin()), b(threads.end());
while(a != b)
{
(*a)->join();
++a;
}
return total_failures;
}