summaryrefslogtreecommitdiffstats
path: root/ml/dlib/dlib/threads/thread_pool_extension.h
diff options
context:
space:
mode:
Diffstat (limited to 'ml/dlib/dlib/threads/thread_pool_extension.h')
-rw-r--r--ml/dlib/dlib/threads/thread_pool_extension.h1392
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_
-
-