// Copyright (C) 2007 Davis E. King (davis@dlib.net) // License: Boost Software License See LICENSE.txt for the full license. #ifndef DLIB_MULTITHREADED_OBJECT_EXTENSIOn_ #define DLIB_MULTITHREADED_OBJECT_EXTENSIOn_ #include "multithreaded_object_extension_abstract.h" #include "threads_kernel.h" #include "auto_mutex_extension.h" #include "rmutex_extension.h" #include "rsignaler_extension.h" #include "../algs.h" #include "../assert.h" #include "../map.h" #include "../member_function_pointer.h" namespace dlib { // ---------------------------------------------------------------------------------------- class multithreaded_object { /*! INITIAL VALUE - is_running_ == false - should_stop_ == false - thread_ids.size() == 0 - dead_threads.size() == 0 - threads_started == 0 CONVENTION - number_of_threads_registered() == thread_ids.size() + dead_threads.size() - number_of_threads_alive() == threads_started - is_running() == is_running_ - should_stop() == should_stop_ - thread_ids == a map of current thread ids to the member function pointers that that thread runs. - threads_started == the number of threads that have been spawned to run thread_helper but haven't ended yet. - dead_threads == a queue that contains all the member function pointers for threads that are currently registered but not running - m_ == the mutex used to protect all our variables - s == the signaler for m_ !*/ public: multithreaded_object ( ); virtual ~multithreaded_object ( ) = 0; void clear ( ); bool is_running ( ) const; unsigned long number_of_threads_alive ( ) const; unsigned long number_of_threads_registered ( ) const; void wait ( ) const; void start ( ); void pause ( ); void stop ( ); protected: bool should_stop ( ) const; template < typename T > void register_thread ( T& object, void (T::*thread)() ) { auto_mutex M(m_); try { mfp mf; mf.set(object,thread); dead_threads.enqueue(mf); if (is_running_) start(); } catch (...) { is_running_ = false; should_stop_ = true; s.broadcast(); throw; } } private: class raii_thread_helper { public: raii_thread_helper(multithreaded_object& self_, thread_id_type id_); ~raii_thread_helper(); multithreaded_object& self; thread_id_type id; }; void thread_helper( ); typedef member_function_pointer<> mfp; rmutex m_; rsignaler s; map<thread_id_type,mfp,memory_manager<char>::kernel_2a>::kernel_1a thread_ids; queue<mfp,memory_manager<char>::kernel_2a>::kernel_1a dead_threads; bool is_running_; bool should_stop_; unsigned long threads_started; // restricted functions multithreaded_object(multithreaded_object&); // copy constructor multithreaded_object& operator=(multithreaded_object&); // assignment operator }; // ---------------------------------------------------------------------------------------- } #ifdef NO_MAKEFILE #include "multithreaded_object_extension.cpp" #endif #endif // DLIB_MULTITHREADED_OBJECT_EXTENSIOn_