Mercurial > octave
changeset 23117:17a3567a7b01
separate final interpreter initialization from execution
* libgui_src/octave-interpreter.cc (octave_interpreter::execute):
Perform final initialization separately from execution.
* interpreter.h, interpreter.cc (interpreter::m_initialized):
New data member.
(interpreter::initialized): New function.
(interpreter::~interpreter): Always call cleanup.
(interpreter::initialize): Rename from execute_internal. Don't call
main_loop here. Protect from being called more than once. Set
m_initialized when done.
(interpreter::execute): Call initialize and main_loop here.
(interpreter::cleanup): Don't protect from recursive calls.
* octave.h, octave.cc (application::interpreter_initialized,
application::initialize_interpreter, application::delete_interpreter):
New functions.
(cli_application::execute): Also delete interpreter here.
* embedded.cc: Update example code.
author | John W. Eaton <jwe@octave.org> |
---|---|
date | Mon, 30 Jan 2017 15:13:29 -0500 |
parents | 868daa374c49 |
children | 3107d3717cc2 |
files | examples/code/embedded.cc libgui/src/octave-interpreter.cc libinterp/corefcn/interpreter.cc libinterp/corefcn/interpreter.h libinterp/octave.cc libinterp/octave.h |
diffstat | 6 files changed, 228 insertions(+), 108 deletions(-) [+] |
line wrap: on
line diff
--- a/examples/code/embedded.cc Tue Nov 15 23:10:15 2016 +0100 +++ b/examples/code/embedded.cc Mon Jan 30 15:13:29 2017 -0500 @@ -7,18 +7,47 @@ int main (void) { - octave::interpreter interpreter; - - int status = interpreter.execute (); + // Create interpreter. - if (status != 0) - { - std::cerr << "creating embedded Octave interpreter failed!" << std::endl; - return status; - } + octave::interpreter interpreter; try { + // Inhibit reading history file by calling + // + // interpreter.initialize_history (false); + + // Set custom load path here if you wish by calling + // + // interpreter.initialize_load_path (false); + + // Perform final initialization of interpreter, including + // executing commands from startup files by calling + // + // int status interpreter.initialize (); + // + // if (! interpreter.initialized ()) + // { + // std::cerr << "Octave interpreter initialization failed!" + // << std::endl; + // exit (status); + // } + // + // You may skip this step if you don't need to do do anything + // between reading the startup files and telling the interpreter + // that you are ready to execute commands. + + // Tell the interpreter that we're ready to execute commands: + + int status = interpreter.execute (); + + if (status != 0) + { + std::cerr << "creating embedded Octave interpreter failed!" + << std::endl; + return status; + } + octave_idx_type n = 2; octave_value_list in; @@ -39,7 +68,7 @@ } catch (const octave::exit_exception& ex) { - std::cerr << "Octave evaluator exited with status = " + std::cerr << "Octave interpreter exited with status = " << ex.exit_status () << std::endl; } catch (const octave::execution_exception&)
--- a/libgui/src/octave-interpreter.cc Tue Nov 15 23:10:15 2016 +0100 +++ b/libgui/src/octave-interpreter.cc Mon Jan 30 15:13:29 2017 -0500 @@ -46,9 +46,37 @@ m_app_context->create_interpreter (); - emit octave_ready_signal (); + int exit_status = 0; + + try + { + // Final initialization including executing startup files. If + // initialization fails, return the last available status from + // that process. + + exit_status = m_app_context->initialize_interpreter (); + + if (m_app_context->interpreter_initialized ()) + { + // The interpreter should be completely ready at this point so let + // the GUI know. - int exit_status = m_app_context->execute_interpreter (); + emit octave_ready_signal (); + + // Start executing commands in the command window. + + exit_status = m_app_context->execute_interpreter (); + } + } + catch (const octave::exit_exception& ex) + { + exit_status = ex.exit_status (); + } + + // Whether or not initialization succeeds we need to clean up the + // interpreter once we are done with it. + + m_app_context->delete_interpreter (); qApp->exit (exit_status); }
--- a/libinterp/corefcn/interpreter.cc Tue Nov 15 23:10:15 2016 +0100 +++ b/libinterp/corefcn/interpreter.cc Mon Jan 30 15:13:29 2017 -0500 @@ -359,11 +359,16 @@ { tree_evaluator *current_evaluator = 0; + // Create an interpreter object and perform initialization up to the + // point of setting reading command history and setting the load + // path. + interpreter::interpreter (application *app_context) : m_app_context (app_context), m_evaluator (new tree_evaluator (this)), m_interactive (false), m_read_site_files (true), m_read_init_files (m_app_context != 0), m_verbose (false), - m_inhibit_startup_message (false), m_load_path_initialized (false) + m_inhibit_startup_message (false), m_load_path_initialized (false), + m_history_initialized (false), m_initialized (false) { current_evaluator = m_evaluator; @@ -407,7 +412,7 @@ initialize_error_handlers (); - if (app_context) + if (m_app_context) octave::install_signal_handlers (); else quit_allowed = false; @@ -425,7 +430,7 @@ bool line_editing = false; bool traditional = false; - if (app_context) + if (m_app_context) { // Embedded interpeters don't execute command line options or const cmdline_options& options = m_app_context->options (); @@ -433,7 +438,7 @@ // Make all command-line arguments available to startup files, // including PKG_ADD files. - app_context->intern_argv (options.all_args ()); + m_app_context->intern_argv (options.all_args ()); bool is_octave_program = m_app_context->is_octave_program (); @@ -497,31 +502,35 @@ interpreter::~interpreter (void) { - if (! m_app_context) - cleanup (); + cleanup (); current_evaluator = 0; delete m_evaluator; } - int interpreter::execute (void) + // Read the history file unless a command-line option inhibits that. + + void interpreter::initialize_history (bool read_history_file) { - int exit_status = 0; + if (! m_history_initialized) + { + // Allow command-line option to override. - try - { - exit_status = execute_internal (); + if (m_app_context) + { + const cmdline_options& options = m_app_context->options (); + + read_history_file = options.read_history_file (); + } + + ::initialize_history (read_history_file); + + if (! m_app_context) + octave::command_history::ignore_entries (); + + m_history_initialized = true; } - catch (const octave::exit_exception& ex) - { - exit_status = ex.exit_status (); - } - - if (m_app_context) - cleanup (); - - return exit_status; } // Set the initial path to the system default unless command-line @@ -561,57 +570,42 @@ } } - void interpreter::initialize_history (bool read_history_file) - { - if (! m_history_initialized) - { - // Allow command-line option to override. - - if (m_app_context) - { - const cmdline_options& options = m_app_context->options (); + // This may be called separately from execute - read_history_file = options.read_history_file (); - } - - ::initialize_history (read_history_file); + int interpreter::initialize (void) + { + if (m_initialized) + return 0; - if (! m_app_context) - octave::command_history::ignore_entries (); - - m_history_initialized = true; - } - } - - int interpreter::execute_internal (void) - { display_startup_message (); - // Initializing the load path may execute PKG_ADD files. It also - // allows the path to be initialized between the calls to create and - // executeexecute the interpreter. + // Wait to read the history file until the interpreter reads input + // files and begins evaluating commands. + + initialize_history (); + + // Initializing the load path may execute PKG_ADD files, so can't be + // done until the interpreter is ready to execute commands. + + // Deferring it to the execute step also allows the path to be + // initialized between creating and execute the interpreter, for + // example, to set a custom path for an embedded interpreter. initialize_load_path (); - initialize_history (); + // We ignore errors in startup files. - // Don't fail, but return non-zero if there is an error in a startup - // file. + execute_startup_files (); int exit_status = 0; - int status = execute_startup_files (); - - if (status) - exit_status = status; - if (m_app_context) { const cmdline_options& options = m_app_context->options (); if (m_app_context->have_eval_option_code ()) { - status = execute_eval_option_code (); + int status = execute_eval_option_code (); if (status ) exit_status = status; @@ -626,7 +620,7 @@ if (m_app_context->have_script_file ()) { - status = execute_command_line_file (); + int status = execute_command_line_file (); if (status) exit_status = status; @@ -651,7 +645,26 @@ octave::command_editor::reset_current_command_number (1); - return main_loop (); + m_initialized = true; + + return exit_status; + } + + int interpreter::execute (void) + { + try + { + int status = initialize (); + + if (! m_initialized) + return status; + + return main_loop (); + } + catch (const octave::exit_exception& ex) + { + return ex.exit_status (); + } } void interpreter::display_startup_message (void) const @@ -1050,8 +1063,6 @@ void interpreter::cleanup (void) { - static bool deja_vu = false; - // If we are attached to a GUI, process pending events and // disconnect the link. @@ -1073,52 +1084,47 @@ OCTAVE_SAFE_CALL (octave::flush_stdout, ()); } - if (! deja_vu) - { - deja_vu = true; + // Do this explicitly so that destructors for mex file objects + // are called, so that functions registered with mexAtExit are + // called. + OCTAVE_SAFE_CALL (clear_mex_functions, ()); - // Do this explicitly so that destructors for mex file objects - // are called, so that functions registered with mexAtExit are - // called. - OCTAVE_SAFE_CALL (clear_mex_functions, ()); + OCTAVE_SAFE_CALL (octave::command_editor::restore_terminal_state, ()); - OCTAVE_SAFE_CALL (octave::command_editor::restore_terminal_state, ()); + OCTAVE_SAFE_CALL (octave_history_write_timestamp, ()); - OCTAVE_SAFE_CALL (octave_history_write_timestamp, ()); + if (! octave::command_history::ignoring_entries ()) + OCTAVE_SAFE_CALL (octave::command_history::clean_up_and_save, ()); - if (! octave::command_history::ignoring_entries ()) - OCTAVE_SAFE_CALL (octave::command_history::clean_up_and_save, ()); + OCTAVE_SAFE_CALL (gh_manager::close_all_figures, ()); - OCTAVE_SAFE_CALL (gh_manager::close_all_figures, ()); + OCTAVE_SAFE_CALL (gtk_manager::unload_all_toolkits, ()); - OCTAVE_SAFE_CALL (gtk_manager::unload_all_toolkits, ()); + OCTAVE_SAFE_CALL (close_files, ()); - OCTAVE_SAFE_CALL (close_files, ()); + OCTAVE_SAFE_CALL (cleanup_tmp_files, ()); - OCTAVE_SAFE_CALL (cleanup_tmp_files, ()); + OCTAVE_SAFE_CALL (symbol_table::cleanup, ()); - OCTAVE_SAFE_CALL (symbol_table::cleanup, ()); + OCTAVE_SAFE_CALL (sysdep_cleanup, ()); - OCTAVE_SAFE_CALL (sysdep_cleanup, ()); + OCTAVE_SAFE_CALL (octave_finalize_hdf5, ()); - OCTAVE_SAFE_CALL (octave_finalize_hdf5, ()); - - OCTAVE_SAFE_CALL (octave::flush_stdout, ()); + OCTAVE_SAFE_CALL (octave::flush_stdout, ()); - // Don't call singleton_cleanup_list::cleanup until we have the - // problems with registering/unregistering types worked out. For - // example, uncomment the following line, then use the make_int - // function from the examples directory to create an integer - // object and then exit Octave. Octave should crash with a - // segfault when cleaning up the typinfo singleton. We need some - // way to force new octave_value_X types that are created in - // .oct files to be unregistered when the .oct file shared library - // is unloaded. - // - // OCTAVE_SAFE_CALL (singleton_cleanup_list::cleanup, ()); + // Don't call singleton_cleanup_list::cleanup until we have the + // problems with registering/unregistering types worked out. For + // example, uncomment the following line, then use the make_int + // function from the examples directory to create an integer + // object and then exit Octave. Octave should crash with a + // segfault when cleaning up the typinfo singleton. We need some + // way to force new octave_value_X types that are created in + // .oct files to be unregistered when the .oct file shared library + // is unloaded. + // + // OCTAVE_SAFE_CALL (singleton_cleanup_list::cleanup, ()); - OCTAVE_SAFE_CALL (octave::chunk_buffer::clear, ()); - } + OCTAVE_SAFE_CALL (octave::chunk_buffer::clear, ()); } void interpreter::recover_from_exception (void)
--- a/libinterp/corefcn/interpreter.h Tue Nov 15 23:10:15 2016 +0100 +++ b/libinterp/corefcn/interpreter.h Mon Jan 30 15:13:29 2017 -0500 @@ -56,6 +56,9 @@ { public: + // Create an interpreter object and perform basic initialization + // up to the point of reading history and setting the load path. + interpreter (application *app_context = 0); // No copying, at least not yet... @@ -64,8 +67,32 @@ interpreter& operator = (const interpreter&) = delete; + // Clean up the interpreter object. + ~interpreter (void); + // If creating an embedded interpreter, you may inhibit reading + // the command history file by calling initialize_history with + // read_history_file = false prior to calling initialize. + + void initialize_history (bool read_history_file = false); + + // If creating an embedded interpreter, you may inhibit setting + // the default compiled-in path by calling intialize_load_path + // with set_initial_path = false prior calling initialize. After + // that, you can add directories to the load path to set up a + // custom path. + + void initialize_load_path (bool set_initial_path = true); + + // Load command line history, set the load path and execute + // startup files. May throw an exit_exception. + + int initialize (void); + + // Initialize the interpreter and execute --eval option code, + // script files, and/or interactive commands. + int execute (void); bool interactive (void) const @@ -98,9 +125,10 @@ m_inhibit_startup_message = flag; } - void initialize_load_path (bool set_initial_path = true); - - void initialize_history (bool read_history_file = false); + bool initialized (void) const + { + return m_initialized; + } static void recover_from_exception (void); @@ -112,8 +140,6 @@ static std::list<std::string> atexit_functions; - int execute_internal (void); - void display_startup_message (void) const; int execute_startup_files (void) const; @@ -144,6 +170,8 @@ bool m_load_path_initialized; bool m_history_initialized; + + bool m_initialized; }; }
--- a/libinterp/octave.cc Tue Nov 15 23:10:15 2016 +0100 +++ b/libinterp/octave.cc Mon Jan 30 15:13:29 2017 -0500 @@ -366,22 +366,41 @@ application::~application (void) { + // Delete interpreter if it still exists. + delete m_interpreter; instance = 0; } + bool application::interpreter_initialized (void) + { + return m_interpreter ? m_interpreter->initialized () : false; + } + void application::create_interpreter (void) { if (! m_interpreter) m_interpreter = new interpreter (this); } + int application::initialize_interpreter (void) + { + return m_interpreter ? m_interpreter->initialize () : -1; + } + int application::execute_interpreter (void) { return m_interpreter ? m_interpreter->execute () : -1; } + void application::delete_interpreter (void) + { + delete m_interpreter; + + m_interpreter = 0; + } + void application::init (void) { if (instance) @@ -417,7 +436,11 @@ { create_interpreter (); - return execute_interpreter (); + int status = execute_interpreter (); + + delete_interpreter (); + + return status; } }
--- a/libinterp/octave.h Tue Nov 15 23:10:15 2016 +0100 +++ b/libinterp/octave.h Mon Jan 30 15:13:29 2017 -0500 @@ -208,10 +208,16 @@ bool is_octave_program (void) const { return m_is_octave_program; } + bool interpreter_initialized (void); + virtual void create_interpreter (void); + virtual int initialize_interpreter (void); + virtual int execute_interpreter (void); + virtual void delete_interpreter (void); + virtual int execute (void) = 0; virtual bool gui_running (void) const { return false; }