// Copyright (C) 2007 Davis E. King (davis@dlib.net) // License: Boost Software License See LICENSE.txt for the full license. #include <string> #include <sstream> #include <dlib/threads.h> #include "tester.h" namespace { using namespace test; using namespace std; using namespace dlib; logger dlog("test.multithreaded_object"); dlib::mutex cm; int count; class test1 : multithreaded_object { public: test1 () { DLIB_TEST(number_of_threads_registered() == 0); DLIB_TEST(number_of_threads_alive() == 0); DLIB_TEST(is_running() == false); clear(); DLIB_TEST(number_of_threads_registered() == 0); DLIB_TEST(number_of_threads_alive() == 0); DLIB_TEST(is_running() == false); } ~test1 () { DLIB_TEST(number_of_threads_registered() == 0); DLIB_TEST(number_of_threads_alive() == 0); DLIB_TEST(is_running() == false); stop(); DLIB_TEST(number_of_threads_registered() == 0); DLIB_TEST(number_of_threads_alive() == 0); DLIB_TEST(is_running() == false); wait(); DLIB_TEST(number_of_threads_registered() == 0); DLIB_TEST(number_of_threads_alive() == 0); DLIB_TEST(is_running() == false); } private: }; class test2 : private multithreaded_object { public: test2() { DLIB_TEST(number_of_threads_registered() == 0); DLIB_TEST(number_of_threads_alive() == 0); DLIB_TEST(is_running() == false); register_thread(*this,&test2::thread); DLIB_TEST(number_of_threads_registered() == 1); DLIB_TEST(number_of_threads_alive() == 0); DLIB_TEST(is_running() == false); clear(); DLIB_TEST(number_of_threads_registered() == 0); DLIB_TEST(number_of_threads_alive() == 0); DLIB_TEST(is_running() == false); register_thread(*this,&test2::thread); DLIB_TEST(number_of_threads_registered() == 1); DLIB_TEST(number_of_threads_alive() == 0); DLIB_TEST(is_running() == false); } ~test2() { DLIB_TEST(number_of_threads_registered() == 1); DLIB_TEST(number_of_threads_alive() == 0); DLIB_TEST(is_running() == false); stop(); DLIB_TEST(number_of_threads_registered() == 1); DLIB_TEST(number_of_threads_alive() == 0); DLIB_TEST(is_running() == false); wait(); DLIB_TEST(number_of_threads_registered() == 1); DLIB_TEST(number_of_threads_alive() == 0); DLIB_TEST(is_running() == false); } private: void thread() { auto_mutex M(cm); ++count; } }; class test3_c1 : private multithreaded_object { public: test3_c1() { DLIB_TEST(number_of_threads_registered() == 0); DLIB_TEST(number_of_threads_alive() == 0); DLIB_TEST(is_running() == false); register_thread(*this,&test3_c1::thread); DLIB_TEST(number_of_threads_registered() == 1); DLIB_TEST(number_of_threads_alive() == 0); DLIB_TEST(is_running() == false); start(); DLIB_TEST(number_of_threads_registered() == 1); DLIB_TEST(is_running() == true); } ~test3_c1() { DLIB_TEST(number_of_threads_registered() == 1); stop(); DLIB_TEST(is_running() == false); DLIB_TEST(number_of_threads_registered() == 1); wait(); DLIB_TEST(number_of_threads_registered() == 1); DLIB_TEST(number_of_threads_alive() == 0); DLIB_TEST(is_running() == false); } private: void thread() { cm.lock(); ++count; cm.unlock(); // wait until we are supposed to stop while (!should_stop()) dlib::sleep(1); } }; class test4_c2 : private multithreaded_object { public: test4_c2() { DLIB_TEST(number_of_threads_registered() == 0); DLIB_TEST(number_of_threads_alive() == 0); DLIB_TEST(is_running() == false); register_thread(*this,&test4_c2::thread); DLIB_TEST(number_of_threads_registered() == 1); DLIB_TEST(number_of_threads_alive() == 0); DLIB_TEST(is_running() == false); start(); DLIB_TEST(number_of_threads_registered() == 1); DLIB_TEST(number_of_threads_alive() == 1); DLIB_TEST(is_running() == true); register_thread(*this,&test4_c2::thread); DLIB_TEST(number_of_threads_registered() == 2); DLIB_TEST(number_of_threads_alive() == 2); DLIB_TEST(is_running() == true); start(); DLIB_TEST(number_of_threads_registered() == 2); DLIB_TEST(number_of_threads_alive() == 2); DLIB_TEST(is_running() == true); start(); DLIB_TEST(number_of_threads_registered() == 2); DLIB_TEST(number_of_threads_alive() == 2); DLIB_TEST(is_running() == true); start(); DLIB_TEST(number_of_threads_registered() == 2); DLIB_TEST(number_of_threads_alive() == 2); DLIB_TEST(is_running() == true); start(); DLIB_TEST(number_of_threads_registered() == 2); DLIB_TEST(number_of_threads_alive() == 2); DLIB_TEST(is_running() == true); pause(); DLIB_TEST(number_of_threads_registered() == 2); DLIB_TEST(number_of_threads_alive() == 2); DLIB_TEST(is_running() == false); } ~test4_c2() { try { DLIB_TEST(number_of_threads_registered() == 2); DLIB_TEST(number_of_threads_alive() == 2); DLIB_TEST_MSG(is_running() == false,"is_running(): " << is_running()); stop(); DLIB_TEST(number_of_threads_registered() == 2); DLIB_TEST(is_running() == false); wait(); DLIB_TEST(number_of_threads_registered() == 2); DLIB_TEST(number_of_threads_alive() == 0); DLIB_TEST(is_running() == false); } catch(std::exception& e) { std::cerr << e.what() << std::endl; exit(1); } } private: void thread() { auto_mutex M(cm); ++count; while (!should_stop()) dlib::sleep(10); } }; class test5 : private multithreaded_object { public: test5() { register_thread(*this,&test5::thread1); register_thread(*this,&test5::thread2); register_thread(*this,&test5::thread3); register_thread(*this,&test5::thread3); start(); } ~test5() { stop(); wait(); } private: void thread1() { while (!should_stop()) dlib::sleep(10); } void thread2() { while (!should_stop()) dlib::sleep(10); } void thread3() { while (!should_stop()) dlib::sleep(10); } }; void multithreaded_object_test ( ) /*! ensures - runs tests on dlib::multithreaded_object for compliance with the specs !*/ { count = 0; for (int i = 0; i < 5; ++i) { { test1 a1; test2 a2; test3_c1 a3; test4_c2 a4; test5 a5; } DLIB_TEST(count == (i+1)*3); print_spinner(); } count = 0; for (int i = 0; i < 5; ++i) { { test1 a1; test2 a2; test3_c1 a3; test4_c2 a4; test5 a5; dlib::sleep(50); } DLIB_TEST(count == (i+1)*3); print_spinner(); } } class multithreaded_object_tester : public tester { public: multithreaded_object_tester ( ) : tester ("test_multithreaded_object", "Runs tests on the multithreaded_object component.") {} void perform_test ( ) { multithreaded_object_test(); } } a; }