diff -r d56511a02884 src/graphics.cc --- a/src/graphics.cc Thu Jun 26 16:06:14 2008 -0400 +++ b/src/graphics.cc Fri Jul 04 23:08:53 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; @@ -1275,6 +1325,8 @@ xset (const graphics_handle& h, const ca xset (const graphics_handle& h, const caseless_str& name, const octave_value& val) { + gh_manager::lock_guard guard; + graphics_object obj = gh_manager::get_object (h); obj.set (name, val); } @@ -1282,6 +1334,8 @@ static void static void xset (const graphics_handle& h, const octave_value_list& args) { + gh_manager::lock_guard guard; + if (args.length () > 0) { graphics_object obj = gh_manager::get_object (h); @@ -1293,6 +1347,8 @@ static octave_value static octave_value xget (const graphics_handle& h, const caseless_str& name) { + gh_manager::lock_guard guard; + graphics_object obj = gh_manager::get_object (h); return obj.get (name); } @@ -1302,6 +1358,8 @@ reparent (const octave_value& ov, const const std::string& property, const graphics_handle& new_parent, bool adopt = true) { + gh_manager::lock_guard guard; + graphics_handle h = octave_NaN; double val = ov.double_value (); @@ -1357,6 +1415,8 @@ static void static void adopt (const graphics_handle& p, const graphics_handle& h) { + gh_manager::lock_guard guard; + graphics_object parent_obj = gh_manager::get_object (p); parent_obj.adopt (h); @@ -1365,12 +1425,16 @@ static bool static bool is_handle (const graphics_handle& h) { + gh_manager::lock_guard guard; + return h.ok (); } static bool is_handle (double val) { + gh_manager::lock_guard guard; + graphics_handle h = gh_manager::lookup (val); return h.ok (); @@ -1379,12 +1443,16 @@ static bool static bool is_handle (const octave_value& val) { + gh_manager::lock_guard guard; + return val.is_real_scalar () && is_handle (val.double_value ()); } static bool is_figure (double val) { + gh_manager::lock_guard guard; + graphics_object obj = gh_manager::get_object (val); return obj && obj.isa ("figure"); @@ -1393,6 +1461,8 @@ static void static void xcreatefcn (const graphics_handle& h) { + gh_manager::lock_guard guard; + graphics_object obj = gh_manager::get_object (h); obj.get_properties ().execute_createfcn (); } @@ -1446,6 +1516,8 @@ base_properties::set_from_list (base_gra base_properties::set_from_list (base_graphics_object& obj, property_list& defaults) { + gh_manager::lock_guard guard; + std::string go_name = graphics_object_name (); property_list::plist_map_const_iterator p = defaults.find (go_name); @@ -1474,6 +1546,8 @@ octave_value octave_value base_properties::get (const caseless_str& name) const { + gh_manager::lock_guard guard; + octave_value retval; if (name.compare ("tag")) @@ -1530,6 +1604,8 @@ octave_value octave_value base_properties::get (bool all) const { + gh_manager::lock_guard guard; + Octave_map m; for (std::map::const_iterator it = all_props.begin (); @@ -1564,6 +1640,8 @@ void void base_properties::set (const caseless_str& name, const octave_value& val) { + gh_manager::lock_guard guard; + if (name.compare ("tag")) set_tag (val); else if (name.compare ("__modified__")) @@ -1685,6 +1763,8 @@ void void base_properties::remove_child (const graphics_handle& h) { + gh_manager::lock_guard guard; + octave_idx_type k = -1; octave_idx_type n = children.numel (); for (octave_idx_type i = 0; i < n; i++) @@ -1713,6 +1793,8 @@ void void base_properties::set_parent (const octave_value& val) { + gh_manager::lock_guard guard; + double tmp = val.double_value (); graphics_handle new_parent = octave_NaN; @@ -1759,6 +1841,8 @@ void void base_properties::update_axis_limits (const std::string& axis_type) const { + gh_manager::lock_guard guard; + graphics_object obj = gh_manager::get_object (__myhandle__); if (obj) @@ -1768,6 +1852,8 @@ void void base_properties::delete_children (void) { + gh_manager::lock_guard guard; + octave_idx_type n = children.numel (); for (octave_idx_type i = 0; i < n; i++) @@ -1788,6 +1874,8 @@ void void base_properties::update_boundingbox (void) { + gh_manager::lock_guard guard; + Matrix kids = get_children (); for (int i = 0; i < kids.numel (); i++) @@ -1803,6 +1891,8 @@ base_properties::add_listener (const cas base_properties::add_listener (const caseless_str& nm, const octave_value& v, listener_mode mode) { + gh_manager::lock_guard guard; + property p = get_property (nm); if (! error_state && p.ok ()) @@ -1897,6 +1987,7 @@ base_graphics_object::update_axis_limits { if (valid_object ()) { + gh_manager::lock_guard guard; graphics_object parent_obj = gh_manager::get_object (get_parent ()); if (parent_obj) @@ -1915,6 +2006,8 @@ void void root_figure::properties::set_currentfigure (const octave_value& v) { + gh_manager::lock_guard guard; + graphics_handle val (v); if (error_state) @@ -1933,6 +2026,8 @@ void void root_figure::properties::set_callbackobject (const octave_value& v) { + gh_manager::lock_guard guard; + graphics_handle val (v); if (error_state) @@ -1968,6 +2063,8 @@ void void figure::properties::set_currentaxes (const octave_value& v) { + gh_manager::lock_guard guard; + graphics_handle val (v); if (error_state) @@ -2001,6 +2098,8 @@ figure::properties::close (bool pop) if (pop) { + gh_manager::lock_guard guard; + gh_manager::pop_figure (__myhandle__); graphics_handle cf = gh_manager::current_figure (); @@ -2012,6 +2111,8 @@ Matrix Matrix figure::properties::get_boundingbox (bool) const { + gh_manager::lock_guard guard; + graphics_backend b = get_backend (); // FIXME: screen size should be obtained from root object Matrix screen_size = b.get_screen_size (); @@ -2030,6 +2131,8 @@ void void figure::properties::set_boundingbox (const Matrix& bb) { + gh_manager::lock_guard guard; + graphics_backend b = get_backend (); // FIXME: screen size should be obtained from root object Matrix screen_size = b.get_screen_size (); @@ -2120,6 +2223,8 @@ void void axes::properties::set_title (const octave_value& v) { + gh_manager::lock_guard guard; + graphics_handle val = ::reparent (v, "set", "title", __myhandle__, false); if (! error_state) @@ -2132,6 +2237,8 @@ void void axes::properties::set_xlabel (const octave_value& v) { + gh_manager::lock_guard guard; + graphics_handle val = ::reparent (v, "set", "xlabel", __myhandle__, false); if (! error_state) @@ -2144,6 +2251,8 @@ void void axes::properties::set_ylabel (const octave_value& v) { + gh_manager::lock_guard guard; + graphics_handle val = ::reparent (v, "set", "ylabel", __myhandle__, false); if (! error_state) @@ -2156,6 +2265,8 @@ void void axes::properties::set_zlabel (const octave_value& v) { + gh_manager::lock_guard guard; + graphics_handle val = ::reparent (v, "set", "zlabel", __myhandle__, false); if (! error_state) @@ -2169,6 +2280,8 @@ axes::properties::set_defaults (base_gra axes::properties::set_defaults (base_graphics_object& obj, const std::string& mode) { + gh_manager::lock_guard guard; + title = graphics_handle (); box = "on"; key = "off"; @@ -2290,6 +2403,8 @@ graphics_handle graphics_handle axes::properties::get_title (void) const { + gh_manager::lock_guard guard; + if (! title.handle_value ().ok ()) title = gh_manager::make_graphics_handle ("text", __myhandle__); @@ -2299,6 +2414,8 @@ graphics_handle graphics_handle axes::properties::get_xlabel (void) const { + gh_manager::lock_guard guard; + if (! xlabel.handle_value ().ok ()) xlabel = gh_manager::make_graphics_handle ("text", __myhandle__); @@ -2308,6 +2425,8 @@ graphics_handle graphics_handle axes::properties::get_ylabel (void) const { + gh_manager::lock_guard guard; + if (! ylabel.handle_value ().ok ()) ylabel = gh_manager::make_graphics_handle ("text", __myhandle__); @@ -2317,6 +2436,8 @@ graphics_handle graphics_handle axes::properties::get_zlabel (void) const { + gh_manager::lock_guard guard; + if (! zlabel.handle_value ().ok ()) zlabel = gh_manager::make_graphics_handle ("text", __myhandle__); @@ -2326,6 +2447,8 @@ void void axes::properties::remove_child (const graphics_handle& h) { + gh_manager::lock_guard guard; + if (title.handle_value ().ok () && h == title.handle_value ()) title = gh_manager::make_graphics_handle ("text", __myhandle__); else if (xlabel.handle_value ().ok () && h == xlabel.handle_value ()) @@ -2341,6 +2464,8 @@ void void axes::properties::delete_children (void) { + gh_manager::lock_guard guard; + base_properties::delete_children (); gh_manager::free (title.handle_value ()); @@ -2493,6 +2618,8 @@ void void axes::properties::update_camera (void) { + gh_manager::lock_guard guard; + double xd = (xdir_is ("normal") ? 1 : -1); double yd = (ydir_is ("normal") ? 1 : -1); double zd = (zdir_is ("normal") ? 1 : -1); @@ -2709,6 +2836,8 @@ void void axes::properties::update_aspectratios (void) { + gh_manager::lock_guard guard; + Matrix xlimits = get_xlim ().matrix_value (); Matrix ylimits = get_ylim ().matrix_value (); Matrix zlimits = get_zlim ().matrix_value (); @@ -2753,6 +2882,8 @@ Matrix Matrix axes::properties::get_boundingbox (bool internal) const { + gh_manager::lock_guard guard; + graphics_object obj = gh_manager::get_object (get_parent ()); Matrix parent_bb = obj.get_properties ().get_boundingbox (true); Matrix pos = (internal ? @@ -2818,6 +2949,8 @@ axes::get_default (const caseless_str& n if (retval.is_undefined ()) { + gh_manager::lock_guard guard; + graphics_handle parent = get_parent (); graphics_object parent_obj = gh_manager::get_object (parent); @@ -3071,6 +3204,8 @@ get_children_limits (double& min_val, do get_children_limits (double& min_val, double& max_val, double& min_pos, const Matrix& kids, char limit_type) { + gh_manager::lock_guard guard; + octave_idx_type n = kids.numel (); switch (limit_type) @@ -3418,6 +3553,8 @@ void void surface::properties::update_normals (void) { + gh_manager::lock_guard guard; + if (normalmode_is ("auto")) { Matrix x = get_xdata ().matrix_value (); @@ -3571,6 +3708,8 @@ octave_value octave_value base_graphics_object::get_default (const caseless_str& name) const { + gh_manager::lock_guard guard; + graphics_handle parent = get_parent (); graphics_object parent_obj = gh_manager::get_object (parent); @@ -3591,10 +3730,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 +3840,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 +3892,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 +3964,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; @@ -3866,6 +4017,8 @@ make_graphics_object (const std::string& make_graphics_object (const std::string& go_name, const octave_value_list& args) { + gh_manager::lock_guard guard; + octave_value retval; double val = octave_NaN; @@ -3936,6 +4089,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 +4219,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 +4269,8 @@ Undocumented internal function.\n\ Undocumented internal function.\n\ @end deftypefn") { + gh_manager::lock_guard guard; + octave_value retval; int nargin = args.length (); @@ -4354,6 +4513,8 @@ addlistener (gcf, \"position\", @{@@my_l if (gh.ok ()) { + gh_manager::lock_guard guard; + graphics_object go = gh_manager::get_object (gh); go.add_property_listener (pname, args(2), POSTSET); @@ -4446,6 +4607,8 @@ addproperty (\"my_style\", gcf, \"lineli if (! error_state) { + gh_manager::lock_guard guard; + graphics_handle gh = gh_manager::lookup (h); if (gh.ok ()) @@ -4490,6 +4653,8 @@ get_property_from_handle (double handle, get_property_from_handle (double handle, const std::string& property, const std::string& func) { + gh_manager::lock_guard guard; + graphics_object obj = gh_manager::get_object (handle); octave_value retval; @@ -4508,6 +4673,8 @@ set_property_in_handle (double handle, c set_property_in_handle (double handle, const std::string& property, const octave_value& arg, const std::string& func) { + gh_manager::lock_guard guard; + graphics_object obj = gh_manager::get_object (handle); int ret = false; 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 Fri Jul 04 23:08:53 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); };