Commit e1b3a927 authored by Davis King's avatar Davis King

Removed two try/catch blocks from the threading code. One was replaced with

the RAII equivalent and the other was the final catch block to log uncaught exceptions
from the user and then abort the program.  The code now lets the exception escape
to the operating system so that it is easier to debug uncaught exceptions.

--HG--
extra : convert_revision : svn%3Afdd8eb12-d10e-0410-9acb-85c331704f74/trunk%403201
parent f9c83710
...@@ -271,6 +271,7 @@ namespace ...@@ -271,6 +271,7 @@ namespace
test5 a5; test5 a5;
} }
DLIB_TEST(count == (i+1)*3); DLIB_TEST(count == (i+1)*3);
print_spinner();
} }
count = 0; count = 0;
...@@ -285,6 +286,7 @@ namespace ...@@ -285,6 +286,7 @@ namespace
dlib::sleep(50); dlib::sleep(50);
} }
DLIB_TEST(count == (i+1)*3); DLIB_TEST(count == (i+1)*3);
print_spinner();
} }
} }
......
...@@ -161,78 +161,64 @@ namespace dlib ...@@ -161,78 +161,64 @@ namespace dlib
// ---------------------------------------------------------------------------------------- // ----------------------------------------------------------------------------------------
void multithreaded_object:: multithreaded_object::raii_thread_helper::
thread_helper( raii_thread_helper(
) multithreaded_object& self_,
thread_id_type id_
) : self(self_), id(id_){}
multithreaded_object::raii_thread_helper::
~raii_thread_helper()
{ {
mfp mf; auto_mutex M(self.m_);
const thread_id_type id = get_thread_id(); if (self.thread_ids.is_in_domain(id))
try
{ {
// if there is a dead_thread sitting around then pull it mfp temp;
// out and put it into mf thread_id_type id_temp;
{ self.thread_ids.remove(id,id_temp,temp);
auto_mutex M(m_); // put this thread's registered function back into the dead_threads queue
if (dead_threads.size() > 0) self.dead_threads.enqueue(temp);
{ }
dead_threads.dequeue(mf);
mfp temp;
thread_id_type id_temp = id;
temp = mf;
thread_ids.add(id_temp,temp);
}
}
if (mf.is_set()) --self.threads_started;
{ // If this is the last thread to terminate then
// call the registered thread function // signal that that is the case.
mf(); if (self.threads_started == 0)
{
self.is_running_ = false;
self.should_stop_ = false;
self.s.broadcast();
}
}
auto_mutex M(m_); // ----------------------------------------------------------------------------------------
if (thread_ids.is_in_domain(id))
{
mfp temp;
thread_id_type id_temp;
thread_ids.remove(id,id_temp,temp);
} void multithreaded_object::
thread_helper(
)
{
mfp mf;
thread_id_type id = get_thread_id();
// put this thread's registered function back into the dead_threads queue // this guy's destructor does all the necessary cleanup in this function
dead_threads.enqueue(mf); raii_thread_helper raii(*this, id);
}
auto_mutex M(m_); // if there is a dead_thread sitting around then pull it
--threads_started; // out and put it into mf
// If this is the last thread to terminate then
// signal that that is the case.
if (threads_started == 0)
{
is_running_ = false;
should_stop_ = false;
s.broadcast();
}
}
catch (...)
{ {
auto_mutex M(m_); auto_mutex M(m_);
if (thread_ids.is_in_domain(id)) if (dead_threads.size() > 0)
{ {
mfp temp; dead_threads.dequeue(mf);
thread_id_type id_temp; mfp temp(mf);
thread_ids.remove(id,id_temp,temp); thread_ids.add(id,temp);
} }
}
--threads_started; if (mf.is_set())
// If this is the last thread to terminate then {
// signal that that is the case. // call the registered thread function
if (threads_started == 0) mf();
{
is_running_ = false;
should_stop_ = false;
s.broadcast();
}
throw;
} }
} }
......
...@@ -113,6 +113,16 @@ namespace dlib ...@@ -113,6 +113,16 @@ namespace dlib
private: 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( void thread_helper(
); );
......
...@@ -225,35 +225,11 @@ namespace dlib ...@@ -225,35 +225,11 @@ namespace dlib
self.data_empty.signal(); self.data_empty.signal();
self.data_mutex.unlock(); self.data_mutex.unlock();
// call funct with its intended parameter // Call funct with its intended parameter. If this function throws then
try // we intentionally let the exception escape the thread and result in whatever
{ // happens when it gets caught by the OS (generally the program is terminated).
funct(param); funct(param);
self.call_end_handlers(); self.call_end_handlers();
}
catch (std::exception& e)
{
std::cerr << "An exception was thrown in a thread and was not caught. Its what() string is:\n"
<< e.what() << std::endl;
self.data_mutex.lock();
--self.total_count;
self.destructed.signal();
self.data_mutex.unlock();
abort();
}
catch (...)
{
std::cerr << "An exception was thrown in a thread and was not caught." << std::endl;
self.data_mutex.lock();
--self.total_count;
self.destructed.signal();
self.data_mutex.unlock();
abort();
}
self.data_mutex.lock(); self.data_mutex.lock();
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment