mirror of https://github.com/davisking/dlib.git
Changed the thread_pool and future classes so that any mixture of
destruction orders between the two is legal. --HG-- extra : convert_revision : svn%3Afdd8eb12-d10e-0410-9acb-85c331704f74/trunk%403138
This commit is contained in:
parent
af20cb9f36
commit
6c65527410
|
@ -67,12 +67,13 @@ namespace
|
|||
void perform_test (
|
||||
)
|
||||
{
|
||||
add_functor f;
|
||||
for (int num_threads= 0; num_threads < 4; ++num_threads)
|
||||
{
|
||||
future<int> a, b, c, res;
|
||||
thread_pool tp(num_threads);
|
||||
print_spinner();
|
||||
|
||||
future<int> a, b, c, res;
|
||||
future<some_struct> obj;
|
||||
|
||||
|
||||
|
@ -205,12 +206,12 @@ namespace
|
|||
a = 1;
|
||||
b = 2;
|
||||
res = 0;
|
||||
add_functor f;
|
||||
tp.add_task(f, a, b, res);
|
||||
DLIB_TEST(a == 1);
|
||||
DLIB_TEST(b == 2);
|
||||
DLIB_TEST(res == 3);
|
||||
|
||||
|
||||
global_var = 0;
|
||||
DLIB_TEST(global_var == 0);
|
||||
id = tp.add_task(&set_global_var);
|
||||
|
@ -239,6 +240,9 @@ namespace
|
|||
|
||||
|
||||
}
|
||||
|
||||
// add this task just to to perterb the thread pool before it goes out of scope
|
||||
tp.add_task(f, a, b, res);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -10,8 +10,8 @@ namespace dlib
|
|||
|
||||
// ----------------------------------------------------------------------------------------
|
||||
|
||||
thread_pool::
|
||||
thread_pool (
|
||||
thread_pool_implementation::
|
||||
thread_pool_implementation (
|
||||
unsigned long num_threads
|
||||
) :
|
||||
task_done_signaler(m),
|
||||
|
@ -21,7 +21,7 @@ namespace dlib
|
|||
tasks.resize(num_threads);
|
||||
for (unsigned long i = 0; i < num_threads; ++i)
|
||||
{
|
||||
register_thread(*this, &thread_pool::thread);
|
||||
register_thread(*this, &thread_pool_implementation::thread);
|
||||
}
|
||||
|
||||
start();
|
||||
|
@ -29,10 +29,33 @@ namespace dlib
|
|||
|
||||
// ----------------------------------------------------------------------------------------
|
||||
|
||||
thread_pool::
|
||||
~thread_pool()
|
||||
void thread_pool_implementation::
|
||||
shutdown_pool (
|
||||
)
|
||||
{
|
||||
{auto_mutex M(m);
|
||||
{
|
||||
auto_mutex M(m);
|
||||
|
||||
// first wait for all pending tasks to finish
|
||||
bool found_task = true;
|
||||
while (found_task)
|
||||
{
|
||||
found_task = false;
|
||||
for (unsigned long i = 0; i < tasks.size(); ++i)
|
||||
{
|
||||
// If task bucket i has a task that is currently supposed to be processed
|
||||
if (tasks[i].is_empty() == false)
|
||||
{
|
||||
found_task = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (found_task)
|
||||
task_done_signaler.wait();
|
||||
}
|
||||
|
||||
// now tell the threads to kill themselves
|
||||
we_are_destructing = true;
|
||||
task_ready_signaler.broadcast();
|
||||
}
|
||||
|
@ -42,7 +65,15 @@ namespace dlib
|
|||
|
||||
// ----------------------------------------------------------------------------------------
|
||||
|
||||
unsigned long thread_pool::
|
||||
thread_pool_implementation::
|
||||
~thread_pool_implementation()
|
||||
{
|
||||
shutdown_pool();
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------------------
|
||||
|
||||
unsigned long thread_pool_implementation::
|
||||
num_threads_in_pool (
|
||||
) const
|
||||
{
|
||||
|
@ -52,7 +83,7 @@ namespace dlib
|
|||
|
||||
// ----------------------------------------------------------------------------------------
|
||||
|
||||
void thread_pool::
|
||||
void thread_pool_implementation::
|
||||
wait_for_task (
|
||||
uint64 task_id
|
||||
) const
|
||||
|
@ -68,7 +99,7 @@ namespace dlib
|
|||
|
||||
// ----------------------------------------------------------------------------------------
|
||||
|
||||
void thread_pool::
|
||||
void thread_pool_implementation::
|
||||
wait_for_all_tasks (
|
||||
) const
|
||||
{
|
||||
|
@ -97,7 +128,7 @@ namespace dlib
|
|||
|
||||
// ----------------------------------------------------------------------------------------
|
||||
|
||||
bool thread_pool::
|
||||
bool thread_pool_implementation::
|
||||
is_worker_thread (
|
||||
const thread_id_type id
|
||||
) const
|
||||
|
@ -118,7 +149,7 @@ namespace dlib
|
|||
|
||||
// ----------------------------------------------------------------------------------------
|
||||
|
||||
void thread_pool::
|
||||
void thread_pool_implementation::
|
||||
thread (
|
||||
)
|
||||
{
|
||||
|
@ -175,7 +206,7 @@ namespace dlib
|
|||
|
||||
// ----------------------------------------------------------------------------------------
|
||||
|
||||
long thread_pool::
|
||||
long thread_pool_implementation::
|
||||
find_empty_task_slot (
|
||||
) const
|
||||
{
|
||||
|
@ -190,7 +221,7 @@ namespace dlib
|
|||
|
||||
// ----------------------------------------------------------------------------------------
|
||||
|
||||
long thread_pool::
|
||||
long thread_pool_implementation::
|
||||
find_ready_task (
|
||||
) const
|
||||
{
|
||||
|
@ -205,7 +236,7 @@ namespace dlib
|
|||
|
||||
// ----------------------------------------------------------------------------------------
|
||||
|
||||
uint64 thread_pool::
|
||||
uint64 thread_pool_implementation::
|
||||
make_next_task_id (
|
||||
long idx
|
||||
)
|
||||
|
@ -217,7 +248,7 @@ namespace dlib
|
|||
|
||||
// ----------------------------------------------------------------------------------------
|
||||
|
||||
unsigned long thread_pool::
|
||||
unsigned long thread_pool_implementation::
|
||||
task_id_to_index (
|
||||
uint64 id
|
||||
) const
|
||||
|
@ -227,7 +258,7 @@ namespace dlib
|
|||
|
||||
// ----------------------------------------------------------------------------------------
|
||||
|
||||
uint64 thread_pool::
|
||||
uint64 thread_pool_implementation::
|
||||
add_task_internal (
|
||||
const bfp_type& bfp
|
||||
)
|
||||
|
@ -270,7 +301,7 @@ namespace dlib
|
|||
|
||||
// ----------------------------------------------------------------------------------------
|
||||
|
||||
bool thread_pool::
|
||||
bool thread_pool_implementation::
|
||||
is_task_thread (
|
||||
) const
|
||||
{
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -76,11 +76,6 @@ namespace dlib
|
|||
~future (
|
||||
);
|
||||
/*!
|
||||
requires
|
||||
- if (item.is_ready() == false) then
|
||||
- The thread_pool that this future was passed to should still exist
|
||||
(i.e. You can't pass a future to a thread_pool and then destruct the
|
||||
thread_pool before you destruct the future).
|
||||
ensures
|
||||
- if (item.is_ready() == false) then
|
||||
- the call to this function blocks until the thread processing the task related
|
||||
|
@ -223,6 +218,12 @@ namespace dlib
|
|||
mode any thread that calls add_task() is considered to be
|
||||
a thread_pool thread capable of executing tasks.
|
||||
|
||||
Also note that all function objects are passed to the tasks
|
||||
by reference. This means you should ensure that your function
|
||||
objects are not destroyed while tasks are still using them.
|
||||
(e.g. Don't let them go out of scope right after a call to
|
||||
add_task())
|
||||
|
||||
EXCEPTIONS
|
||||
Note that if an exception is thrown inside a task thread and
|
||||
is not caught then the normal rule for uncaught exceptions in
|
||||
|
@ -248,7 +249,7 @@ namespace dlib
|
|||
);
|
||||
/*!
|
||||
ensures
|
||||
- all resources allocated by *this have been freed.
|
||||
- blocks until all tasks in the pool have finished.
|
||||
!*/
|
||||
|
||||
bool is_task_thread (
|
||||
|
|
Loading…
Reference in New Issue