2 ** OSSP ex - Exception Handling (modified to fit into SimGrid)
3 ** Copyright (c) 2005 Martin Quinson.
4 ** Copyright (c) 2002-2004 Ralf S. Engelschall <rse@engelschall.com>
5 ** Copyright (c) 2002-2004 The OSSP Project <http://www.ossp.org/>
6 ** Copyright (c) 2002-2004 Cable & Wireless <http://www.cw.com/>
8 ** This file is part of OSSP ex, an exception handling library
9 ** which can be found at http://www.ossp.org/pkg/lib/ex/.
11 ** Permission to use, copy, modify, and distribute this software for
12 ** any purpose with or without fee is hereby granted, provided that
13 ** the above copyright notice and this permission notice appear in all
16 ** THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
17 ** WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
18 ** MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
19 ** IN NO EVENT SHALL THE AUTHORS AND COPYRIGHT HOLDERS AND THEIR
20 ** CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21 ** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22 ** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
23 ** USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
24 ** ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
25 ** OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
26 ** OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 ** ex.h: exception handling (pre-processor part)
36 #include <xbt/sysdep.h>
38 /* required ISO-C standard facilities */
41 /* the machine context */
42 #if defined(__EX_MCTX_MCSC__)
43 #include <ucontext.h> /* POSIX.1 ucontext(3) */
44 #define __ex_mctx_struct ucontext_t uc;
45 #define __ex_mctx_save(mctx) (getcontext(&(mctx)->uc) == 0)
46 #define __ex_mctx_restored(mctx) /* noop */
47 #define __ex_mctx_restore(mctx) (void)setcontext(&(mctx)->uc)
49 #elif defined(__EX_MCTX_SSJLJ__)
50 #include <setjmp.h> /* POSIX.1 sigjmp_buf(3) */
51 #define __ex_mctx_struct sigjmp_buf jb;
52 #define __ex_mctx_save(mctx) (sigsetjmp((mctx)->jb, 1) == 0)
53 #define __ex_mctx_restored(mctx) /* noop */
54 #define __ex_mctx_restore(mctx) (void)siglongjmp((mctx)->jb, 1)
56 #elif defined(__EX_MCTX_SJLJ__) || !defined(__EX_MCTX_CUSTOM__)
57 #include <setjmp.h> /* ISO-C jmp_buf(3) */
58 #define __ex_mctx_struct jmp_buf jb;
59 #define __ex_mctx_save(mctx) (setjmp((mctx)->jb) == 0)
60 #define __ex_mctx_restored(mctx) /* noop */
61 #define __ex_mctx_restore(mctx) (void)longjmp((mctx)->jb, 1)
64 /* declare the machine context type */
65 typedef struct { __ex_mctx_struct } __ex_mctx_t;
67 /** Content of an exception */
69 char *msg; /*< human readable message; to be freed */
70 int code; /*< category like HTTP (what went wrong) */
71 int value; /*< like errno (why did it went wrong) */
73 char *host; /*< NULL for localhost; hostname:port if remote */
75 char *file; /*< to be freed only for remote exceptions */
77 char *func; /*< to be freed only for remote exceptions */
80 /* declare the context type (private) */
82 __ex_mctx_t *ctx_mctx; /* permanent machine context of enclosing try/catch */
83 int ctx_deferred; /* permanent flag whether exception is deferred */
84 int ctx_deferring;/* permanent counter of exception deferring level */
85 int ctx_defer; /* temporary flag for exception deferring macro */
86 int ctx_shielding;/* permanent counter of exception shielding level */
87 int ctx_shield; /* temporary flag for exception shielding macro */
88 int ctx_caught; /* temporary flag whether exception was caught */
89 volatile ex_t ctx_ex; /* temporary exception storage */
92 /* the static and dynamic initializers for a context structure */
93 #define SG_CTX_INITIALIZER \
94 { NULL, 0, 0, 0, 0, 0, 0, { /* content */ NULL, 0, 0, \
95 /*throw point*/ NULL, NULL, NULL, 0, NULL } }
96 #define SG_CTX_INITIALIZE(ctx) \
98 (ctx)->ctx_mctx = NULL; \
99 (ctx)->ctx_deferred = 0; \
100 (ctx)->ctx_deferring = 0; \
101 (ctx)->ctx_defer = 0; \
102 (ctx)->ctx_shielding = 0; \
103 (ctx)->ctx_shield = 0; \
104 (ctx)->ctx_caught = 0; \
105 (ctx)->ctx_ex.msg = NULL; \
106 (ctx)->ctx_ex.code = 0; \
107 (ctx)->ctx_ex.value = 0; \
108 (ctx)->ctx_ex.host = NULL; \
109 (ctx)->ctx_ex.procname = NULL; \
110 (ctx)->ctx_ex.file = NULL; \
111 (ctx)->ctx_ex.line = 0; \
112 (ctx)->ctx_ex.func = NULL; \
115 /* the exception context */
116 typedef ex_ctx_t *(*ex_ctx_cb_t)(void);
117 extern ex_ctx_cb_t __xbt_ex_ctx;
118 extern ex_ctx_t *__xbt_ex_ctx_default(void);
120 /* the termination handler */
121 typedef void (*ex_term_cb_t)(ex_t *);
122 extern ex_term_cb_t __xbt_ex_terminate;
123 extern void __xbt_ex_terminate_default(ex_t *e);
125 /* the block for trying execution */
128 ex_ctx_t *__xbt_ex_ctx_ptr = __xbt_ex_ctx(); \
129 int __ex_cleanup = 0; \
130 __ex_mctx_t *__ex_mctx_en; \
131 __ex_mctx_t __ex_mctx_me; \
132 __ex_mctx_en = __xbt_ex_ctx_ptr->ctx_mctx; \
133 __xbt_ex_ctx_ptr->ctx_mctx = &__ex_mctx_me; \
134 if (__ex_mctx_save(&__ex_mctx_me)) { \
137 /* the optional(!) block for cleanup */
141 __xbt_ex_ctx_ptr->ctx_caught = 0; \
144 __ex_mctx_restored(&__ex_mctx_me); \
145 __xbt_ex_ctx_ptr->ctx_caught = 1; \
147 __xbt_ex_ctx_ptr->ctx_mctx = __ex_mctx_en; \
152 /* the block for catching an exception */
153 #define sg_catch(e) \
156 if (!(__ex_cleanup)) \
157 __xbt_ex_ctx_ptr->ctx_caught = 0; \
160 if (!(__ex_cleanup)) { \
161 __ex_mctx_restored(&__ex_mctx_me); \
162 __xbt_ex_ctx_ptr->ctx_caught = 1; \
165 __xbt_ex_ctx_ptr->ctx_mctx = __ex_mctx_en; \
167 if ( !(__xbt_ex_ctx()->ctx_caught) \
168 || ((e) = __xbt_ex_ctx()->ctx_ex, 0)) { \
172 /* the throwing of a new exception */
173 #define sg_throw(c,v,m) \
174 (( __xbt_ex_ctx()->ctx_shielding > 0 \
175 || (__xbt_ex_ctx()->ctx_deferring > 0 && __xbt_ex_ctx()->ctx_deferred == 1)) ? 0 : \
176 (__xbt_ex_ctx()->ctx_ex.msg = bprintf(m), \
177 __xbt_ex_ctx()->ctx_ex.code = (c), \
178 __xbt_ex_ctx()->ctx_ex.value = (v), \
179 __xbt_ex_ctx()->ctx_ex.host = (char*)NULL, \
180 __xbt_ex_ctx()->ctx_ex.procname = strdup(xbt_procname()), \
181 __xbt_ex_ctx()->ctx_ex.file = (char*)__FILE__, \
182 __xbt_ex_ctx()->ctx_ex.line = __LINE__, \
183 __xbt_ex_ctx()->ctx_ex.func = (char*)_XBT_FUNCTION, \
184 __xbt_ex_ctx()->ctx_deferred = 1, \
185 (__xbt_ex_ctx()->ctx_deferring > 0 ? 0 : \
186 (__xbt_ex_ctx()->ctx_mctx == NULL \
187 ? (__xbt_ex_terminate((ex_t *)&(__xbt_ex_ctx()->ctx_ex)), -1) \
188 : (__ex_mctx_restore(__xbt_ex_ctx()->ctx_mctx), 1) ))))
190 /* the re-throwing of an already caught exception */
192 (( __xbt_ex_ctx()->ctx_shielding > 0 \
193 || __xbt_ex_ctx()->ctx_deferring > 0) ? 0 : \
194 ( __xbt_ex_ctx()->ctx_mctx == NULL \
195 ? (__xbt_ex_terminate((ex_t *)&(__xbt_ex_ctx()->ctx_ex)), -1) \
196 : (__ex_mctx_restore(__xbt_ex_ctx()->ctx_mctx), 1) ))
198 /* shield an operation from exception handling */
200 for (__xbt_ex_ctx()->ctx_shielding++, \
201 __xbt_ex_ctx()->ctx_shield = 1; \
202 __xbt_ex_ctx()->ctx_shield == 1; \
203 __xbt_ex_ctx()->ctx_shield = 0, \
204 __xbt_ex_ctx()->ctx_shielding--)
206 /* defer immediate exception handling */
208 for (((__xbt_ex_ctx()->ctx_deferring)++ == 0 ? __xbt_ex_ctx()->ctx_deferred = 0 : 0), \
209 __xbt_ex_ctx()->ctx_defer = 1; \
210 __xbt_ex_ctx()->ctx_defer == 1; \
211 __xbt_ex_ctx()->ctx_defer = 0, \
212 ((--(__xbt_ex_ctx()->ctx_deferring) == 0 && __xbt_ex_ctx()->ctx_deferred == 1) ? sg_rethrow : 0))
214 /* exception handling tests */
215 #define sg_catching \
216 (__xbt_ex_ctx()->ctx_mctx != NULL)
217 #define sg_shielding \
218 (__xbt_ex_ctx()->ctx_shielding > 0)
219 #define sg_deferring \
220 (__xbt_ex_ctx()->ctx_deferring > 0)
222 /* optional namespace mapping */
223 #if defined(__EX_NS_UCCXX__)
225 #define Cleanup sg_cleanup
226 #define Catch sg_catch
227 #define Throw sg_throw
228 #define Rethrow sg_rethrow
229 #define Shield sg_shield
230 #define Defer sg_defer
231 #elif defined(__EX_NS_CXX__) || (!defined(__cplusplus) && !defined(__EX_NS_CUSTOM__))
233 #define cleanup sg_cleanup
234 #define catch sg_catch
235 #define throw sg_throw
236 #define rethrow sg_rethrow
237 #define shield sg_shield
238 #define defer sg_defer
241 #endif /* __SG_EX_H__ */