Commit 19a3000d authored by Davis King's avatar Davis King

Fixed a destruction order problem in the timer object and also added

some extra mutex locks to the global singleton in the gui core.

--HG--
extra : convert_revision : svn%3Afdd8eb12-d10e-0410-9acb-85c331704f74/trunk%402533
parent 9e0980e9
...@@ -63,6 +63,12 @@ namespace dlib ...@@ -63,6 +63,12 @@ namespace dlib
// ---------------------------------------------------------------------------------------- // ----------------------------------------------------------------------------------------
dlib::mutex* global_mutex()
{
static dlib::mutex* m = new dlib::mutex;
return m;
}
class event_handler_thread : public threaded_object class event_handler_thread : public threaded_object
{ {
public: public:
...@@ -180,6 +186,8 @@ namespace dlib ...@@ -180,6 +186,8 @@ namespace dlib
wait(); wait();
} }
delete global_mutex();
} }
private: private:
...@@ -268,12 +276,28 @@ namespace dlib ...@@ -268,12 +276,28 @@ namespace dlib
} }
}; };
// Do all this just to make sure global_mutex() is initialized at program start
// and thus hopefully before any threads have the chance to startup and call
// globals() concurrently.
struct call_global_mutex { call_global_mutex() { global_mutex(); } };
static call_global_mutex call_global_mutex_instance;
event_handler_thread& globals() event_handler_thread& globals()
{
global_mutex()->lock();
try
{ {
static event_handler_thread* p = new event_handler_thread; static event_handler_thread* p = new event_handler_thread;
global_mutex()->unlock();
p->start_event_thread(); p->start_event_thread();
return *p; return *p;
} }
catch (...)
{
global_mutex()->unlock();
throw;
}
}
struct event_handler_thread_destruct_helper struct event_handler_thread_destruct_helper
{ {
......
...@@ -55,6 +55,12 @@ namespace dlib ...@@ -55,6 +55,12 @@ namespace dlib
// ---------------------------------------------------------------------------------------- // ----------------------------------------------------------------------------------------
dlib::mutex* global_mutex()
{
static dlib::mutex* m = new dlib::mutex;
return m;
}
class event_handler_thread : public threaded_object class event_handler_thread : public threaded_object
{ {
public: public:
...@@ -169,6 +175,8 @@ namespace dlib ...@@ -169,6 +175,8 @@ namespace dlib
wait(); wait();
} }
} }
delete global_mutex();
} }
private: private:
...@@ -300,9 +308,16 @@ namespace dlib ...@@ -300,9 +308,16 @@ namespace dlib
void init_keyboard_mod_masks(); void init_keyboard_mod_masks();
}; };
// Do all this just to make sure global_mutex() is initialized at program start
// and thus hopefully before any threads have the chance to startup and call
// globals() concurrently.
struct call_global_mutex { call_global_mutex() { global_mutex(); } };
static call_global_mutex call_global_mutex_instance;
event_handler_thread& globals() event_handler_thread& globals()
{ {
static event_handler_thread* p = new event_handler_thread; auto_mutex M(*global_mutex());
static event_handler_thread* p = new event_handler_thread();
return *p; return *p;
} }
......
...@@ -181,9 +181,9 @@ namespace dlib ...@@ -181,9 +181,9 @@ namespace dlib
// ---------------------------------------------------------------------------------------- // ----------------------------------------------------------------------------------------
timer_kernel_2_global_clock& get_global_clock() shared_ptr_thread_safe<timer_kernel_2_global_clock> get_global_clock()
{ {
static timer_kernel_2_global_clock d; static shared_ptr_thread_safe<timer_kernel_2_global_clock> d(new timer_kernel_2_global_clock);
return d; return d;
} }
......
...@@ -9,6 +9,7 @@ ...@@ -9,6 +9,7 @@
#include "timer_kernel_abstract.h" #include "timer_kernel_abstract.h"
#include "../uintn.h" #include "../uintn.h"
#include "../binary_search_tree.h" #include "../binary_search_tree.h"
#include "../smart_pointers_thread_safe.h"
namespace dlib namespace dlib
{ {
...@@ -94,17 +95,11 @@ namespace dlib ...@@ -94,17 +95,11 @@ namespace dlib
mutex m; mutex m;
friend timer_kernel_2_global_clock& get_global_clock(); friend shared_ptr_thread_safe<timer_kernel_2_global_clock> get_global_clock();
private: private:
timer_kernel_2_global_clock(); timer_kernel_2_global_clock();
void destruct();
/*!
ensures
- calls delete this;
!*/
time_map tm; time_map tm;
signaler s; signaler s;
bool shutdown; bool shutdown;
...@@ -117,7 +112,7 @@ namespace dlib ...@@ -117,7 +112,7 @@ namespace dlib
- spawns timer tasks as is appropriate - spawns timer tasks as is appropriate
!*/ !*/
}; };
timer_kernel_2_global_clock& get_global_clock(); shared_ptr_thread_safe<timer_kernel_2_global_clock> get_global_clock();
/*! /*!
ensures ensures
- returns the global instance of the timer_kernel_2_global_clock object - returns the global instance of the timer_kernel_2_global_clock object
...@@ -138,9 +133,10 @@ namespace dlib ...@@ -138,9 +133,10 @@ namespace dlib
- af == a pointer to the action_function() - af == a pointer to the action_function()
- in_global_clock == false - in_global_clock == false
- next_time_to_run == 0 - next_time_to_run == 0
- gc == get_global_clock()
CONVENTION CONVENTION
- the mutex used to lock everything is get_global_clock().m - the mutex used to lock everything is gc->m
- running == is_running() - running == is_running()
- delay == delay_time() - delay == delay_time()
- *ao == action_object() - *ao == action_object()
...@@ -207,6 +203,7 @@ namespace dlib ...@@ -207,6 +203,7 @@ namespace dlib
// data members // data members
T& ao; T& ao;
const af_type af; const af_type af;
shared_ptr_thread_safe<timer_kernel_2_global_clock> gc;
// restricted functions // restricted functions
timer_kernel_2(const timer_kernel_2&); // copy constructor timer_kernel_2(const timer_kernel_2&); // copy constructor
...@@ -229,7 +226,8 @@ namespace dlib ...@@ -229,7 +226,8 @@ namespace dlib
af_type af_ af_type af_
) : ) :
ao(ao_), ao(ao_),
af(af_) af(af_),
gc(get_global_clock())
{ {
delay = 1000; delay = 1000;
next_time_to_run = 0; next_time_to_run = 0;
...@@ -259,9 +257,9 @@ namespace dlib ...@@ -259,9 +257,9 @@ namespace dlib
clear( clear(
) )
{ {
auto_mutex M(get_global_clock().m); auto_mutex M(gc->m);
running = false; running = false;
get_global_clock().remove(this); gc->remove(this);
delay = 1000; delay = 1000;
next_time_to_run = 0; next_time_to_run = 0;
} }
...@@ -311,7 +309,7 @@ namespace dlib ...@@ -311,7 +309,7 @@ namespace dlib
is_running ( is_running (
) const ) const
{ {
auto_mutex M(get_global_clock().m); auto_mutex M(gc->m);
return running; return running;
} }
...@@ -324,7 +322,7 @@ namespace dlib ...@@ -324,7 +322,7 @@ namespace dlib
delay_time ( delay_time (
) const ) const
{ {
auto_mutex M(get_global_clock().m); auto_mutex M(gc->m);
return delay; return delay;
} }
...@@ -338,8 +336,8 @@ namespace dlib ...@@ -338,8 +336,8 @@ namespace dlib
unsigned long milliseconds unsigned long milliseconds
) )
{ {
auto_mutex M(get_global_clock().m); auto_mutex M(gc->m);
get_global_clock().adjust_delay(this,milliseconds); gc->adjust_delay(this,milliseconds);
} }
// ---------------------------------------------------------------------------------------- // ----------------------------------------------------------------------------------------
...@@ -351,10 +349,10 @@ namespace dlib ...@@ -351,10 +349,10 @@ namespace dlib
start ( start (
) )
{ {
auto_mutex M(get_global_clock().m); auto_mutex M(gc->m);
if (!running) if (!running)
{ {
get_global_clock().add(this); gc->add(this);
running = true; running = true;
} }
} }
...@@ -368,10 +366,10 @@ namespace dlib ...@@ -368,10 +366,10 @@ namespace dlib
stop ( stop (
) )
{ {
get_global_clock().m.lock(); gc->m.lock();
running = false; running = false;
get_global_clock().remove(this); gc->remove(this);
get_global_clock().m.unlock(); gc->m.unlock();
} }
// ---------------------------------------------------------------------------------------- // ----------------------------------------------------------------------------------------
...@@ -385,11 +383,11 @@ namespace dlib ...@@ -385,11 +383,11 @@ namespace dlib
{ {
// call the action function // call the action function
(ao.*af)(); (ao.*af)();
auto_mutex M(get_global_clock().m); auto_mutex M(gc->m);
if (running) if (running)
{ {
get_global_clock().remove(this); gc->remove(this);
get_global_clock().add(this); gc->add(this);
} }
} }
...@@ -402,10 +400,10 @@ namespace dlib ...@@ -402,10 +400,10 @@ namespace dlib
stop_and_wait ( stop_and_wait (
) )
{ {
get_global_clock().m.lock(); gc->m.lock();
running = false; running = false;
get_global_clock().remove(this); gc->remove(this);
get_global_clock().m.unlock(); gc->m.unlock();
wait(); wait();
} }
......
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