Commit 54bfa36a authored by Davis King's avatar Davis King

Added the unregister_thread_end_handler() function and also used it to

fix a bug that can trigger when the thread_specific_data object is destructed.

--HG--
extra : convert_revision : svn%3Afdd8eb12-d10e-0410-9acb-85c331704f74/trunk%402483
parent 66a3e292
...@@ -31,6 +31,9 @@ namespace dlib ...@@ -31,6 +31,9 @@ namespace dlib
~thread_specific_data ( ~thread_specific_data (
) )
{ {
unregister_thread_end_handler(const_cast<thread_specific_data&>(*this),&thread_specific_data::thread_end_handler);
auto_mutex M(m);
items.reset(); items.reset();
while (items.move_next()) while (items.move_next())
{ {
...@@ -94,9 +97,12 @@ namespace dlib ...@@ -94,9 +97,12 @@ namespace dlib
thread_id_type junk; thread_id_type junk;
T* item; T* item;
auto_mutex M(m); auto_mutex M(m);
if (items[id])
{
items.remove(id,junk,item); items.remove(id,junk,item);
delete item; delete item;
} }
}
mutable typename binary_search_tree<thread_id_type,T*>::kernel_2a items; mutable typename binary_search_tree<thread_id_type,T*>::kernel_2a items;
mutex m; mutex m;
......
...@@ -113,6 +113,26 @@ namespace dlib ...@@ -113,6 +113,26 @@ namespace dlib
If this exception is thrown then the call to this function had no effect. If this exception is thrown then the call to this function had no effect.
!*/ !*/
// ----------------------------------------------------------------------------------------
template <
typename T
>
void unregister_thread_end_handler (
T& obj,
void (T::*handler)()
);
/*!
requires
- handler == a valid member function pointer for class T
ensures
- Undoes all previous calls to register_thread_end_handler(obj,handler).
So the given handler won't be called when any threads end.
throws
- std::bad_alloc
If this exception is thrown then the call to this function had no effect.
!*/
// ---------------------------------------------------------------------------------------- // ----------------------------------------------------------------------------------------
template < template <
......
...@@ -81,6 +81,32 @@ namespace dlib ...@@ -81,6 +81,32 @@ namespace dlib
void* param void* param
); );
template <
typename T
>
void unregister_thread_end_handler (
T& obj,
void (T::*handler)()
)
{
member_function_pointer<>::kernel_1a 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 < template <
typename T typename T
> >
...@@ -202,6 +228,19 @@ namespace dlib ...@@ -202,6 +228,19 @@ namespace dlib
threads_kernel_shared::thread_pool().register_thread_end_handler(obj,handler); 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)()
)
{
threads_kernel_shared::thread_pool().unregister_thread_end_handler(obj,handler);
}
// ---------------------------------------------------------------------------------------- // ----------------------------------------------------------------------------------------
template < template <
......
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