# HG changeset patch # User John W. Eaton # Date 1216295930 14400 # Node ID 78400fde223eb1b06b31a840fa1808d340705d2f # Parent 85d6296d51e12dba384a208000e3a1a104a4219d Support for backend-to-octave event management diff -r 85d6296d51e1 -r 78400fde223e liboctave/ChangeLog --- a/liboctave/ChangeLog Wed Jul 16 14:28:48 2008 -0400 +++ b/liboctave/ChangeLog Thu Jul 17 07:58:50 2008 -0400 @@ -1,3 +1,18 @@ +2008-07-16 John W. Eaton + + * oct-mutex.h (octave_autolock::octave_autolock (void), + octave_autolock (const octave_autolock&), + octave_autolock::operator = (const octave_autolock&)): + Delete definitions. + +2008-07-16 Michael Goffioul + + * cmd-edit.cc (event_hook_lock): New static mutex variable. + (command_editor::event_handler): Lock and copy event_hook_set before + executing handlers. + (command_editor::add_event_hook, command_editor::remove_event_hook): + Autolock event_hook_lock. + 2008-07-15 Michael Goffioul * oct-mutex.h, oct-mutex.cc: New files. diff -r 85d6296d51e1 -r 78400fde223e liboctave/cmd-edit.cc --- a/liboctave/cmd-edit.cc Wed Jul 16 14:28:48 2008 -0400 +++ b/liboctave/cmd-edit.cc Thu Jul 17 07:58:50 2008 -0400 @@ -45,6 +45,7 @@ #include "lo-error.h" #include "lo-utils.h" #include "oct-env.h" +#include "oct-mutex.h" #include "oct-time.h" command_editor *command_editor::instance = 0; @@ -53,6 +54,8 @@ std::set command_editor::event_hook_set; +static octave_mutex event_hook_lock; + #if defined (USE_READLINE) #include @@ -852,8 +855,14 @@ int command_editor::event_handler (void) { - for (event_hook_set_iterator p = event_hook_set.begin (); - p != event_hook_set.end (); p++) + event_hook_lock.lock (); + + std::set hook_set (event_hook_set); + + event_hook_lock.unlock (); + + for (event_hook_set_iterator p = hook_set.begin (); + p != hook_set.end (); p++) { event_hook_fcn f = *p; @@ -1160,6 +1169,8 @@ void command_editor::add_event_hook (event_hook_fcn f) { + octave_autolock guard (event_hook_lock); + if (instance_ok ()) { event_hook_set.insert (f); @@ -1171,6 +1182,8 @@ void command_editor::remove_event_hook (event_hook_fcn f) { + octave_autolock guard (event_hook_lock); + if (instance_ok ()) { event_hook_set_iterator p = event_hook_set.find (f); diff -r 85d6296d51e1 -r 78400fde223e liboctave/oct-mutex.h --- a/liboctave/oct-mutex.h Wed Jul 16 14:28:48 2008 -0400 +++ b/liboctave/oct-mutex.h Thu Jul 17 07:58:50 2008 -0400 @@ -93,9 +93,11 @@ } private: - octave_autolock (void) { } - octave_autolock (const octave_autolock&) { } - octave_autolock& operator = (const octave_autolock&) { } + + // No copying or default constructor! + octave_autolock (void); + octave_autolock (const octave_autolock&); + octave_autolock& operator = (const octave_autolock&); private: octave_mutex mutex; diff -r 85d6296d51e1 -r 78400fde223e src/ChangeLog --- a/src/ChangeLog Wed Jul 16 14:28:48 2008 -0400 +++ b/src/ChangeLog Thu Jul 17 07:58:50 2008 -0400 @@ -1,3 +1,53 @@ +2008-07-16 John W. Eaton + + * graphics.h.in (gh_manager::autolock): Delete copy constructor + and assignment definitions. + +2008-07-16 Michael Goffioul + + * graphics.h.in (callback_property::execute): Remove static version. + (base_properties::is_hittest, base_properties::is_interruptible, + base_properties::is_selected, base_properties::is_selectionhighlight): + New convenience property accessors. + (base_graphics_object::get_handle, graphics_object::get_handle): Idem. + (gh_manager::graphics_lock): New global mutex + (gh_manager::lock, gh_manager::unlock, gh_manager::do_lock, + gh_manager::do_unlock): Add accessors for it. + (gh_manager::autolock): New class for easy locking of the graphics + system. + (gh_manager::event_data): New class for event management. + (gh_manager::event_queue): New object to hold pending events. + (gh_manager::callback_objects): New stack of callback objects. + (gh_manager::execute_callback, gh_manager:post_callback, + gh_manager::post_function, gh_manager::post_set, + gh_manager::process_events, gh_manager::flush_events, + gh_manager::restore_gcbo): New static methods for event management. + (gh_manager::do_execute_callback, gh_manager::do_post_callback, + gh_manager::do_post_function, gh_manager::do_post_set, + gh_manager::do_process_events, gh_manager::do_post_event, + gh_manager::do_restore_gcbo): New non-static versions. + * graphics.cc (xreset_gcbo): Remove. + (execute_callback): Likewise. + (base_property::run_listeners, callback_property::execute): Use + gh_manager::execute_callback. + (class callback_event_data, class function_event_data, class + set_event_data): New classes to implement various types of events. + (gh_manager::event_data::create_callback_event, + gh_manager::event_data::create_function_event, + gh_manager::event_data::create_set_event): Implement event factory + methods. + (gh_manager::do_restore_gcbo, gh_manager::do_execute_callback, + gh_manager::do_post_event, gh_manager::do_post_callback, + gh_manager::do_post_function, gh_manager::do_post_set, + gh_manager::do_process_events): New methods for event management. + (Fishandle, Fset, Fget, F__get__, F__go_figure__, F__go_delete__, + F__go_axes_init__, F__go_handles__, F__go_figure_handles__, + Favailable_backends, Fdrawnow, Faddlistener, Faddproperty, + get_property_from_handle, set_property_in_handle): Lock graphics + system. + (GO_BODY): Likewise. + (Fdrawnow): Support single "expose" argument. + 2008-07-15 John W. Eaton * DLD-FUNCTIONS/__convn__.cc (convn): Cast second arg to diff -r 85d6296d51e1 -r 78400fde223e src/graphics.cc --- a/src/graphics.cc Wed Jul 16 14:28:48 2008 -0400 +++ b/src/graphics.cc Thu Jul 17 07:58:50 2008 -0400 @@ -37,6 +37,7 @@ #include "file-ops.h" #include "file-stat.h" +#include "cmd-edit.h" #include "defun.h" #include "error.h" #include "graphics.h" @@ -172,83 +173,6 @@ return m; } -static void -xset_gcbo (const graphics_handle& h) -{ - graphics_object go = gh_manager::get_object (0); - root_figure::properties& props = - dynamic_cast (go.get_properties ()); - - props.set_callbackobject (h.as_octave_value ()); -} - -static void -xreset_gcbo (void *) -{ - xset_gcbo (graphics_handle ()); -} - -static void -execute_callback (const octave_value& cb_arg, const graphics_handle& h, - const octave_value& data) -{ - octave_value_list args; - octave_function *fcn = 0; - - args(0) = h.as_octave_value (); - if (data.is_defined ()) - args(1) = data; - else - args(1) = Matrix (); - - unwind_protect::begin_frame ("execute_callback"); - unwind_protect::add (xreset_gcbo); - - xset_gcbo (h); - - BEGIN_INTERRUPT_WITH_EXCEPTIONS; - - // Copy CB because "function_value" method is non-const. - - octave_value cb = cb_arg; - - if (cb.is_function_handle ()) - fcn = cb.function_value (); - else if (cb.is_string ()) - { - int status; - std::string s = cb.string_value (); - - eval_string (s, false, status); - } - else if (cb.is_cell () && cb.length () > 0 - && (cb.rows () == 1 || cb.columns () == 1) - && cb.cell_value ()(0).is_function_handle ()) - { - Cell c = cb.cell_value (); - - fcn = c(0).function_value (); - if (! error_state) - { - for (int i = 0; i < c.length () ; i++) - args(2+i) = c(i); - } - } - else - { - std::string nm = cb.class_name (); - error ("trying to execute non-executable object (class = %s)", - nm.c_str ()); - } - - if (fcn && ! error_state) - feval (fcn, args); - - END_INTERRUPT_WITH_EXCEPTIONS; - - unwind_protect::run_frame ("execute_callback"); -} - static Matrix convert_position (const Matrix& pos, const caseless_str& from_units, const caseless_str& to_units, @@ -541,7 +465,7 @@ for (int i = 0; i < l.length (); i++) { - execute_callback (l(i), parent, octave_value ()); + gh_manager::execute_callback (parent, l(i), octave_value ()); if (error_state) break; @@ -829,15 +753,7 @@ callback_property::execute (const octave_value& data) const { if (callback.is_defined () && ! callback.is_empty ()) - execute_callback (callback, get_parent (), data); -} - -void -callback_property::execute (const octave_value& cb, const graphics_handle& h, - const octave_value& data) -{ - if (cb.is_defined () && ! cb.is_empty ()) - execute_callback (cb, h, data); + gh_manager::execute_callback (get_parent (), callback, data); } // Used to cache dummy graphics objects from which dynamic @@ -3649,6 +3565,323 @@ } } +class +callback_event_data : public gh_manager::event_data +{ +public: + callback_event_data (const graphics_handle& h, const std::string& name, + const octave_value& data = Matrix ()) + : gh_manager::event_data (0), handle (h), callback_name (name), + callback_data (data) { } + + void execute (void) + { + gh_manager::execute_callback (handle, callback_name, callback_data); + } + +private: + callback_event_data (void) + : gh_manager::event_data (0) { } + +private: + graphics_handle handle; + std::string callback_name; + octave_value callback_data; +}; + +class +function_event_data : public gh_manager::event_data +{ +public: + function_event_data (gh_manager::event_fcn fcn, void* data = 0) + : gh_manager::event_data (0), function (fcn), + function_data (data) { } + + void execute (void) + { + function (function_data); + } + +private: + function_event_data (void) + : gh_manager::event_data (0) { } + +private: + gh_manager::event_fcn function; + void* function_data; +}; + +class +set_event_data : public gh_manager::event_data +{ +public: + set_event_data (const graphics_handle& h, const std::string& name, + const octave_value& value) + : gh_manager::event_data (0), handle (h), property_name (name), + property_value (value) { } + + void execute (void) + { + gh_manager::autolock guard; + + xset (handle, property_name, property_value); + } + +private: + set_event_data (void) + : gh_manager::event_data (0) { } + +private: + graphics_handle handle; + std::string property_name; + octave_value property_value; +}; + +gh_manager::event_data +gh_manager::event_data::create_callback_event (const graphics_handle& h, + const std::string& name, + const octave_value& data) +{ + event_data e; + + e.rep = new callback_event_data (h, name, data); + + e.rep->refcount++; + + return e; +} + +gh_manager::event_data +gh_manager::event_data::create_function_event (gh_manager::event_fcn fcn, + void *data) +{ + event_data e; + + e.rep =new function_event_data (fcn, data); + + e.rep->refcount++; + + return e; +} + +gh_manager::event_data +gh_manager::event_data::create_set_event (const graphics_handle& h, + const std::string& name, + const octave_value& data) +{ + event_data e; + + e.rep = new set_event_data (h, name, data); + + e.rep->refcount++; + + return e; +} + +static void +xset_gcbo (const graphics_handle& h) +{ + graphics_object go = gh_manager::get_object (0); + root_figure::properties& props = + dynamic_cast (go.get_properties ()); + + props.set_callbackobject (h.as_octave_value ()); +} + +void +gh_manager::do_restore_gcbo (void) +{ + gh_manager::autolock guard; + + callback_objects.pop_front (); + + xset_gcbo (callback_objects.empty () + ? graphics_handle () + : callback_objects.front ().get_handle ()); +} + +void +gh_manager::do_execute_callback (const graphics_handle& h, + const octave_value& cb_arg, + const octave_value& data) +{ + octave_value_list args; + octave_function *fcn = 0; + + args(0) = h.as_octave_value (); + if (data.is_defined ()) + args(1) = data; + else + args(1) = Matrix (); + + unwind_protect::begin_frame ("execute_callback"); + unwind_protect::add (gh_manager::restore_gcbo); + + if (true) + { + gh_manager::autolock guard; + + callback_objects.push_front (get_object (h)); + xset_gcbo (h); + } + + BEGIN_INTERRUPT_WITH_EXCEPTIONS; + + // Copy CB because "function_value" method is non-const. + + octave_value cb = cb_arg; + + if (cb.is_function_handle ()) + fcn = cb.function_value (); + else if (cb.is_string ()) + { + int status; + std::string s = cb.string_value (); + + eval_string (s, false, status); + } + else if (cb.is_cell () && cb.length () > 0 + && (cb.rows () == 1 || cb.columns () == 1) + && cb.cell_value ()(0).is_function_handle ()) + { + Cell c = cb.cell_value (); + + fcn = c(0).function_value (); + if (! error_state) + { + for (int i = 0; i < c.length () ; i++) + args(2+i) = c(i); + } + } + else + { + std::string nm = cb.class_name (); + error ("trying to execute non-executable object (class = %s)", + nm.c_str ()); + } + + if (fcn && ! error_state) + feval (fcn, args); + + END_INTERRUPT_WITH_EXCEPTIONS; + + unwind_protect::run_frame ("execute_callback"); +} + +void +gh_manager::do_post_event (const event_data& e) +{ + event_queue.push_back (e); + + command_editor::add_event_hook (gh_manager::process_events); +} + +void +gh_manager::do_post_callback (const graphics_handle& h, const std::string name, + const octave_value& data) +{ + gh_manager::autolock guard; + + graphics_object go = get_object (h); + + if (go.valid_object ()) + { + if (callback_objects.empty ()) + do_post_event (event_data::create_callback_event (h, name, data)); + else + { + const graphics_object& current = callback_objects.front (); + + if (current.get_properties ().is_interruptible ()) + do_post_event (event_data::create_callback_event (h, name, data)); + else + { + caseless_str busy_action (go.get_properties ().get_busyaction ()); + + if (busy_action.compare ("queue")) + do_post_event (event_data::create_callback_event (h, name, data)); + else + { + caseless_str cname (name); + + if (cname.compare ("deletefcn") + || cname.compare ("createfcn") + || (go.isa ("figure") + && (cname.compare ("closerequestfcn") + || cname.compare ("resizefcn")))) + do_post_event (event_data::create_callback_event (h, name, data)); + } + } + } + } +} + +void +gh_manager::do_post_function (event_fcn fcn, void* fcn_data) +{ + gh_manager::autolock guard; + + do_post_event (event_data::create_function_event (fcn, fcn_data)); +} + +void +gh_manager::do_post_set (const graphics_handle& h, const std::string name, + const octave_value& value) +{ + gh_manager::autolock guard; + + do_post_event (event_data::create_set_event (h, name, value)); +} + +int +gh_manager::do_process_events (bool force) +{ + event_data e; + + do + { + e = event_data (); + + gh_manager::lock (); + + if (! event_queue.empty ()) + { + if (callback_objects.empty () || force) + { + e = event_queue.front (); + + event_queue.pop_front (); + } + else + { + const graphics_object& go = callback_objects.front (); + + if (go.get_properties ().is_interruptible ()) + { + e = event_queue.front (); + + event_queue.pop_front (); + } + } + } + + gh_manager::unlock (); + + if (e.ok ()) + e.execute (); + } + while (e.ok ()); + + gh_manager::lock (); + + if (event_queue.empty ()) + command_editor::remove_event_hook (gh_manager::process_events); + + gh_manager::unlock (); + + return 0; +} + property_list::plist_map_type root_figure::init_factory_properties (void) { @@ -3674,6 +3907,8 @@ Return true if @var{h} is a graphics handle and false otherwise.\n\ @end deftypefn") { + gh_manager::autolock guard; + octave_value retval; if (args.length () == 1) @@ -3691,6 +3926,8 @@ for the graphics handle @var{h}.\n\ @end deftypefn") { + gh_manager::autolock guard; + octave_value retval; int nargin = args.length (); @@ -3741,6 +3978,8 @@ values or lists respectively.\n\ @end deftypefn") { + gh_manager::autolock guard; + octave_value retval; octave_value_list vlist; @@ -3811,6 +4050,8 @@ values or lists respectively.\n\ @end deftypefn") { + gh_manager::autolock guard; + octave_value retval; octave_value_list vlist; @@ -3932,6 +4173,8 @@ Undocumented internal function.\n\ @end deftypefn") { + gh_manager::autolock guard; + octave_value retval; if (args.length () > 0) @@ -3982,6 +4225,8 @@ } #define GO_BODY(TYPE) \ + gh_manager::autolock guard; \ + \ octave_value retval; \ \ if (args.length () > 0) \ @@ -4060,6 +4305,8 @@ Undocumented internal function.\n\ @end deftypefn") { + gh_manager::autolock guard; + octave_value_list retval; if (args.length () == 1) @@ -4108,6 +4355,8 @@ Undocumented internal function.\n\ @end deftypefn") { + gh_manager::autolock guard; + octave_value retval; int nargin = args.length (); @@ -4156,6 +4405,8 @@ Undocumented internal function.\n\ @end deftypefn") { + gh_manager::autolock guard; + return octave_value (gh_manager::handle_list ()); } @@ -4165,6 +4416,8 @@ Undocumented internal function.\n\ @end deftypefn") { + gh_manager::autolock guard; + return octave_value (gh_manager::figure_handle_list ()); } @@ -4174,6 +4427,8 @@ Returns resgistered graphics backends.\n\ @end deftypefn") { + gh_manager::autolock guard; + return octave_value (graphics_backend::available_backends_list ()); } @@ -4195,6 +4450,8 @@ octave_value retval; + gh_manager::lock (); + unwind_protect::begin_frame ("Fdrawnow"); unwind_protect::add (clear_drawnow_request); @@ -4209,7 +4466,7 @@ __go_close_all_registered__ = true; } - if (args.length () == 0) + if (args.length () == 0 || args.length () == 1) { Matrix hlist = gh_manager::figure_handle_list (); @@ -4225,7 +4482,13 @@ if (fprops.is_modified ()) { if (fprops.is_visible ()) - fprops.get_backend ().redraw_figure (h); + { + gh_manager::unlock (); + + fprops.get_backend ().redraw_figure (h); + + gh_manager::lock (); + } else if (! fprops.get___plot_stream__ ().is_empty ()) { fprops.close (false); @@ -4236,6 +4499,27 @@ } } } + + bool do_events = true; + + if (args.length () == 1) + { + caseless_str val (args(0).string_value ()); + + if (! error_state && val.compare ("expose")) + do_events = false; + else + error ("drawnow: invalid argument, expected `expose' as argument"); + } + + if (do_events) + { + gh_manager::unlock (); + + gh_manager::process_events (); + + gh_manager::lock (); + } } else if (args.length () >= 2 && args.length () <= 4) { @@ -4276,8 +4560,12 @@ { graphics_object go = gh_manager::get_object (h); + gh_manager::unlock (); + go.get_backend () .print_figure (h, term, file, mono, debug_file); + + gh_manager::lock (); } else error ("drawnow: nothing to draw"); @@ -4300,6 +4588,8 @@ unwind_protect::run_frame ("Fdrawnow"); + gh_manager::unlock (); + return retval; } @@ -4334,6 +4624,8 @@ \n\ @end deftypefn") { + gh_manager::autolock guard; + octave_value retval; if (args.length () == 3) @@ -4430,6 +4722,8 @@ \n\ @end deftypefn") { + gh_manager::autolock guard; + octave_value retval; if (args.length () >= 3) @@ -4486,6 +4780,8 @@ get_property_from_handle (double handle, const std::string& property, const std::string& func) { + gh_manager::autolock guard; + graphics_object obj = gh_manager::get_object (handle); octave_value retval; @@ -4504,6 +4800,8 @@ set_property_in_handle (double handle, const std::string& property, const octave_value& arg, const std::string& func) { + gh_manager::autolock guard; + graphics_object obj = gh_manager::get_object (handle); int ret = false; diff -r 85d6296d51e1 -r 78400fde223e src/graphics.h.in --- a/src/graphics.h.in Wed Jul 16 14:28:48 2008 -0400 +++ b/src/graphics.h.in Thu Jul 17 07:58:50 2008 -0400 @@ -37,6 +37,7 @@ #include "gripes.h" #include "oct-map.h" +#include "oct-mutex.h" #include "ov.h" class caseless_str : public std::string @@ -1124,11 +1125,6 @@ OCTINTERP_API void execute (const octave_value& data = octave_value ()) const; - OCTINTERP_API static - void execute (const octave_value& cb, const graphics_handle& h, - const octave_value& data = octave_value ()); - - callback_property& operator = (const octave_value& val) { set (val); @@ -1566,12 +1562,16 @@ std::string get_handlevisibility (void) const { return handlevisibility.current_value (); } + bool is_hittest (void) const { return hittest.is_on (); } std::string get_hittest (void) const { return hittest.current_value (); } + bool is_interruptible (void) const { return interruptible.is_on (); } std::string get_interruptible (void) const { return interruptible.current_value (); } + bool is_selected (void) const { return selected.is_on (); } std::string get_selected (void) const { return selected.current_value (); } + bool is_selectionhighlight (void) const { return selectionhighlight.is_on (); } std::string get_selectionhighlight (void) const { return selectionhighlight.current_value (); } octave_value get_uicontextmenu (void) const { return uicontextmenu.get (); } @@ -1899,6 +1899,17 @@ } } + graphics_handle get_handle (void) const + { + if (valid_object ()) + return get_properties ().get___myhandle__ (); + else + { + error ("base_graphics_object::get_handle: invalid graphics object"); + return graphics_handle (); + } + } + virtual void remove_child (const graphics_handle& h) { if (valid_object ()) @@ -2068,6 +2079,8 @@ graphics_handle get_parent (void) const { return rep->get_parent (); } + graphics_handle get_handle (void) const { return rep->get_handle (); } + void remove_child (const graphics_handle& h) { rep->remove_child (h); } void adopt (const graphics_handle& h) { rep->adopt (h); } @@ -3486,6 +3499,8 @@ public: + typedef void (*event_fcn) (void*); + static bool instance_ok (void) { bool retval = true; @@ -3557,11 +3572,160 @@ return instance_ok () ? instance->do_handle_list () : Matrix (); } + static void lock (void) + { + if (instance_ok ()) + instance->do_lock (); + } + + static void unlock (void) + { + if (instance_ok ()) + instance->do_unlock (); + } + static Matrix figure_handle_list (void) { return instance_ok () ? instance->do_figure_handle_list () : Matrix (); } + static void execute_callback (const graphics_handle& h, + const std::string& name, + const octave_value& data = Matrix ()) + { + graphics_object go = get_object (h); + + if (go.valid_object ()) + { + octave_value cb = go.get (name); + + if (! error_state) + execute_callback (h, cb, data); + } + } + + static void execute_callback (const graphics_handle& h, + const octave_value& cb, + const octave_value& data = Matrix ()) + { + if (instance_ok ()) + instance->do_execute_callback (h, cb, data); + } + + static void post_callback (const graphics_handle& h, + const std::string& name, + const octave_value& data = Matrix ()) + { + if (instance_ok ()) + instance->do_post_callback (h, name, data); + } + + static void post_function (event_fcn fcn, void* data = 0) + { + if (instance_ok ()) + instance->do_post_function (fcn, data); + } + + static void post_set (const graphics_handle& h, + const std::string& name, + const octave_value& value) + { + if (instance_ok ()) + instance->do_post_set (h, name, value); + } + + static int process_events (void) + { + return (instance_ok () ? instance->do_process_events () : 0); + } + + static int flush_events (void) + { + return (instance_ok () ? instance->do_process_events (true) : 0); + } + +public: + class autolock + { + public: + autolock (void) { lock (); } + + ~autolock (void) { unlock (); } + + private: + + // No copying! + autolock (const autolock&); + autolock& operator = (const autolock&); + }; + +public: + class event_data + { + public: + event_data (void) : rep (0) { } + + event_data (const event_data& d) + { + rep = d.rep; + if (rep) + rep->refcount++; + } + + virtual ~event_data (void) + { + if (rep && --rep->refcount == 0) + { + delete rep; + rep = 0; + } + } + + event_data& operator = (const event_data& d) + { + if (d.rep != rep) + { + if (rep && --rep->refcount == 0) + delete rep; + + rep = d.rep; + if (rep) + rep->refcount++; + } + + return *this; + } + + virtual void execute (void) + { if (rep) rep->execute (); } + + bool ok (void) const { return (rep != 0); } + + static event_data + create_callback_event (const graphics_handle& h, + const std::string& name, + const octave_value& data = Matrix ()); + + static event_data + create_function_event (event_fcn fcn, void *data = 0); + + static event_data + create_set_event (const graphics_handle& h, + const std::string& name, + const octave_value& value); + + protected: + explicit event_data (int /* dummy */) + : refcount (0) { } + + private: + union + { + event_data *rep; + int refcount; + }; + }; + private: static gh_manager *instance; @@ -3588,6 +3752,15 @@ // created. std::list figure_list; + // The lock for accessing the graphics sytsem + octave_mutex graphics_lock; + + // The list of event queued by backends + std::list event_queue; + + // The stack of callback objects + std::list callback_objects; + graphics_handle get_handle (const std::string& go_name); void do_free (const graphics_handle& h); @@ -3645,6 +3818,33 @@ { return figure_list.empty () ? graphics_handle () : figure_list.front (); } + + void do_lock (void) { graphics_lock.lock (); } + + void do_unlock (void) { graphics_lock.unlock (); } + + void do_execute_callback (const graphics_handle& h, const octave_value& cb, + const octave_value& data); + + void do_post_callback (const graphics_handle& h, const std::string name, + const octave_value& data); + + void do_post_function (event_fcn fcn, void* fcn_data); + + void do_post_set (const graphics_handle& h, const std::string name, + const octave_value& value); + + int do_process_events (bool force = false); + + static void restore_gcbo (void*) + { + if (instance_ok ()) + instance->do_restore_gcbo (); + } + + void do_restore_gcbo (void); + + void do_post_event (const event_data& e); };