Changeset 2878
- Timestamp:
- Aug 14, 2009 10:41:00 AM (15 years ago)
- Location:
- pjproject/trunk/pjlib
- Files:
-
- 3 edited
Legend:
- Unmodified
- Added
- Removed
-
pjproject/trunk/pjlib/include/pj/except.h
r2394 r2878 57 57 * The exception handling mechanism is completely thread safe, so the exception 58 58 * thrown by one thread will not interfere with other thread. 59 *60 * CAVEATS:61 * - unlike C++ exception, the scheme here won't call destructors of local62 * objects if exception is thrown. Care must be taken when a function63 * hold some resorce such as pool or mutex etc.64 * - You CAN NOT make nested exception in one single function without using65 * a nested PJ_USE_EXCEPTION.66 * - You can not provide more than PJ_CATCH or PJ_CATCH_ANY nor use PJ_CATCH67 * and PJ_CATCH_ANY for a single PJ_TRY.68 * - Exceptions will always be caught by the first handler (unlike C++ where69 * exception is only caught if the type matches.70 59 * 71 60 * The exception handling constructs are similar to C++. The blocks will be … … 128 117 * ID is raised by default pool policy when it fails to allocate memory. 129 118 * 119 * CAVEATS: 120 * - unlike C++ exception, the scheme here won't call destructors of local 121 * objects if exception is thrown. Care must be taken when a function 122 * hold some resorce such as pool or mutex etc. 123 * - You CAN NOT make nested exception in one single function without using 124 * a nested PJ_USE_EXCEPTION. Samples: 125 \verbatim 126 void wrong_sample() 127 { 128 PJ_USE_EXCEPTION; 129 130 PJ_TRY { 131 // Do stuffs 132 ... 133 } 134 PJ_CATCH_ANY { 135 // Do other stuffs 136 .... 137 .. 138 139 // The following block is WRONG! You MUST declare 140 // PJ_USE_EXCEPTION once again in this block. 141 PJ_TRY { 142 .. 143 } 144 PJ_CATCH_ANY { 145 .. 146 } 147 PJ_END; 148 } 149 PJ_END; 150 } 151 152 \endverbatim 153 154 * - You MUST NOT exit the function inside the PJ_TRY block. The correct way 155 * is to return from the function after PJ_END block is executed. 156 * For example, the following code will yield crash not in this code, 157 * but rather in the subsequent execution of PJ_TRY block: 158 \verbatim 159 void wrong_sample() 160 { 161 PJ_USE_EXCEPTION; 162 163 PJ_TRY { 164 // do some stuffs 165 ... 166 return; <======= DO NOT DO THIS! 167 } 168 PJ_CATCH_ANY { 169 } 170 PJ_END; 171 } 172 \endverbatim 173 174 * - You can not provide more than PJ_CATCH or PJ_CATCH_ANY nor use PJ_CATCH 175 * and PJ_CATCH_ANY for a single PJ_TRY. 176 * - Exceptions will always be caught by the first handler (unlike C++ where 177 * exception is only caught if the type matches. 178 130 179 * \section PJ_EX_KEYWORDS Keywords 131 180 * … … 311 360 * Pop exception handler. 312 361 */ 313 PJ_DECL(void) pj_pop_exception_handler_( void);362 PJ_DECL(void) pj_pop_exception_handler_(struct pj_exception_state_t *rec); 314 363 315 364 /** … … 344 393 * @hideinitializer 345 394 */ 346 #define PJ_END pj_pop_exception_handler_( ); \395 #define PJ_END pj_pop_exception_handler_(&pj_x_except__); \ 347 396 } else {} 348 397 -
pjproject/trunk/pjlib/src/pj/except.c
r2394 r2878 51 51 /* This will crash the system! */ 52 52 } 53 pj_pop_exception_handler_(handler); 53 54 pj_longjmp(handler->state, exception_id); 54 55 } … … 87 88 } 88 89 89 PJ_DEF(void) pj_pop_exception_handler_( void)90 PJ_DEF(void) pj_pop_exception_handler_(struct pj_exception_state_t *rec) 90 91 { 91 92 struct pj_exception_state_t *handler; … … 93 94 handler = (struct pj_exception_state_t *) 94 95 pj_thread_local_get(thread_local_id); 95 pj_assert(handler != NULL); 96 pj_thread_local_set(thread_local_id, handler->prev); 96 if (handler && handler==rec) { 97 pj_thread_local_set(thread_local_id, handler->prev); 98 } 97 99 } 98 100 #endif -
pjproject/trunk/pjlib/src/pjlib-test/exception.c
r2407 r2878 62 62 PJ_THROW( ID_2 ); 63 63 PJ_UNREACHED(return -1;) 64 } 65 66 static int try_catch_test(void) 67 { 68 PJ_USE_EXCEPTION; 69 int rc = -200; 70 71 PJ_TRY { 72 PJ_THROW(ID_1); 73 } 74 PJ_CATCH_ANY { 75 rc = 0; 76 } 77 PJ_END; 78 return rc; 79 } 80 81 static int throw_in_handler(void) 82 { 83 PJ_USE_EXCEPTION; 84 int rc = 0; 85 86 PJ_TRY { 87 PJ_THROW(ID_1); 88 } 89 PJ_CATCH_ANY { 90 if (PJ_GET_EXCEPTION() != ID_1) 91 rc = -300; 92 else 93 PJ_THROW(ID_2); 94 } 95 PJ_END; 96 return rc; 97 } 98 99 static int return_in_handler(void) 100 { 101 PJ_USE_EXCEPTION; 102 103 PJ_TRY { 104 PJ_THROW(ID_1); 105 } 106 PJ_CATCH_ANY { 107 return 0; 108 } 109 PJ_END; 110 return -400; 64 111 } 65 112 … … 154 201 return rc; 155 202 203 /* 204 * Nested handlers 205 */ 206 PJ_TRY { 207 rc = try_catch_test(); 208 } 209 PJ_CATCH_ANY { 210 rc = -70; 211 } 212 PJ_END; 213 214 if (rc != 0) 215 return rc; 216 217 /* 218 * Throwing exception inside handler 219 */ 220 rc = -80; 221 PJ_TRY { 222 int rc2; 223 rc2 = throw_in_handler(); 224 if (rc2) 225 rc = rc2; 226 } 227 PJ_CATCH_ANY { 228 if (PJ_GET_EXCEPTION() == ID_2) { 229 rc = 0; 230 } else { 231 rc = -90; 232 } 233 } 234 PJ_END; 235 236 if (rc != 0) 237 return rc; 238 239 240 /* 241 * Return from handler. Returning from the function inside a handler 242 * should be okay (though returning from the function inside the 243 * PJ_TRY block IS NOT OKAY!!). We want to test to see if handler 244 * is cleaned up properly, but not sure how to do this. 245 */ 246 PJ_TRY { 247 int rc2; 248 rc2 = return_in_handler(); 249 if (rc2) 250 rc = rc2; 251 } 252 PJ_CATCH_ANY { 253 rc = -100; 254 } 255 PJ_END; 256 257 156 258 return 0; 157 259 }
Note: See TracChangeset
for help on using the changeset viewer.