diff -r d56511a02884 src/graphics.cc --- a/src/graphics.cc Thu Jun 26 16:06:14 2008 -0400 +++ b/src/graphics.cc Sat Jul 05 17:30:56 2008 +0200 @@ -1268,6 +1268,56 @@ gh_manager::do_free (const graphics_hand error ("graphics_handle::free: can't delete root figure"); } } +#if defined (__WIN32__) && ! defined (__CYGWIN__) +CRITICAL_SECTION __go_lock__; +#else +pthread_mutex_t __go_lock__; +#endif + +void +gh_manager::init_mutex (void) +{ +#if defined (__WIN32__) && ! defined (__CYGWIN__) + InitializeCriticalSection (&__go_lock__); +#else + pthread_mutexattr_t attr; + pthread_mutexattr_init (&attr); + pthread_mutexattr_settype (&attr, PTHREAD_MUTEX_RECURSIVE); // mutex needs to be recursive + pthread_mutex_init (&__go_lock__, &attr); + pthread_mutexattr_destroy (&attr); +#endif +} + +void +gh_manager::cleanup_mutex (void) +{ +#if defined (__WIN32__) && ! defined (__CYGWIN__) + DeleteCriticalSection (&__go_lock__); +#else + pthread_mutex_destroy (&__go_lock__); +#endif +} + +void +gh_manager::do_lock (void) +{ +#if defined (__WIN32__) && ! defined (__CYGWIN__) + EnterCriticalSection (&__go_lock__); +#else + pthread_mutex_lock (&__go_lock__); +#endif +} + +void +gh_manager::do_unlock (void) +{ +#if defined (__WIN32__) && ! defined (__CYGWIN__) + LeaveCriticalSection (&__go_lock__); +#else + pthread_mutex_unlock (&__go_lock__); +#endif +} + gh_manager *gh_manager::instance = 0; @@ -3591,10 +3641,16 @@ gh_manager::gh_manager (void) : handle_map (), handle_free_list (), next_handle (-1.0 - (rand () + 1.0) / (RAND_MAX + 2.0)) { + init_mutex(); handle_map[0] = graphics_object (new root_figure ()); // Make sure the default backend is registered. graphics_backend::default_backend (); +} + +gh_manager::~gh_manager (void) +{ + cleanup_mutex (); } graphics_handle @@ -3695,6 +3751,8 @@ for the graphics handle @var{h}.\n\ for the graphics handle @var{h}.\n\ @end deftypefn") { + gh_manager::lock_guard guard; + octave_value retval; int nargin = args.length (); @@ -3745,6 +3803,8 @@ values or lists respectively.\n\ values or lists respectively.\n\ @end deftypefn") { + gh_manager::lock_guard guard; + octave_value retval; octave_value_list vlist; @@ -3815,6 +3875,8 @@ values or lists respectively.\n\ values or lists respectively.\n\ @end deftypefn") { + gh_manager::lock_guard guard; + octave_value retval; octave_value_list vlist; @@ -3936,6 +3998,8 @@ Undocumented internal function.\n\ Undocumented internal function.\n\ @end deftypefn") { + gh_manager::lock_guard guard; + octave_value retval; if (args.length () > 0) @@ -4064,6 +4128,8 @@ Undocumented internal function.\n\ Undocumented internal function.\n\ @end deftypefn") { + gh_manager::lock_guard guard; + octave_value_list retval; if (args.length () == 1) @@ -4112,6 +4178,8 @@ Undocumented internal function.\n\ Undocumented internal function.\n\ @end deftypefn") { + gh_manager::lock_guard guard; + octave_value retval; int nargin = args.length (); @@ -4338,6 +4406,7 @@ addlistener (gcf, \"position\", @{@@my_l \n\ @end deftypefn") { + gh_manager::lock_guard guard; octave_value retval; if (args.length () == 3) @@ -4354,6 +4423,7 @@ addlistener (gcf, \"position\", @{@@my_l if (gh.ok ()) { + graphics_object go = gh_manager::get_object (gh); go.add_property_listener (pname, args(2), POSTSET); @@ -4434,6 +4504,7 @@ addproperty (\"my_style\", gcf, \"lineli \n\ @end deftypefn") { + gh_manager::lock_guard guard; octave_value retval; if (args.length () >= 3) diff -r d56511a02884 src/graphics.h.in --- a/src/graphics.h.in Thu Jun 26 16:06:14 2008 -0400 +++ b/src/graphics.h.in Sat Jul 05 17:30:56 2008 +0200 @@ -3486,6 +3486,8 @@ protected: public: + ~gh_manager (void); + static bool instance_ok (void) { bool retval = true; @@ -3561,6 +3563,38 @@ public: { return instance_ok () ? instance->do_figure_handle_list () : Matrix (); } + + /// Locks gh_manager instance. Use to protect property access. + /// Locking is recursive, this method can be called multiple times, and a corresponding number of unlock() calls + /// is required in order to unlock mutex. + static void lock (void) + { + if (instance_ok ()) + instance->do_lock (); + } + + /// Unlocks gh_manager instance. + ///\see lock(void) + static void unlock (void) + { + if (instance_ok ()) + instance->do_unlock (); + } + + /// Lock guard object, allows for simple RIIA locking. + class lock_guard + { + public: + lock_guard (void) + { + lock(); + } + + ~lock_guard (void) + { + unlock(); + } + }; private: @@ -3645,6 +3679,14 @@ private: { return figure_list.empty () ? graphics_handle () : figure_list.front (); } + + void do_lock (void); + + void do_unlock (void); + + void init_mutex (void); + + void cleanup_mutex (void); };