Main Page | Namespace List | Class Hierarchy | Class List | File List | Namespace Members | Class Members | File Members

ruby_exceptions.hpp

Go to the documentation of this file.
00001 #ifndef Exc_Ruby__Ruby_Exceptions__hpp_
00002 #define Exc_Ruby__Ruby_Exceptions__hpp_
00003 
00009 #include <ruby.h>
00010 #undef TYPE
00011 
00012 #include <stdexcept>
00013 #include "detail/ruby_hacks.hpp"
00014 
00015 namespace Exc_Ruby
00016 {
00017 
00019 
00028 struct Ruby_Exception
00029 {
00031   Ruby_Exception(VALUE e) : ex(e) { }
00032 
00035   Ruby_Exception(VALUE exc, char const * fmt, ...);
00036 
00038   VALUE ex;
00039 };
00040 
00042 
00046 struct Ruby_Jump_Tag
00047 {
00049   Ruby_Jump_Tag(int t) : tag(t) { }
00050 
00052   int tag;
00053 };
00054 
00058 // Goto is used here to avoid having to use a second try/catch block (can't
00059 // rb_exc_raise directly out of the catch blocks below, since the exceptions
00060 // will not get properly cleaned up).
00061 // The gotos are located before the try and not after it so the function can't
00062 // "fall through" into the exception-handling code accidentally.
00063 #define RUBY_TRY \
00064   VALUE Exc_Ruby__ruby_exc = Qnil; \
00065   int Exc_Ruby__ruby_jump_tag = 0; \
00066   \
00067   goto start_of_RUBY_TRY; \
00068   \
00069   Exc_Ruby__ruby_exception: \
00070     rb_exc_raise(Exc_Ruby__ruby_exc); \
00071   Exc_Ruby__ruby_jump_tag: \
00072     rb_jump_tag(Exc_Ruby__ruby_jump_tag); \
00073   \
00074   start_of_RUBY_TRY: \
00075   try
00076 
00082 #define RUBY_RETHROW(ex) \
00083   Exc_Ruby__ruby_exc = ex; \
00084   goto Exc_Ruby__ruby_exception;
00085 
00089 #define RUBY_CATCH \
00090   catch(::Exc_Ruby::Ruby_Exception const & ex) \
00091   { \
00092     RUBY_RETHROW(ex.ex); \
00093   } \
00094   catch(::Exc_Ruby::Ruby_Jump_Tag const & ex) \
00095   { \
00096     Exc_Ruby__ruby_jump_tag = ex.tag; \
00097     goto Exc_Ruby__ruby_jump_tag; \
00098   } \
00099   catch(std::bad_alloc const & ex) \
00100   { \
00101     /* This won't work quite right if the rb_exc_new2 fails; not    */ \
00102     /* much we can do about that, since Ruby doesn't give us access */ \
00103     /* to a pre-allocated NoMemoryError object                      */ \
00104     RUBY_RETHROW(rb_exc_new2(rb_eNoMemError, ex.what())); \
00105   } \
00106   catch(std::exception const & ex) \
00107   { \
00108     /* This can raise a NoMemoryError in VERY rare circumstances    */ \
00109     RUBY_RETHROW(rb_exc_new2(rb_eRuntimeError, ex.what())); \
00110   } \
00111   catch(...) \
00112   { \
00113     RUBY_RETHROW(rb_exc_new2(rb_eRuntimeError, "unknown C++ exception thrown")); \
00114   } \
00115 
00116 } // namespace Exc_Ruby
00117 
00118 #include "ruby_exceptions.ipp"
00119 
00120 #endif // Exc_Ruby__Ruby_Exceptions__hpp_
00121 

Generated on Sat Jan 1 12:02:19 2005 for Exceptional Ruby by doxygen 1.3.6