dlib C++ Library - threads_kernel_shared.h

// Copyright (C) 2003 Davis E. King (davis@dlib.net)
// License: Boost Software License See LICENSE.txt for the full license.
#ifndef DLIB_THREADS_KERNEl_SHARED_
#define DLIB_THREADS_KERNEl_SHARED_
// this file should be included at the bottom of one of the thread kernel headers for a 
// specific platform.
//#include "../threads.h"
#include "auto_mutex_extension.h"
#include "../binary_search_tree.h"
#include "../member_function_pointer.h"
#include "../memory_manager.h"
#include "../queue.h"
#include "../set.h"
#include "../test_for_odr_violations.h"
namespace dlib
{
// ----------------------------------------------------------------------------------------
 namespace threads_kernel_shared
 {
 void thread_starter (
 void*
 );
 class threader
 {
 /*!
 INITIAL VALUE
 - pool_count == 0 and
 - data_ready is associated with the mutex data_mutex 
 - data_empty is associated with the mutex data_mutex
 - destructed is associated with the mutex data_mutex
 - destruct == false
 - total_count == 0
 - function_pointer == 0
 - do_not_ever_destruct == false
 CONVENTION
 - data_ready is associated with the mutex data_mutex 
 - data_empty is associated with the mutex data_mutex 
 - data_ready == a signaler used signal when there is new data waiting 
 to start a thread with.
 - data_empty == a signaler used to signal when the data is now empty 
 - pool_count == the number of suspended threads in the thread pool 
 - total_count == the number of threads that are executing anywhere. i.e.
 pool_count + the ones that are currently running some user function.
 - if (function_pointer != 0) then
 - parameter == a void pointer pointing to the parameter which 
 should be used to start the next thread 
 - function_pointer == a pointer to the next function to make a 
 new thread with
 - if (the destructor is running) then
 - destruct == true
 - else
 - destruct == false
 - thread_ids is locked by the data_mutex
 - thread_ids == a set that contains the thread id for each thread spawned by this
 object.
 !*/
 public:
 threader (
 );
 
 ~threader (
 );
 void destruct_if_ready (
 );
 /*!
 ensures
 - if (there are no threads currently running and we haven't set do_not_ever_destruct) then
 - calls delete this
 - else
 - does nothing
 !*/
 bool create_new_thread (
 void (*funct)(void*),
 void* param
 );
 template <
 typename T
 >
 void unregister_thread_end_handler (
 T& obj,
 void (T::*handler)()
 )
 {
 member_function_pointer<> mfp, junk_mfp;
 mfp.set(obj,handler);
 thread_id_type junk_id;
 // find any member function pointers in the registry that point to the same
 // thing as mfp and remove them
 auto_mutex M(reg.m);
 reg.reg.reset();
 while (reg.reg.move_next())
 {
 while (reg.reg.current_element_valid() && reg.reg.element().value() == mfp)
 {
 reg.reg.remove_current_element(junk_id, junk_mfp);
 }
 }
 }
 template <
 typename T
 >
 void register_thread_end_handler (
 T& obj,
 void (T::*handler)()
 )
 {
 thread_id_type id = get_thread_id();
 member_function_pointer<> mfp;
 mfp.set(obj,handler);
 auto_mutex M(reg.m);
 reg.reg.add(id,mfp);
 }
 bool is_dlib_thread (
 thread_id_type id
 );
 private:
 friend void thread_starter (
 void*
 );
 void call_end_handlers (
 );
 /*!
 ensures
 - calls the registered end handlers for the calling thread and
 then removes them from reg.reg
 !*/
 // private data
 set<thread_id_type,memory_manager<char>::kernel_2b>::kernel_1b_c thread_ids;
 unsigned long total_count;
 void* parameter;
 void (*function_pointer)(void*);
 unsigned long pool_count;
 mutex data_mutex; // mutex to protect the above data
 signaler data_ready; // signaler to signal when there is new data
 signaler data_empty; // signaler to signal when the data is empty
 bool destruct;
 signaler destructed; // signaler to signal when a thread has ended 
 bool do_not_ever_destruct;
 struct registry_type
 {
 mutex m;
 binary_search_tree<
 thread_id_type,
 member_function_pointer<>,
 memory_manager<char>::kernel_2a
 >::kernel_2a_c reg;
 };
 // stuff for the register_thread_end_handler 
 registry_type reg;
 // restricted functions
 threader(threader&); // copy constructor
 threader& operator=(threader&); // assignement opertor
 };
 // ------------------------------------------------------------------------------------
 threader& thread_pool (
 ); 
 /*!
 ensures
 - returns a reference to the global threader object
 !*/
 // ------------------------------------------------------------------------------------
 extern bool thread_pool_has_been_destroyed;
 }
 bool is_dlib_thread (
 thread_id_type id 
 );
 bool is_dlib_thread (
 );
// ----------------------------------------------------------------------------------------
 inline bool create_new_thread (
 void (*funct)(void*),
 void* param
 )
 {
 try
 {
 // now make this thread
 return threads_kernel_shared::thread_pool().create_new_thread(funct,param);
 }
 catch (std::bad_alloc&)
 {
 return false;
 }
 }
// ----------------------------------------------------------------------------------------
 template <
 typename T
 >
 inline void register_thread_end_handler (
 T& obj,
 void (T::*handler)()
 )
 {
 DLIB_ASSERT(is_dlib_thread(), 
 "\tvoid register_thread_end_handler"
 << "\n\tYou can't register a thread end handler for a thread dlib didn't spawn."
 );
 threads_kernel_shared::thread_pool().register_thread_end_handler(obj,handler);
 }
// ----------------------------------------------------------------------------------------
 template <
 typename T
 >
 inline void unregister_thread_end_handler (
 T& obj,
 void (T::*handler)()
 )
 {
 // Check if the thread pool has been destroyed and if it has then don't do anything.
 // This bool here is always true except when the program has started to terminate and
 // the thread pool object has been destroyed. This if is here to catch other global
 // objects that have destructors that try to call unregister_thread_end_handler(). 
 // Without this check we get into trouble if the thread pool is destroyed before these
 // objects.
 if (threads_kernel_shared::thread_pool_has_been_destroyed == false)
 threads_kernel_shared::thread_pool().unregister_thread_end_handler(obj,handler);
 }
// ----------------------------------------------------------------------------------------
}
#ifdef NO_MAKEFILE
#include "threads_kernel_shared.cpp"
#endif
#endif // DLIB_THREADS_KERNEl_SHARED_

AltStyle によって変換されたページ (->オリジナル) /