diff options
Diffstat (limited to 'ml/dlib/dlib/threads/thread_pool_extension.h')
-rw-r--r-- | ml/dlib/dlib/threads/thread_pool_extension.h | 1392 |
1 files changed, 0 insertions, 1392 deletions
diff --git a/ml/dlib/dlib/threads/thread_pool_extension.h b/ml/dlib/dlib/threads/thread_pool_extension.h deleted file mode 100644 index bc2e1782c..000000000 --- a/ml/dlib/dlib/threads/thread_pool_extension.h +++ /dev/null @@ -1,1392 +0,0 @@ -// Copyright (C) 2008 Davis E. King (davis@dlib.net) -// License: Boost Software License See LICENSE.txt for the full license. -#ifndef DLIB_THREAD_POOl_Hh_ -#define DLIB_THREAD_POOl_Hh_ - -#include <exception> -#include <memory> -#include <thread> - -#include "thread_pool_extension_abstract.h" -#include "multithreaded_object_extension.h" -#include "../member_function_pointer.h" -#include "../bound_function_pointer.h" -#include "threads_kernel.h" -#include "auto_mutex_extension.h" -#include "../uintn.h" -#include "../array.h" - -namespace dlib -{ - -// ---------------------------------------------------------------------------------------- - - class thread_pool_implementation; - - template < - typename T - > - class future - { - /*! - INITIAL VALUE - - task_id == 0 - - tp.get() == 0 - - CONVENTION - - is_ready() == (tp.get() == 0) - - get() == var - - - if (tp.get() != 0) - - tp == a pointer to the thread_pool_implementation that is using this future object - - task_id == the task id of the task in the thread pool tp that is using - this future object. - !*/ - public: - - future ( - ) : task_id(0) {} - - future ( - const T& item - ) : task_id(0), var(item) {} - - future ( - const future& item - ) :task_id(0), var(item.get()) {} - - ~future ( - ) { wait(); } - - future& operator=( - const T& item - ) { get() = item; return *this; } - - future& operator=( - const future& item - ) { get() = item.get(); return *this; } - - operator T& ( - ) { return get(); } - - operator const T& ( - ) const { return get(); } - - T& get ( - ) { wait(); return var; } - - const T& get ( - ) const { wait(); return var; } - - bool is_ready ( - ) const { return tp.get() == 0; } - - private: - - friend class thread_pool; - - inline void wait () const; - - mutable uint64 task_id; - mutable std::shared_ptr<thread_pool_implementation> tp; - - T var; - }; - -// ---------------------------------------------------------------------------------------- - - template <typename T> - inline void swap ( - future<T>& a, - future<T>& b - ) { dlib::exchange(a.get(), b.get()); } - // Note that dlib::exchange() just calls std::swap. I'm only using it because - // this works around some bugs in certain compilers. - -// ---------------------------------------------------------------------------------------- - - template <typename T> bool operator== (const future<T>& a, const future<T>& b) { return a.get() == b.get(); } - template <typename T> bool operator!= (const future<T>& a, const future<T>& b) { return a.get() != b.get(); } - template <typename T> bool operator<= (const future<T>& a, const future<T>& b) { return a.get() <= b.get(); } - template <typename T> bool operator>= (const future<T>& a, const future<T>& b) { return a.get() >= b.get(); } - template <typename T> bool operator< (const future<T>& a, const future<T>& b) { return a.get() < b.get(); } - template <typename T> bool operator> (const future<T>& a, const future<T>& b) { return a.get() > b.get(); } - - template <typename T> bool operator== (const future<T>& a, const T& b) { return a.get() == b; } - template <typename T> bool operator== (const T& a, const future<T>& b) { return a == b.get(); } - template <typename T> bool operator!= (const future<T>& a, const T& b) { return a.get() != b; } - template <typename T> bool operator!= (const T& a, const future<T>& b) { return a != b.get(); } - template <typename T> bool operator<= (const future<T>& a, const T& b) { return a.get() <= b; } - template <typename T> bool operator<= (const T& a, const future<T>& b) { return a <= b.get(); } - template <typename T> bool operator>= (const future<T>& a, const T& b) { return a.get() >= b; } - template <typename T> bool operator>= (const T& a, const future<T>& b) { return a >= b.get(); } - template <typename T> bool operator< (const future<T>& a, const T& b) { return a.get() < b; } - template <typename T> bool operator< (const T& a, const future<T>& b) { return a < b.get(); } - template <typename T> bool operator> (const future<T>& a, const T& b) { return a.get() > b; } - template <typename T> bool operator> (const T& a, const future<T>& b) { return a > b.get(); } - -// ---------------------------------------------------------------------------------------- - - class thread_pool_implementation - { - /*! - CONVENTION - - num_threads_in_pool() == tasks.size() - - if (the destructor has been called) then - - we_are_destructing == true - - else - - we_are_destructing == false - - - is_task_thread() == is_worker_thread(get_thread_id()) - - - m == the mutex used to protect everything in this object - - worker_thread_ids == an array that contains the thread ids for - all the threads in the thread pool - !*/ - typedef bound_function_pointer::kernel_1a_c bfp_type; - - friend class thread_pool; - explicit thread_pool_implementation ( - unsigned long num_threads - ); - - public: - ~thread_pool_implementation( - ); - - void wait_for_task ( - uint64 task_id - ) const; - - unsigned long num_threads_in_pool ( - ) const; - - void wait_for_all_tasks ( - ) const; - - bool is_task_thread ( - ) const; - - template <typename T> - uint64 add_task ( - T& obj, - void (T::*funct)() - ) - { - auto_mutex M(m); - const thread_id_type my_thread_id = get_thread_id(); - - // find a thread that isn't doing anything - long idx = find_empty_task_slot(); - if (idx == -1 && is_worker_thread(my_thread_id)) - { - // this function is being called from within a worker thread and there - // aren't any other worker threads free so just perform the task right - // here - - M.unlock(); - (obj.*funct)(); - - // return a task id that is both non-zero and also one - // that is never normally returned. This way calls - // to wait_for_task() will never block given this id. - return 1; - } - - // wait until there is a thread that isn't doing anything - while (idx == -1) - { - task_done_signaler.wait(); - idx = find_empty_task_slot(); - } - - tasks[idx].thread_id = my_thread_id; - tasks[idx].task_id = make_next_task_id(idx); - tasks[idx].mfp0.set(obj,funct); - - task_ready_signaler.signal(); - - return tasks[idx].task_id; - } - - template <typename T> - uint64 add_task ( - T& obj, - void (T::*funct)(long), - long arg1 - ) - { - auto_mutex M(m); - const thread_id_type my_thread_id = get_thread_id(); - - // find a thread that isn't doing anything - long idx = find_empty_task_slot(); - if (idx == -1 && is_worker_thread(my_thread_id)) - { - // this function is being called from within a worker thread and there - // aren't any other worker threads free so just perform the task right - // here - - M.unlock(); - (obj.*funct)(arg1); - - // return a task id that is both non-zero and also one - // that is never normally returned. This way calls - // to wait_for_task() will never block given this id. - return 1; - } - - // wait until there is a thread that isn't doing anything - while (idx == -1) - { - task_done_signaler.wait(); - idx = find_empty_task_slot(); - } - - tasks[idx].thread_id = my_thread_id; - tasks[idx].task_id = make_next_task_id(idx); - tasks[idx].mfp1.set(obj,funct); - tasks[idx].arg1 = arg1; - - task_ready_signaler.signal(); - - return tasks[idx].task_id; - } - - template <typename T> - uint64 add_task ( - T& obj, - void (T::*funct)(long,long), - long arg1, - long arg2 - ) - { - auto_mutex M(m); - const thread_id_type my_thread_id = get_thread_id(); - - // find a thread that isn't doing anything - long idx = find_empty_task_slot(); - if (idx == -1 && is_worker_thread(my_thread_id)) - { - // this function is being called from within a worker thread and there - // aren't any other worker threads free so just perform the task right - // here - - M.unlock(); - (obj.*funct)(arg1, arg2); - - // return a task id that is both non-zero and also one - // that is never normally returned. This way calls - // to wait_for_task() will never block given this id. - return 1; - } - - // wait until there is a thread that isn't doing anything - while (idx == -1) - { - task_done_signaler.wait(); - idx = find_empty_task_slot(); - } - - tasks[idx].thread_id = my_thread_id; - tasks[idx].task_id = make_next_task_id(idx); - tasks[idx].mfp2.set(obj,funct); - tasks[idx].arg1 = arg1; - tasks[idx].arg2 = arg2; - - task_ready_signaler.signal(); - - return tasks[idx].task_id; - } - - struct function_object_copy - { - virtual ~function_object_copy(){} - }; - - template <typename T> - struct function_object_copy_instance : function_object_copy - { - function_object_copy_instance(const T& item_) : item(item_) {} - T item; - virtual ~function_object_copy_instance(){} - }; - - uint64 add_task_internal ( - const bfp_type& bfp, - std::shared_ptr<function_object_copy>& item - ); - /*! - ensures - - adds a task to call the given bfp object. - - swaps item into the internal task object which will have a lifetime - at least as long as the running task. - - returns the task id for this new task - !*/ - - uint64 add_task_internal ( - const bfp_type& bfp - ) { std::shared_ptr<function_object_copy> temp; return add_task_internal(bfp, temp); } - /*! - ensures - - adds a task to call the given bfp object. - - returns the task id for this new task - !*/ - - void shutdown_pool ( - ); - /*! - ensures - - causes all threads to terminate and blocks the - caller until this happens. - !*/ - - private: - - bool is_worker_thread ( - const thread_id_type id - ) const; - /*! - requires - - m is locked - ensures - - if (thread with given id is one of the thread pool's worker threads or num_threads_in_pool() == 0) then - - returns true - - else - - returns false - !*/ - - void thread ( - ); - /*! - this is the function that executes the threads in the thread pool - !*/ - - long find_empty_task_slot ( - ) const; - /*! - requires - - m is locked - ensures - - if (there is currently a empty task slot) then - - returns the index of that task slot in tasks - - there is a task slot - - else - - returns -1 - !*/ - - long find_ready_task ( - ) const; - /*! - requires - - m is locked - ensures - - if (there is currently a task to do) then - - returns the index of that task in tasks - - else - - returns -1 - !*/ - - uint64 make_next_task_id ( - long idx - ); - /*! - requires - - m is locked - - 0 <= idx < tasks.size() - ensures - - returns the next index to be used for tasks that are placed in - tasks[idx] - !*/ - - unsigned long task_id_to_index ( - uint64 id - ) const; - /*! - requires - - m is locked - - num_threads_in_pool() != 0 - ensures - - returns the index in tasks corresponding to the given id - !*/ - - struct task_state_type - { - task_state_type() : is_being_processed(false), task_id(0), next_task_id(2), arg1(0), arg2(0), eptr(nullptr) {} - - bool is_ready () const - /*! - ensures - - if (is_empty() == false && no thread is currently processing this task) then - - returns true - - else - - returns false - !*/ - { - return !is_being_processed && !is_empty(); - } - - bool is_empty () const - /*! - ensures - - if (this task state is empty. i.e. it doesn't contain a task to be processed) then - - returns true - - else - - returns false - !*/ - { - return task_id == 0; - } - - bool is_being_processed; // true when a thread is working on this task - uint64 task_id; // the id of this task. 0 means this task is empty - thread_id_type thread_id; // the id of the thread that requested this task - - uint64 next_task_id; - - long arg1; - long arg2; - - member_function_pointer<> mfp0; - member_function_pointer<long> mfp1; - member_function_pointer<long,long> mfp2; - bfp_type bfp; - - std::shared_ptr<function_object_copy> function_copy; - mutable std::exception_ptr eptr; // non-null if the task threw an exception - - void propagate_exception() const - { - if (eptr) - { - auto tmp = eptr; - eptr = nullptr; - std::rethrow_exception(tmp); - } - } - - }; - - array<task_state_type> tasks; - array<thread_id_type> worker_thread_ids; - - mutex m; - signaler task_done_signaler; - signaler task_ready_signaler; - bool we_are_destructing; - - std::vector<std::thread> threads; - - // restricted functions - thread_pool_implementation(thread_pool_implementation&); // copy constructor - thread_pool_implementation& operator=(thread_pool_implementation&); // assignment operator - - }; - - -// ---------------------------------------------------------------------------------------- - - class thread_pool - { - /*! - This object is just a shell that holds a std::shared_ptr - to the real thread_pool_implementation object. The reason for doing - it this way is so that we can allow any mixture of destruction orders - between thread_pool objects and futures. Whoever gets destroyed - last cleans up the thread_pool_implementation resources. - !*/ - typedef bound_function_pointer::kernel_1a_c bfp_type; - - public: - explicit thread_pool ( - unsigned long num_threads - ) - { - impl.reset(new thread_pool_implementation(num_threads)); - } - - ~thread_pool ( - ) - { - try - { - impl->shutdown_pool(); - } - catch (std::exception& e) - { - std::cerr << "An unhandled exception was inside a dlib::thread_pool when it was destructed." << std::endl; - std::cerr << "It's what string is: \n" << e.what() << std::endl; - using namespace std; - assert(false); - abort(); - } - catch (...) - { - std::cerr << "An unhandled exception was inside a dlib::thread_pool when it was destructed." << std::endl; - using namespace std; - assert(false); - abort(); - } - } - - void wait_for_task ( - uint64 task_id - ) const { impl->wait_for_task(task_id); } - - unsigned long num_threads_in_pool ( - ) const { return impl->num_threads_in_pool(); } - - void wait_for_all_tasks ( - ) const { impl->wait_for_all_tasks(); } - - bool is_task_thread ( - ) const { return impl->is_task_thread(); } - - template <typename T> - uint64 add_task ( - T& obj, - void (T::*funct)() - ) - { - return impl->add_task(obj, funct); - } - - template <typename T> - uint64 add_task ( - T& obj, - void (T::*funct)(long), - long arg1 - ) - { - return impl->add_task(obj, funct, arg1); - } - - template <typename T> - uint64 add_task ( - T& obj, - void (T::*funct)(long,long), - long arg1, - long arg2 - ) - { - return impl->add_task(obj, funct, arg1, arg2); - } - - // -------------------- - - template <typename F> - uint64 add_task ( - F& function_object - ) - { - COMPILE_TIME_ASSERT(is_function<F>::value == false); - COMPILE_TIME_ASSERT(is_pointer_type<F>::value == false); - - bfp_type temp; - temp.set(function_object); - uint64 id = impl->add_task_internal(temp); - - return id; - } - - template <typename F> - uint64 add_task_by_value ( - const F& function_object - ) - { - thread_pool_implementation::function_object_copy_instance<F>* ptr = 0; - ptr = new thread_pool_implementation::function_object_copy_instance<F>(function_object); - std::shared_ptr<thread_pool_implementation::function_object_copy> function_copy(ptr); - - - bfp_type temp; - temp.set(ptr->item); - uint64 id = impl->add_task_internal(temp, function_copy); - - return id; - } - - template <typename T> - uint64 add_task ( - const T& obj, - void (T::*funct)() const - ) - { - bfp_type temp; - temp.set(obj,funct); - uint64 id = impl->add_task_internal(temp); - - return id; - } - - template <typename T> - uint64 add_task_by_value ( - const T& obj, - void (T::*funct)() const - ) - { - thread_pool_implementation::function_object_copy_instance<const T>* ptr = 0; - ptr = new thread_pool_implementation::function_object_copy_instance<const T>(obj); - std::shared_ptr<thread_pool_implementation::function_object_copy> function_copy(ptr); - - bfp_type temp; - temp.set(ptr->item,funct); - uint64 id = impl->add_task_internal(temp, function_copy); - - return id; - } - - template <typename T> - uint64 add_task_by_value ( - const T& obj, - void (T::*funct)() - ) - { - thread_pool_implementation::function_object_copy_instance<T>* ptr = 0; - ptr = new thread_pool_implementation::function_object_copy_instance<T>(obj); - std::shared_ptr<thread_pool_implementation::function_object_copy> function_copy(ptr); - - bfp_type temp; - temp.set(ptr->item,funct); - uint64 id = impl->add_task_internal(temp, function_copy); - - return id; - } - - uint64 add_task ( - void (*funct)() - ) - { - bfp_type temp; - temp.set(funct); - uint64 id = impl->add_task_internal(temp); - - return id; - } - - // -------------------- - - template <typename F, typename A1> - uint64 add_task ( - F& function_object, - future<A1>& arg1 - ) - { - COMPILE_TIME_ASSERT(is_function<F>::value == false); - COMPILE_TIME_ASSERT(is_pointer_type<F>::value == false); - - bfp_type temp; - temp.set(function_object,arg1.get()); - uint64 id = impl->add_task_internal(temp); - - // tie the future to this task - arg1.task_id = id; - arg1.tp = impl; - return id; - } - - template <typename F, typename A1> - uint64 add_task_by_value ( - const F& function_object, - future<A1>& arg1 - ) - { - thread_pool_implementation::function_object_copy_instance<F>* ptr = 0; - ptr = new thread_pool_implementation::function_object_copy_instance<F>(function_object); - std::shared_ptr<thread_pool_implementation::function_object_copy> function_copy(ptr); - - bfp_type temp; - temp.set(ptr->item, arg1.get()); - uint64 id = impl->add_task_internal(temp, function_copy); - - // tie the future to this task - arg1.task_id = id; - arg1.tp = impl; - return id; - } - - template <typename T, typename T1, typename A1> - uint64 add_task ( - T& obj, - void (T::*funct)(T1), - future<A1>& arg1 - ) - { - bfp_type temp; - temp.set(obj,funct,arg1.get()); - uint64 id = impl->add_task_internal(temp); - - // tie the future to this task - arg1.task_id = id; - arg1.tp = impl; - return id; - } - - template <typename T, typename T1, typename A1> - uint64 add_task_by_value ( - const T& obj, - void (T::*funct)(T1), - future<A1>& arg1 - ) - { - thread_pool_implementation::function_object_copy_instance<T>* ptr = 0; - ptr = new thread_pool_implementation::function_object_copy_instance<T>(obj); - std::shared_ptr<thread_pool_implementation::function_object_copy> function_copy(ptr); - - bfp_type temp; - temp.set(ptr->item,funct,arg1.get()); - uint64 id = impl->add_task_internal(temp, function_copy); - - // tie the future to this task - arg1.task_id = id; - arg1.tp = impl; - return id; - } - - - template <typename T, typename T1, typename A1> - uint64 add_task ( - const T& obj, - void (T::*funct)(T1) const, - future<A1>& arg1 - ) - { - bfp_type temp; - temp.set(obj,funct,arg1.get()); - uint64 id = impl->add_task_internal(temp); - - // tie the future to this task - arg1.task_id = id; - arg1.tp = impl; - return id; - } - - template <typename T, typename T1, typename A1> - uint64 add_task_by_value ( - const T& obj, - void (T::*funct)(T1) const, - future<A1>& arg1 - ) - { - thread_pool_implementation::function_object_copy_instance<const T>* ptr = 0; - ptr = new thread_pool_implementation::function_object_copy_instance<const T>(obj); - std::shared_ptr<thread_pool_implementation::function_object_copy> function_copy(ptr); - - bfp_type temp; - temp.set(ptr->item,funct,arg1.get()); - uint64 id = impl->add_task_internal(temp, function_copy); - - // tie the future to this task - arg1.task_id = id; - arg1.tp = impl; - return id; - } - - template <typename T1, typename A1> - uint64 add_task ( - void (*funct)(T1), - future<A1>& arg1 - ) - { - bfp_type temp; - temp.set(funct,arg1.get()); - uint64 id = impl->add_task_internal(temp); - - // tie the future to this task - arg1.task_id = id; - arg1.tp = impl; - return id; - } - - // -------------------- - - template <typename F, typename A1, typename A2> - uint64 add_task ( - F& function_object, - future<A1>& arg1, - future<A2>& arg2 - ) - { - COMPILE_TIME_ASSERT(is_function<F>::value == false); - COMPILE_TIME_ASSERT(is_pointer_type<F>::value == false); - - bfp_type temp; - temp.set(function_object, arg1.get(), arg2.get()); - uint64 id = impl->add_task_internal(temp); - - // tie the future to this task - arg1.task_id = id; - arg1.tp = impl; - arg2.task_id = id; - arg2.tp = impl; - return id; - } - - template <typename F, typename A1, typename A2> - uint64 add_task_by_value ( - const F& function_object, - future<A1>& arg1, - future<A2>& arg2 - ) - { - thread_pool_implementation::function_object_copy_instance<F>* ptr = 0; - ptr = new thread_pool_implementation::function_object_copy_instance<F>(function_object); - std::shared_ptr<thread_pool_implementation::function_object_copy> function_copy(ptr); - - bfp_type temp; - temp.set(ptr->item, arg1.get(), arg2.get()); - uint64 id = impl->add_task_internal(temp, function_copy); - - // tie the future to this task - arg1.task_id = id; - arg1.tp = impl; - arg2.task_id = id; - arg2.tp = impl; - return id; - } - - template <typename T, typename T1, typename A1, - typename T2, typename A2> - uint64 add_task ( - T& obj, - void (T::*funct)(T1,T2), - future<A1>& arg1, - future<A2>& arg2 - ) - { - bfp_type temp; - temp.set(obj, funct, arg1.get(), arg2.get()); - uint64 id = impl->add_task_internal(temp); - - // tie the futures to this task - arg1.task_id = id; - arg1.tp = impl; - arg2.task_id = id; - arg2.tp = impl; - return id; - } - - template <typename T, typename T1, typename A1, - typename T2, typename A2> - uint64 add_task_by_value ( - const T& obj, - void (T::*funct)(T1,T2), - future<A1>& arg1, - future<A2>& arg2 - ) - { - thread_pool_implementation::function_object_copy_instance<T>* ptr = 0; - ptr = new thread_pool_implementation::function_object_copy_instance<T>(obj); - std::shared_ptr<thread_pool_implementation::function_object_copy> function_copy(ptr); - - bfp_type temp; - temp.set(ptr->item, funct, arg1.get(), arg2.get()); - uint64 id = impl->add_task_internal(temp, function_copy); - - // tie the futures to this task - arg1.task_id = id; - arg1.tp = impl; - arg2.task_id = id; - arg2.tp = impl; - return id; - } - - template <typename T, typename T1, typename A1, - typename T2, typename A2> - uint64 add_task ( - const T& obj, - void (T::*funct)(T1,T2) const, - future<A1>& arg1, - future<A2>& arg2 - ) - { - bfp_type temp; - temp.set(obj, funct, arg1.get(), arg2.get()); - uint64 id = impl->add_task_internal(temp); - - // tie the futures to this task - arg1.task_id = id; - arg1.tp = impl; - arg2.task_id = id; - arg2.tp = impl; - return id; - } - - template <typename T, typename T1, typename A1, - typename T2, typename A2> - uint64 add_task_by_value ( - const T& obj, - void (T::*funct)(T1,T2) const, - future<A1>& arg1, - future<A2>& arg2 - ) - { - thread_pool_implementation::function_object_copy_instance<const T>* ptr = 0; - ptr = new thread_pool_implementation::function_object_copy_instance<const T>(obj); - std::shared_ptr<thread_pool_implementation::function_object_copy> function_copy(ptr); - - bfp_type temp; - temp.set(ptr->item, funct, arg1.get(), arg2.get()); - uint64 id = impl->add_task_internal(temp, function_copy); - - // tie the futures to this task - arg1.task_id = id; - arg1.tp = impl; - arg2.task_id = id; - arg2.tp = impl; - return id; - } - - template <typename T1, typename A1, - typename T2, typename A2> - uint64 add_task ( - void (*funct)(T1,T2), - future<A1>& arg1, - future<A2>& arg2 - ) - { - bfp_type temp; - temp.set(funct, arg1.get(), arg2.get()); - uint64 id = impl->add_task_internal(temp); - - // tie the futures to this task - arg1.task_id = id; - arg1.tp = impl; - arg2.task_id = id; - arg2.tp = impl; - return id; - } - - // -------------------- - - template <typename F, typename A1, typename A2, typename A3> - uint64 add_task ( - F& function_object, - future<A1>& arg1, - future<A2>& arg2, - future<A3>& arg3 - ) - { - COMPILE_TIME_ASSERT(is_function<F>::value == false); - COMPILE_TIME_ASSERT(is_pointer_type<F>::value == false); - - bfp_type temp; - temp.set(function_object, arg1.get(), arg2.get(), arg3.get()); - uint64 id = impl->add_task_internal(temp); - - // tie the future to this task - arg1.task_id = id; - arg1.tp = impl; - arg2.task_id = id; - arg2.tp = impl; - arg3.task_id = id; - arg3.tp = impl; - return id; - } - - template <typename F, typename A1, typename A2, typename A3> - uint64 add_task_by_value ( - const F& function_object, - future<A1>& arg1, - future<A2>& arg2, - future<A3>& arg3 - ) - { - thread_pool_implementation::function_object_copy_instance<F>* ptr = 0; - ptr = new thread_pool_implementation::function_object_copy_instance<F>(function_object); - std::shared_ptr<thread_pool_implementation::function_object_copy> function_copy(ptr); - - bfp_type temp; - temp.set(ptr->item, arg1.get(), arg2.get(), arg3.get()); - uint64 id = impl->add_task_internal(temp, function_copy); - - // tie the future to this task - arg1.task_id = id; - arg1.tp = impl; - arg2.task_id = id; - arg2.tp = impl; - arg3.task_id = id; - arg3.tp = impl; - return id; - } - - template <typename T, typename T1, typename A1, - typename T2, typename A2, - typename T3, typename A3> - uint64 add_task ( - T& obj, - void (T::*funct)(T1,T2,T3), - future<A1>& arg1, - future<A2>& arg2, - future<A3>& arg3 - ) - { - bfp_type temp; - temp.set(obj, funct, arg1.get(), arg2.get(), arg3.get()); - uint64 id = impl->add_task_internal(temp); - - // tie the futures to this task - arg1.task_id = id; - arg1.tp = impl; - arg2.task_id = id; - arg2.tp = impl; - arg3.task_id = id; - arg3.tp = impl; - return id; - } - - template <typename T, typename T1, typename A1, - typename T2, typename A2, - typename T3, typename A3> - uint64 add_task_by_value ( - const T& obj, - void (T::*funct)(T1,T2,T3), - future<A1>& arg1, - future<A2>& arg2, - future<A3>& arg3 - ) - { - thread_pool_implementation::function_object_copy_instance<T>* ptr = 0; - ptr = new thread_pool_implementation::function_object_copy_instance<T>(obj); - std::shared_ptr<thread_pool_implementation::function_object_copy> function_copy(ptr); - - bfp_type temp; - temp.set(ptr->item, funct, arg1.get(), arg2.get(), arg3.get()); - uint64 id = impl->add_task_internal(temp, function_copy); - - // tie the futures to this task - arg1.task_id = id; - arg1.tp = impl; - arg2.task_id = id; - arg2.tp = impl; - arg3.task_id = id; - arg3.tp = impl; - return id; - } - - template <typename T, typename T1, typename A1, - typename T2, typename A2, - typename T3, typename A3> - uint64 add_task ( - const T& obj, - void (T::*funct)(T1,T2,T3) const, - future<A1>& arg1, - future<A2>& arg2, - future<A3>& arg3 - ) - { - bfp_type temp; - temp.set(obj, funct, arg1.get(), arg2.get(), arg3.get()); - uint64 id = impl->add_task_internal(temp); - - // tie the futures to this task - arg1.task_id = id; - arg1.tp = impl; - arg2.task_id = id; - arg2.tp = impl; - arg3.task_id = id; - arg3.tp = impl; - return id; - } - - template <typename T, typename T1, typename A1, - typename T2, typename A2, - typename T3, typename A3> - uint64 add_task_by_value ( - const T& obj, - void (T::*funct)(T1,T2,T3) const, - future<A1>& arg1, - future<A2>& arg2, - future<A3>& arg3 - ) - { - thread_pool_implementation::function_object_copy_instance<const T>* ptr = 0; - ptr = new thread_pool_implementation::function_object_copy_instance<const T>(obj); - std::shared_ptr<thread_pool_implementation::function_object_copy> function_copy(ptr); - - bfp_type temp; - temp.set(ptr->item, funct, arg1.get(), arg2.get(), arg3.get()); - uint64 id = impl->add_task_internal(temp, function_copy); - - // tie the futures to this task - arg1.task_id = id; - arg1.tp = impl; - arg2.task_id = id; - arg2.tp = impl; - arg3.task_id = id; - arg3.tp = impl; - return id; - } - - template <typename T1, typename A1, - typename T2, typename A2, - typename T3, typename A3> - uint64 add_task ( - void (*funct)(T1,T2,T3), - future<A1>& arg1, - future<A2>& arg2, - future<A3>& arg3 - ) - { - bfp_type temp; - temp.set(funct, arg1.get(), arg2.get(), arg3.get()); - uint64 id = impl->add_task_internal(temp); - - // tie the futures to this task - arg1.task_id = id; - arg1.tp = impl; - arg2.task_id = id; - arg2.tp = impl; - arg3.task_id = id; - arg3.tp = impl; - return id; - } - - // -------------------- - - template <typename F, typename A1, typename A2, typename A3, typename A4> - uint64 add_task ( - F& function_object, - future<A1>& arg1, - future<A2>& arg2, - future<A3>& arg3, - future<A4>& arg4 - ) - { - COMPILE_TIME_ASSERT(is_function<F>::value == false); - COMPILE_TIME_ASSERT(is_pointer_type<F>::value == false); - - bfp_type temp; - temp.set(function_object, arg1.get(), arg2.get(), arg3.get(), arg4.get()); - uint64 id = impl->add_task_internal(temp); - - // tie the future to this task - arg1.task_id = id; - arg1.tp = impl; - arg2.task_id = id; - arg2.tp = impl; - arg3.task_id = id; - arg3.tp = impl; - arg4.task_id = id; - arg4.tp = impl; - return id; - } - - template <typename F, typename A1, typename A2, typename A3, typename A4> - uint64 add_task_by_value ( - const F& function_object, - future<A1>& arg1, - future<A2>& arg2, - future<A3>& arg3, - future<A4>& arg4 - ) - { - thread_pool_implementation::function_object_copy_instance<F>* ptr = 0; - ptr = new thread_pool_implementation::function_object_copy_instance<F>(function_object); - std::shared_ptr<thread_pool_implementation::function_object_copy> function_copy(ptr); - - bfp_type temp; - temp.set(ptr->item, arg1.get(), arg2.get(), arg3.get(), arg4.get()); - uint64 id = impl->add_task_internal(temp, function_copy); - - // tie the future to this task - arg1.task_id = id; - arg1.tp = impl; - arg2.task_id = id; - arg2.tp = impl; - arg3.task_id = id; - arg3.tp = impl; - arg4.task_id = id; - arg4.tp = impl; - return id; - } - - template <typename T, typename T1, typename A1, - typename T2, typename A2, - typename T3, typename A3, - typename T4, typename A4> - uint64 add_task ( - T& obj, - void (T::*funct)(T1,T2,T3,T4), - future<A1>& arg1, - future<A2>& arg2, - future<A3>& arg3, - future<A4>& arg4 - ) - { - bfp_type temp; - temp.set(obj, funct, arg1.get(), arg2.get(), arg3.get(), arg4.get()); - uint64 id = impl->add_task_internal(temp); - - // tie the futures to this task - arg1.task_id = id; - arg1.tp = impl; - arg2.task_id = id; - arg2.tp = impl; - arg3.task_id = id; - arg3.tp = impl; - arg4.task_id = id; - arg4.tp = impl; - return id; - } - - template <typename T, typename T1, typename A1, - typename T2, typename A2, - typename T3, typename A3, - typename T4, typename A4> - uint64 add_task_by_value ( - const T& obj, - void (T::*funct)(T1,T2,T3,T4), - future<A1>& arg1, - future<A2>& arg2, - future<A3>& arg3, - future<A4>& arg4 - ) - { - thread_pool_implementation::function_object_copy_instance<T>* ptr = 0; - ptr = new thread_pool_implementation::function_object_copy_instance<T>(obj); - std::shared_ptr<thread_pool_implementation::function_object_copy> function_copy(ptr); - - bfp_type temp; - temp.set(ptr->item, funct, arg1.get(), arg2.get(), arg3.get(), arg4.get()); - uint64 id = impl->add_task_internal(temp, function_copy); - - // tie the futures to this task - arg1.task_id = id; - arg1.tp = impl; - arg2.task_id = id; - arg2.tp = impl; - arg3.task_id = id; - arg3.tp = impl; - arg4.task_id = id; - arg4.tp = impl; - return id; - } - - template <typename T, typename T1, typename A1, - typename T2, typename A2, - typename T3, typename A3, - typename T4, typename A4> - uint64 add_task ( - const T& obj, - void (T::*funct)(T1,T2,T3,T4) const, - future<A1>& arg1, - future<A2>& arg2, - future<A3>& arg3, - future<A4>& arg4 - ) - { - bfp_type temp; - temp.set(obj, funct, arg1.get(), arg2.get(), arg3.get(), arg4.get()); - uint64 id = impl->add_task_internal(temp); - - // tie the futures to this task - arg1.task_id = id; - arg1.tp = impl; - arg2.task_id = id; - arg2.tp = impl; - arg3.task_id = id; - arg3.tp = impl; - arg4.task_id = id; - arg4.tp = impl; - return id; - } - - template <typename T, typename T1, typename A1, - typename T2, typename A2, - typename T3, typename A3, - typename T4, typename A4> - uint64 add_task_by_value ( - const T& obj, - void (T::*funct)(T1,T2,T3,T4) const, - future<A1>& arg1, - future<A2>& arg2, - future<A3>& arg3, - future<A4>& arg4 - ) - { - thread_pool_implementation::function_object_copy_instance<const T>* ptr = 0; - ptr = new thread_pool_implementation::function_object_copy_instance<const T>(obj); - std::shared_ptr<thread_pool_implementation::function_object_copy> function_copy(ptr); - - bfp_type temp; - temp.set(ptr->item, funct, arg1.get(), arg2.get(), arg3.get(), arg4.get()); - uint64 id = impl->add_task_internal(temp, function_copy); - - // tie the futures to this task - arg1.task_id = id; - arg1.tp = impl; - arg2.task_id = id; - arg2.tp = impl; - arg3.task_id = id; - arg3.tp = impl; - arg4.task_id = id; - arg4.tp = impl; - return id; - } - - template <typename T1, typename A1, - typename T2, typename A2, - typename T3, typename A3, - typename T4, typename A4> - uint64 add_task ( - void (*funct)(T1,T2,T3,T4), - future<A1>& arg1, - future<A2>& arg2, - future<A3>& arg3, - future<A4>& arg4 - ) - { - bfp_type temp; - temp.set(funct, arg1.get(), arg2.get(), arg3.get(), arg4.get()); - uint64 id = impl->add_task_internal(temp); - - // tie the futures to this task - arg1.task_id = id; - arg1.tp = impl; - arg2.task_id = id; - arg2.tp = impl; - arg3.task_id = id; - arg3.tp = impl; - arg4.task_id = id; - arg4.tp = impl; - return id; - } - - private: - - std::shared_ptr<thread_pool_implementation> impl; - - // restricted functions - thread_pool(thread_pool&); // copy constructor - thread_pool& operator=(thread_pool&); // assignment operator - - }; - - -// ---------------------------------------------------------------------------------------- - - template <typename T> - void future<T>:: - wait ( - ) const - { - if (tp) - { - tp->wait_for_task(task_id); - tp.reset(); - task_id = 0; - } - } - -} - -// ---------------------------------------------------------------------------------------- - -#ifdef NO_MAKEFILE -#include "thread_pool_extension.cpp" -#endif - -#endif // DLIB_THREAD_POOl_Hh_ - - |