mirror of
https://github.com/mruby/mruby
synced 2026-06-08 16:11:16 +00:00
Add the MRB_ENSURE() macro
This commit is contained in:
@@ -1615,6 +1615,10 @@ mrbmemset(void *s, int c, size_t n)
|
||||
|
||||
#define mrb_int_hash_func(mrb,key) (uint32_t)((key)^((key)<<2)^((key)>>2))
|
||||
|
||||
#define MRB_UNIQNAME(name) MRB_UNIQNAME_1(name, __LINE__)
|
||||
#define MRB_UNIQNAME_1(name, line) MRB_UNIQNAME_2(name, line)
|
||||
#define MRB_UNIQNAME_2(name, line) name##line
|
||||
|
||||
MRB_END_DECL
|
||||
|
||||
#endif /* MRUBY_H */
|
||||
|
||||
@@ -127,6 +127,42 @@ MRB_API mrb_value mrb_rescue_exceptions(mrb_state *mrb, mrb_func_t body, mrb_val
|
||||
mrb_func_t rescue, mrb_value r_data,
|
||||
mrb_int len, struct RClass **classes);
|
||||
|
||||
/**
|
||||
* Calls `func` via `mrb_protect_error()` and then always executes the user block exactly once.
|
||||
* Even if a global jump (similar to a Ruby exception) occurs within `func`, the block will be executed,
|
||||
* and after the block's completion, the global jump will be re-thrown.
|
||||
*
|
||||
* By checking `mrb->exc != NULL` within the block, you can determine if a global jump occurred in `func`.
|
||||
*
|
||||
* If you want to suppress the global jump and continue processing, use `mrb_clear_error(mrb); break;`.
|
||||
*
|
||||
* - `mrb`: The mruby state reference
|
||||
* - `result_var`: Pre-defined mrb_value type variable (to receive `func`'s return value)
|
||||
* - `func`: Function to call (compatible with `mrb_protect_error_func`)
|
||||
* - `data`: User data to pass to `func`
|
||||
*
|
||||
* Example:
|
||||
*
|
||||
* mrb_value result;
|
||||
* MRB_ENSURE(mrb, result, body_func, userdata) {
|
||||
* // This block is always executed (equivalent to Ruby's ensure)
|
||||
*
|
||||
* if (mrb->exc) {
|
||||
* // Post-processing when an exception occurs
|
||||
* }
|
||||
*
|
||||
* // To ignore the global jump, use `mrb_clear_error(mrb); break;` here
|
||||
* }
|
||||
*/
|
||||
#define MRB_ENSURE(mrb, result_var, func, data) \
|
||||
for (mrb_bool MRB_UNIQNAME(_break_) = FALSE; \
|
||||
!MRB_UNIQNAME(_break_) && \
|
||||
(((result_var) = mrb_protect_error(mrb, func, data, &MRB_UNIQNAME(_break_))), \
|
||||
((mrb)->exc = (MRB_UNIQNAME(_break_) ? mrb_obj_ptr((result_var)) : NULL)), \
|
||||
TRUE); \
|
||||
(void)(MRB_UNIQNAME(_break_) && (mrb)->jmp && (mrb_exc_raise(mrb, result_var), TRUE)), \
|
||||
MRB_UNIQNAME(_break_) = TRUE)
|
||||
|
||||
MRB_END_DECL
|
||||
|
||||
#endif /* MRUBY_ERROR_H */
|
||||
|
||||
Reference in New Issue
Block a user