quit.h

Go to the documentation of this file.
00001 /*
00002 
00003 Copyright (C) 2002-2012 John W. Eaton
00004 
00005 This file is part of Octave.
00006 
00007 Octave is free software; you can redistribute it and/or modify it
00008 under the terms of the GNU General Public License as published by the
00009 Free Software Foundation; either version 3 of the License, or (at your
00010 option) any later version.
00011 
00012 Octave is distributed in the hope that it will be useful, but WITHOUT
00013 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
00014 FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
00015 for more details.
00016 
00017 You should have received a copy of the GNU General Public License
00018 along with Octave; see the file COPYING.  If not, see
00019 <http://www.gnu.org/licenses/>.
00020 
00021 */
00022 
00023 #if !defined (octave_quit_h)
00024 #define octave_quit_h 1
00025 
00026 #ifdef __cplusplus
00027 #include <new>
00028 extern "C" {
00029 #endif
00030 
00031 #include <stdio.h>
00032 
00033 #include <signal.h>
00034 #include <setjmp.h>
00035 
00036 #if defined (__WIN32__) && ! defined (_POSIX_VERSION)
00037 
00038 #define WIN32_LEAN_AND_MEAN
00039 #include <windows.h>
00040 
00041 CRUFT_API extern void w32_sigint_init (void);   /* setup */
00042 CRUFT_API extern void w32_raise_final (void);   /* tear down */
00043 CRUFT_API extern void w32_raise (int sig);      /* raise signal in main thread */
00044 CRUFT_API extern int w32_in_main_thread (void); /* return true if in main thread */
00045 
00046 #endif
00047 
00048 #if defined (OCTAVE_HAVE_SIG_JUMP)
00049 
00050 typedef sigjmp_buf octave_jmp_buf;
00051 
00052 #define octave_set_current_context sigsetjmp (current_context, 1)
00053 
00054 #else
00055 
00056 typedef jmp_buf octave_jmp_buf;
00057 
00058 #define octave_set_current_context setjmp (current_context)
00059 
00060 #endif
00061 
00062 CRUFT_API extern octave_jmp_buf current_context;
00063 
00064 CRUFT_API extern void octave_save_current_context (void *);
00065 
00066 CRUFT_API extern void octave_restore_current_context (void *);
00067 
00068 CRUFT_API extern void octave_jump_to_enclosing_context (void) GCC_ATTR_NORETURN;
00069 
00070 CRUFT_API extern void octave_save_signal_mask (void);
00071 
00072 CRUFT_API extern void octave_restore_signal_mask (void);
00073 
00074 #ifdef __cplusplus
00075 class
00076 octave_execution_exception
00077 {
00078 };
00079 
00080 class
00081 octave_interrupt_exception
00082 {
00083 };
00084 #endif
00085 
00086 enum octave_exception
00087 {
00088   octave_no_exception = 0,
00089   octave_exec_exception = 1,
00090   octave_alloc_exception = 2
00091 };
00092 
00093 CRUFT_API extern sig_atomic_t octave_interrupt_immediately;
00094 
00095 /*
00096   > 0: interrupt pending
00097     0: no interrupt pending
00098   < 0: handling interrupt
00099 */
00100 CRUFT_API extern sig_atomic_t octave_interrupt_state;
00101 
00102 CRUFT_API extern sig_atomic_t octave_exception_state;
00103 
00104 CRUFT_API extern volatile sig_atomic_t octave_signal_caught;
00105 
00106 CRUFT_API extern void octave_handle_signal (void);
00107 
00108 CRUFT_API extern void octave_throw_interrupt_exception (void) GCC_ATTR_NORETURN;
00109 
00110 CRUFT_API extern void octave_throw_execution_exception (void) GCC_ATTR_NORETURN;
00111 
00112 CRUFT_API extern void octave_throw_bad_alloc (void) GCC_ATTR_NORETURN;
00113 
00114 CRUFT_API extern void octave_rethrow_exception (void);
00115 
00116 #ifdef __cplusplus
00117 inline void octave_quit (void)
00118 {
00119   if (octave_signal_caught)
00120     {
00121       octave_signal_caught = 0;
00122       octave_handle_signal ();
00123     }
00124 };
00125 
00126 #define OCTAVE_QUIT octave_quit ()
00127 
00128 #else
00129 
00130 #define OCTAVE_QUIT \
00131   do \
00132     { \
00133       if (octave_signal_caught) \
00134         { \
00135           octave_signal_caught = 0; \
00136           octave_handle_signal (); \
00137         } \
00138     } \
00139   while (0)
00140 #endif
00141 
00142 /* Normally, you just want to use
00143 
00144      BEGIN_INTERRUPT_IMMEDIATELY_IN_FOREIGN_CODE;
00145      ... some code that calls a "foreign" function ...
00146      END_INTERRUPT_IMMEDIATELY_IN_FOREIGN_CODE;
00147 
00148    but sometimes it is useful to do something like
00149 
00150      BEGIN_INTERRUPT_IMMEDIATELY_IN_FOREIGN_CODE_1;
00151      ... custom code here, normally ending in a call to
00152          octave_rethrow_exception ...
00153      BEGIN_INTERRUPT_IMMEDIATELY_IN_FOREIGN_CODE_2;
00154 
00155    so that you can perform extra clean up operations before throwing
00156    the interrupt exception.  */
00157 
00158 #define BEGIN_INTERRUPT_IMMEDIATELY_IN_FOREIGN_CODE \
00159   BEGIN_INTERRUPT_IMMEDIATELY_IN_FOREIGN_CODE_1; \
00160   octave_rethrow_exception (); \
00161   BEGIN_INTERRUPT_IMMEDIATELY_IN_FOREIGN_CODE_2
00162 
00163 #define BEGIN_INTERRUPT_IMMEDIATELY_IN_FOREIGN_CODE_1 \
00164   do \
00165     { \
00166       octave_jmp_buf saved_context; \
00167  \
00168       octave_save_current_context (saved_context); \
00169  \
00170       if (octave_set_current_context) \
00171         { \
00172           octave_restore_current_context (saved_context)
00173 
00174 #define BEGIN_INTERRUPT_IMMEDIATELY_IN_FOREIGN_CODE_2 \
00175         } \
00176       else \
00177         { \
00178           octave_interrupt_immediately++
00179 
00180 #define END_INTERRUPT_IMMEDIATELY_IN_FOREIGN_CODE \
00181           octave_interrupt_immediately--; \
00182           octave_restore_current_context (saved_context); \
00183         } \
00184     } \
00185   while (0)
00186 
00187 #ifdef __cplusplus
00188 
00189 #define BEGIN_INTERRUPT_WITH_EXCEPTIONS \
00190   sig_atomic_t saved_octave_interrupt_immediately = octave_interrupt_immediately; \
00191  \
00192   try \
00193     { \
00194       octave_interrupt_immediately = 0;
00195 
00196 #define END_INTERRUPT_WITH_EXCEPTIONS \
00197     } \
00198   catch (octave_interrupt_exception) \
00199     { \
00200       octave_interrupt_immediately = saved_octave_interrupt_immediately; \
00201       octave_jump_to_enclosing_context (); \
00202     } \
00203   catch (octave_execution_exception) \
00204     { \
00205       octave_interrupt_immediately = saved_octave_interrupt_immediately; \
00206       octave_exception_state = octave_exec_exception; \
00207       octave_jump_to_enclosing_context (); \
00208     } \
00209   catch (std::bad_alloc) \
00210     { \
00211       octave_interrupt_immediately = saved_octave_interrupt_immediately; \
00212       octave_exception_state = octave_alloc_exception; \
00213       octave_jump_to_enclosing_context (); \
00214     } \
00215  \
00216   octave_interrupt_immediately = saved_octave_interrupt_immediately
00217 #endif
00218 
00219 #ifdef __cplusplus
00220 }
00221 
00222 /* These should only be declared for C++ code, and should also be
00223    outside of any extern "C" block.  */
00224 
00225 extern CRUFT_API void (*octave_signal_hook) (void);
00226 extern CRUFT_API void (*octave_interrupt_hook) (void);
00227 extern CRUFT_API void (*octave_bad_alloc_hook) (void);
00228 
00229 #endif
00230 
00231 #endif
 All Classes Files Functions Variables Typedefs Enumerations Enumerator Friends Defines