stdcxx-dev mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From Martin Sebor <se...@roguewave.com>
Subject Re: design of testuite exceptions (was: Re: svn commit: r418319 - /incubator/stdcxx/trunk/tests/strings/21.string.io.cpp)
Date Wed, 12 Jul 2006 01:26:46 GMT
Farid Zaripov wrote:
>  > -----Original Message-----
>  > From: Martin Sebor [mailto:sebor@roguewave.com]
>  > Sent: Friday, July 07, 2006 10:40 PM
>  > To: stdcxx-dev@incubator.apache.org
>  > Subject: design of testuite exceptions (was: Re: svn commit:
>  > r418319 - /incubator/stdcxx/trunk/tests/strings/21.string.io.cpp)
>  >
>   [...]
>  > Great! A few (rather lengthy) comments:
> 
>   Implemented your notes about testsuite exception (rw_exception.h, 
> exception.cpp).

Okay. I think I would still like to remove the logtostderr argument
and do the logging in new.cpp. I believe understand why you left it
there (because it would be difficult to format the what() string
otherwise, correct?) but I don't want us to have to specify an extra
function argument in all the calls to rw_throw() in all the tests
when the argument is always going to be be 0.

Also, it would be more efficient to avoid catching and rethrowing
the exception only to call va_end() on the argument list. For that
matter, I think it would also be better not to introduce templates
to throw the exception and instead use a case and switch statement
(templates defined in .cpp files need to be explicitly instantiated
for some compilers, e.g., for Compaq/HP C++ on Tru64). But that's
something we can easily change at any time (i.e., it's not an
obstacle to committing the code).

Finally, I'm wondering whether we even want to be able to catch
different types of test exceptions (i.e., StreamException and
ExceptionBase) or whether we want to catch the same type and
maybe just throw different (but not visible) types derived from
it. I.e., rw_exception.h would define just one exception class,
say Exception, and exception.cpp would throw a type derived from
it:

     // rw_exception.h

     struct Exception {
         const ExceptionId id_;
         Exception ();
         virtual ~Exception ();
         virtual const char* what () const = 0;
     };

     // exception.cpp
     struct BadAlloc: std::bad_alloc { ... };
     struct TestException: Exception {
         char what_ [256];
         virtual const char* what () const { return what_; }
     };

     void rw_throw (ExceptionId id, ...) {
         // format what string
         switch (id) {
         case BadAlloc: throw BadAlloc (...);
         case ...: throw ... (...);
         }
     }

It seems that by keeping the set of visible types to a minimum we
could assure that tests won't try to catch the different types of
exceptions, thus keeping them simple (they can still distinguish
the actual dynamic types of the caught exceptions by looking at
the id_ member. Do you agree?

Moving on to allocator.cpp, I suspect you might have introduced
a typo in the fifth argument to rw_throw: "SharedAlloc::funcall"
should be the name of the function or 0 (in which case rw_throw
would need to avoid trying to format it):

[...]
> @@ -229,9 +202,10 @@
>          // increment the exception counter for this function
>          ++n_throws_ [mf];
>  
> -        _rw_throw_exception (__FILE__, __LINE__,
> -                             "UserAlloc::%s: reached call limit of %zu",
> -                             _rw_func_names [mf], throw_at_calls_);
> +        rw_throw (ex_bad_alloc, false, __FILE__, __LINE__,
> +                  "SharedAlloc::funcall",
> +                  "UserAlloc::%s: reached call limit of %zu",
> +                  _rw_func_names [mf], throw_at_calls_);
>  
>          RW_ASSERT (!"logic error: should not reach");
>      }
> 
> 
> ------------------------------------------------------------------------
> 
> Index: new.cpp
> ===================================================================
> --- new.cpp	(revision 420901)
> +++ new.cpp	(working copy)
> @@ -37,6 +37,8 @@
[...]
> +/*
>  struct BadAlloc: _RWSTD_BAD_ALLOC
>  {
>      char what_ [4096];
>  
> -    /* virtual */ const char* what () const _THROWS (()) {
> +    const char* what () const _THROWS (()) {
>          return what_;
>      }
>  };
> +*/

You can remove commented out code.

>  
>  
>  static size_t seq_gen;   // sequence number generator
> @@ -365,40 +369,31 @@
>          || reached_block_limit
>          || reached_size_limit) {
>  
> -        BadAlloc ex;
> -
>  #ifndef _RWSTD_NO_EXCEPTIONS
>  
> -        rw_snprintfa (ex.what_, 4096U, "%s:%d: %s (%zu) ",
> -                      __FILE__, __LINE__, name [array], nbytes);
> +        bool logtostderr = 
> +            trace_sequence [0] <= seq_gen && seq_gen < trace_sequence
[1];
>  
> -        strcat (ex.what_, "threw bad_alloc: ");
> -
>          if (reached_call_limit)
> +            rw_throw (ex_bad_alloc, logtostderr, 
> +                      __FILE__, __LINE__, name [array], 
> +                      "(%zu), reached call limit of %zu", 
> +                      nbytes, pst->new_calls_ [array]);

I would be happier with catching the exception here (by reference),
logging the what() string when logging/tracing is enabled, and then
rethrowing it, than be stuck with the extra argument to rw_throw().
It'll be easier to figure out a better way to do it later.

Martin

Mime
View raw message