// Copyright (C) 2012 Vicente Botet // // Distributed under 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) #define BOOST_THREAD_VERSION 2 #include #include #include #include // Number should be big enough to allow context switch between threads, otherwise the bug doesn't show. static int MAX_COUNTS; class ItemKeeper { public: ItemKeeper() { } void doSomething() { boost::unique_lock scoped_lock(mutex); int counts = MAX_COUNTS; while (counts--); } private: boost::mutex mutex; }; ItemKeeper itemKeeper; int MAX_ITERATIONS(5); void threadFunc(int invokerID, bool& exceptionOccurred) { try { for (int i = 0; i < MAX_ITERATIONS; i++) { std::cout << "Thread " << invokerID << ", iteration " << i << std::endl; itemKeeper.doSomething(); } } catch (...) { exceptionOccurred = true; } } int main(int argc, char* argv[]) { if (argc < 2) { MAX_COUNTS = 5000000; } else { std::string valueStr(argv[1]); bool has_only_digits = (valueStr.find_first_not_of( "0123456789" ) == std::string::npos); if (has_only_digits) { std::istringstream aStream(valueStr); aStream >> MAX_COUNTS; } else { std::cerr << "Argument should be an integer\n"; return 1; } } bool exceptionOccurred1(false); bool exceptionOccurred2(false); boost::thread thread1(threadFunc, 1, boost::ref(exceptionOccurred1)); boost::thread thread2(threadFunc, 2, boost::ref(exceptionOccurred2)); boost::posix_time::time_duration timeout = boost::posix_time::milliseconds(10000*100); bool deadlockOccured(false); //thread1.join(); //thread2.join(); if (!thread1.timed_join(timeout)) { deadlockOccured = true; thread1.interrupt(); } if (!thread2.timed_join(timeout)) { deadlockOccured = true; thread2.interrupt(); } if (deadlockOccured) { std::cout << "Deadlock occurred\n"; return 1; } if (exceptionOccurred1 || exceptionOccurred2) { std::cout << "Exception occurred\n"; return 1; } return 0; }