// Copyright (C) 2007 Davis E. King (davis@dlib.net) // License: Boost Software License See LICENSE.txt for the full license. #ifndef DLIB_THREADED_OBJECT_EXTENSIOn_CPP #define DLIB_THREADED_OBJECT_EXTENSIOn_CPP #include "threaded_object_extension.h" #include "create_new_thread_extension.h" namespace dlib { // ---------------------------------------------------------------------------------------- threaded_object:: threaded_object ( ): s(m_), id1(0), is_running_(false), is_alive_(false), should_stop_(false), id_valid(false) { } // ---------------------------------------------------------------------------------------- threaded_object:: ~threaded_object ( ) { try { DLIB_ASSERT(is_alive() == false, "\tthreaded_object::~threaded_object()" << "\n\tYou have let a threaded object destruct itself before terminating its thread" << "\n\tthis: " << this ); } catch (std::exception& e) { std::cerr << e.what() << std::endl; assert(false); abort(); } } // ---------------------------------------------------------------------------------------- bool threaded_object:: is_running ( ) const { auto_mutex M(m_); DLIB_ASSERT(id1 != get_thread_id() || id_valid == false, "\tbool threaded_object::is_running()" << "\n\tYou can NOT call this function from the thread that executes threaded_object::thread" << "\n\tthis: " << this ); return is_running_; } // ---------------------------------------------------------------------------------------- bool threaded_object:: is_alive ( ) const { auto_mutex M(m_); DLIB_ASSERT(id1 != get_thread_id() || id_valid == false, "\tbool threaded_object::is_alive()" << "\n\tYou can NOT call this function from the thread that executes threaded_object::thread" << "\n\tthis: " << this ); return is_alive_; } // ---------------------------------------------------------------------------------------- void threaded_object:: wait ( ) const { auto_mutex M(m_); DLIB_ASSERT(id1 != get_thread_id() || id_valid == false, "\tvoid threaded_object::wait()" << "\n\tYou can NOT call this function from the thread that executes threaded_object::thread" << "\n\tthis: " << this ); while (is_alive_) s.wait(); } // ---------------------------------------------------------------------------------------- void threaded_object:: start ( ) { auto_mutex M(m_); DLIB_ASSERT(id1 != get_thread_id() || id_valid == false, "\tvoid threaded_object::start()" << "\n\tYou can NOT call this function from the thread that executes threaded_object::thread" << "\n\tthis: " << this ); if (is_alive_ == false) { if (create_new_thread<threaded_object,&threaded_object::thread_helper>(*this) == false) { is_running_ = false; throw thread_error(); } } is_alive_ = true; is_running_ = true; should_stop_ = false; s.broadcast(); } // ---------------------------------------------------------------------------------------- void threaded_object:: restart ( ) { auto_mutex M(m_); DLIB_ASSERT(id1 != get_thread_id() || id_valid == false, "\tvoid threaded_object::restart()" << "\n\tYou can NOT call this function from the thread that executes threaded_object::thread" << "\n\tthis: " << this ); if (is_alive_ == false) { if (create_new_thread<threaded_object,&threaded_object::thread_helper>(*this) == false) { is_running_ = false; throw thread_error(); } should_respawn_ = false; } else { should_respawn_ = true; } is_alive_ = true; is_running_ = true; should_stop_ = false; s.broadcast(); } // ---------------------------------------------------------------------------------------- void threaded_object:: set_respawn ( ) { auto_mutex M(m_); DLIB_ASSERT(id1 != get_thread_id() || id_valid == false, "\tvoid threaded_object::set_respawn()" << "\n\tYou can NOT call this function from the thread that executes threaded_object::thread" << "\n\tthis: " << this ); should_respawn_ = true; } // ---------------------------------------------------------------------------------------- bool threaded_object:: should_respawn ( ) const { auto_mutex M(m_); DLIB_ASSERT(id1 != get_thread_id() || id_valid == false, "\tbool threaded_object::should_respawn()" << "\n\tYou can NOT call this function from the thread that executes threaded_object::thread" << "\n\tthis: " << this ); return should_respawn_; } // ---------------------------------------------------------------------------------------- void threaded_object:: pause ( ) { auto_mutex M(m_); DLIB_ASSERT(id1 != get_thread_id() || id_valid == false, "\tvoid threaded_object::pause()" << "\n\tYou can NOT call this function from the thread that executes threaded_object::thread" << "\n\tthis: " << this ); is_running_ = false; } // ---------------------------------------------------------------------------------------- void threaded_object:: stop ( ) { auto_mutex M(m_); DLIB_ASSERT(id1 != get_thread_id() || id_valid == false, "\tvoid threaded_object::stop()" << "\n\tYou can NOT call this function from the thread that executes threaded_object::thread" << "\n\tthis: " << this ); should_stop_ = true; is_running_ = false; should_respawn_ = false; s.broadcast(); } // ---------------------------------------------------------------------------------------- bool threaded_object:: should_stop ( ) const { auto_mutex M(m_); DLIB_ASSERT(is_alive_ && id1 == get_thread_id() && id_valid == true, "\tbool threaded_object::should_stop()" << "\n\tYou can only call this function from the thread that executes threaded_object::thread" << "\n\tthis: " << this ); while (is_running_ == false && should_stop_ == false) s.wait(); return should_stop_; } // ---------------------------------------------------------------------------------------- void threaded_object:: thread_helper( ) { #ifdef ENABLE_ASSERTS id1 = get_thread_id(); id_valid = true; #endif while (true) { m_.lock(); should_respawn_ = false; m_.unlock(); thread(); auto_mutex M(m_); if (should_respawn_) continue; #ifdef ENABLE_ASSERTS id_valid = false; #endif is_alive_ = false; is_running_ = false; should_stop_ = false; s.broadcast(); return; } } // ---------------------------------------------------------------------------------------- } #endif // DLIB_THREADED_OBJECT_EXTENSIOn_CPP