/* * * 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 * DESCRIPTION: test program for boost::static_mutex. */ #include #include #include #include #include // // we cannot use the regular Boost.Test in here: it is not thread safe // and calls to BOOST_CHECK will eventually crash on some compilers // (Borland certainly) due to race conditions inside the Boost.Test lib. // #define BOOST_CHECK(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_CHECK(++has_lock == 1); BOOST_CHECK(guard.locked()); BOOST_CHECK(guard); bool result = (--data > 0) ? true : false; BOOST_CHECK(--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_CHECK(0 == guard.locked()); BOOST_CHECK(!guard); guard.lock(); BOOST_CHECK(++has_lock == 1); BOOST_CHECK(guard.locked()); BOOST_CHECK(guard); bool result = (--data > 0) ? true : false; BOOST_CHECK(--has_lock == 0); guard.unlock(); BOOST_CHECK(0 == guard.locked()); BOOST_CHECK(!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_CHECK(++has_lock == 1); BOOST_CHECK(guard.locked()); BOOST_CHECK(guard); bool result = (--data > 0) ? true : false; BOOST_CHECK(--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 > threads; for(int i = 0; i < 2; ++i) { try{ threads.push_back(boost::shared_ptr(new boost::thread(&thread1_proc))); } catch(const std::exception& e) { std::cerr << "Thread creation failed with message: " << e.what() << "" << std::endl; } } for(int i = 0; i < 2; ++i) { try{ threads.push_back(boost::shared_ptr(new boost::thread(&thread2_proc))); } catch(const std::exception& e) { std::cerr << "Thread creation failed with message: " << e.what() << "" << std::endl; } } for(int i = 0; i < 2; ++i) { try{ threads.push_back(boost::shared_ptr(new boost::thread(&thread3_proc))); } catch(const std::exception& e) { std::cerr << "Thread creation failed with message: " << e.what() << "" << std::endl; } } std::list >::const_iterator a(threads.begin()), b(threads.end()); while(a != b) { (*a)->join(); ++a; } return total_failures; }