GNU Octave  3.8.0
A high-level interpreted language, primarily intended for numerical computations, mostly compatible with Matlab
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Pages
quit.h
Go to the documentation of this file.
1 /*
2 
3 Copyright (C) 2002-2013 John W. Eaton
4 
5 This file is part of Octave.
6 
7 Octave is free software; you can redistribute it and/or modify it
8 under the terms of the GNU General Public License as published by the
9 Free Software Foundation; either version 3 of the License, or (at your
10 option) any later version.
11 
12 Octave is distributed in the hope that it will be useful, but WITHOUT
13 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
14 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
15 for more details.
16 
17 You should have received a copy of the GNU General Public License
18 along with Octave; see the file COPYING. If not, see
19 <http://www.gnu.org/licenses/>.
20 
21 */
22 
23 #if !defined (octave_quit_h)
24 #define octave_quit_h 1
25 
26 #ifdef __cplusplus
27 #include <new>
28 extern "C" {
29 #endif
30 
31 #include <stdio.h>
32 
33 #include <signal.h>
34 #include <setjmp.h>
35 
36 #if defined (__WIN32__) && ! defined (_POSIX_VERSION)
37 
38 #define WIN32_LEAN_AND_MEAN
39 #include <windows.h>
40 
41 CRUFT_API extern void w32_sigint_init (void); /* setup */
42 CRUFT_API extern void w32_raise_final (void); /* tear down */
43 CRUFT_API extern void w32_raise (int sig); /* raise signal in main thread */
44 CRUFT_API extern int w32_in_main_thread (void); /* return true if in main thread */
45 
46 #endif
47 
48 #if defined (OCTAVE_HAVE_SIG_JUMP)
49 
50 typedef sigjmp_buf octave_jmp_buf;
51 
52 #define octave_set_current_context sigsetjmp (current_context, 1)
53 
54 #else
55 
56 typedef jmp_buf octave_jmp_buf;
57 
58 #define octave_set_current_context setjmp (current_context)
59 
60 #endif
61 
62 CRUFT_API extern octave_jmp_buf current_context;
63 
64 CRUFT_API extern void octave_save_current_context (void *);
65 
66 CRUFT_API extern void octave_restore_current_context (void *);
67 
68 CRUFT_API extern void octave_jump_to_enclosing_context (void) GCC_ATTR_NORETURN;
69 
70 CRUFT_API extern void octave_save_signal_mask (void);
71 
72 CRUFT_API extern void octave_restore_signal_mask (void);
73 
74 #ifdef __cplusplus
75 class
76 octave_execution_exception
77 {
78 };
79 
80 class
81 octave_interrupt_exception
82 {
83 };
84 #endif
85 
87 {
91 };
92 
93 CRUFT_API extern sig_atomic_t octave_interrupt_immediately;
94 
95 /*
96  > 0: interrupt pending
97  0: no interrupt pending
98  < 0: handling interrupt
99 */
100 CRUFT_API extern sig_atomic_t octave_interrupt_state;
101 
102 CRUFT_API extern sig_atomic_t octave_exception_state;
103 
104 CRUFT_API extern volatile sig_atomic_t octave_signal_caught;
105 
106 CRUFT_API extern void octave_handle_signal (void);
107 
108 CRUFT_API extern void octave_throw_interrupt_exception (void) GCC_ATTR_NORETURN;
109 
110 CRUFT_API extern void octave_throw_execution_exception (void) GCC_ATTR_NORETURN;
111 
112 CRUFT_API extern void octave_throw_bad_alloc (void) GCC_ATTR_NORETURN;
113 
114 CRUFT_API extern void octave_rethrow_exception (void);
115 
116 #ifdef __cplusplus
117 inline void octave_quit (void)
118 {
119  if (octave_signal_caught)
120  {
121  octave_signal_caught = 0;
123  }
124 };
125 
126 #define OCTAVE_QUIT octave_quit ()
127 
128 #else
129 
130 #define OCTAVE_QUIT \
131  do \
132  { \
133  if (octave_signal_caught) \
134  { \
135  octave_signal_caught = 0; \
136  octave_handle_signal (); \
137  } \
138  } \
139  while (0)
140 #endif
141 
142 /* Normally, you just want to use
143 
144  BEGIN_INTERRUPT_IMMEDIATELY_IN_FOREIGN_CODE;
145  ... some code that calls a "foreign" function ...
146  END_INTERRUPT_IMMEDIATELY_IN_FOREIGN_CODE;
147 
148  but sometimes it is useful to do something like
149 
150  BEGIN_INTERRUPT_IMMEDIATELY_IN_FOREIGN_CODE_1;
151  ... custom code here, normally ending in a call to
152  octave_rethrow_exception ...
153  BEGIN_INTERRUPT_IMMEDIATELY_IN_FOREIGN_CODE_2;
154 
155  so that you can perform extra clean up operations before throwing
156  the interrupt exception. */
157 
158 #define BEGIN_INTERRUPT_IMMEDIATELY_IN_FOREIGN_CODE \
159  BEGIN_INTERRUPT_IMMEDIATELY_IN_FOREIGN_CODE_1; \
160  octave_rethrow_exception (); \
161  BEGIN_INTERRUPT_IMMEDIATELY_IN_FOREIGN_CODE_2
162 
163 #define BEGIN_INTERRUPT_IMMEDIATELY_IN_FOREIGN_CODE_1 \
164  do \
165  { \
166  octave_jmp_buf saved_context; \
167  \
168  octave_save_current_context (saved_context); \
169  \
170  if (octave_set_current_context) \
171  { \
172  octave_restore_current_context (saved_context)
173 
174 #define BEGIN_INTERRUPT_IMMEDIATELY_IN_FOREIGN_CODE_2 \
175  } \
176  else \
177  { \
178  octave_interrupt_immediately++
179 
180 #define END_INTERRUPT_IMMEDIATELY_IN_FOREIGN_CODE \
181  octave_interrupt_immediately--; \
182  octave_restore_current_context (saved_context); \
183  } \
184  } \
185  while (0)
186 
187 #ifdef __cplusplus
188 
189 #define BEGIN_INTERRUPT_WITH_EXCEPTIONS \
190  sig_atomic_t saved_octave_interrupt_immediately = octave_interrupt_immediately; \
191  \
192  try \
193  { \
194  octave_interrupt_immediately = 0;
195 
196 #define END_INTERRUPT_WITH_EXCEPTIONS \
197  } \
198  catch (octave_interrupt_exception) \
199  { \
200  octave_interrupt_immediately = saved_octave_interrupt_immediately; \
201  octave_jump_to_enclosing_context (); \
202  } \
203  catch (octave_execution_exception) \
204  { \
205  octave_interrupt_immediately = saved_octave_interrupt_immediately; \
206  octave_exception_state = octave_exec_exception; \
207  octave_jump_to_enclosing_context (); \
208  } \
209  catch (std::bad_alloc) \
210  { \
211  octave_interrupt_immediately = saved_octave_interrupt_immediately; \
212  octave_exception_state = octave_alloc_exception; \
213  octave_jump_to_enclosing_context (); \
214  } \
215  \
216  octave_interrupt_immediately = saved_octave_interrupt_immediately
217 #endif
218 
219 #ifdef __cplusplus
220 }
221 
222 /* These should only be declared for C++ code, and should also be
223  outside of any extern "C" block. */
224 
225 extern CRUFT_API void (*octave_signal_hook) (void);
226 extern CRUFT_API void (*octave_interrupt_hook) (void);
227 extern CRUFT_API void (*octave_bad_alloc_hook) (void);
228 
229 #endif
230 
231 #endif