Re: [AD] 4.3 error handling

[ Thread Index | Date Index | More lists.liballeg.org/allegro-developers Archives ]


On Wednesday 07 June 2006 14:32, Elias Pschernig wrote:
> True. We could even additionally provide a callback (NULL by default),
> but if you set one with al_set_error_callback, then it is gets called
> (and no longjmp-exception is raised).

Sounds reasonable. The user could always throw manually from the callback to 
jump back to the last try/catch point.

> Yeah, this example makes more sense. Still, it won't occur often - an
> initialization as complicated as above only should be necessary if you
> do something special.

That is actual audio init code you'd use with the current sound code. Granted 
it's the low-level stuff, but it's still what you'd do. And it'd only get 
more complicated if you want to use muliple AL_VOICEs, or specific drivers, 
or setting options, or whatever else.

> If you just want to use al_play_sample, then an 
> al_init_audio() should be all that's needed (and therefore a simple if
> would be less code than the al_error_try {} al_error_catch {}).

For the high-level stuff, sure. But the low-level code still needs to be 
called somewhere.

> > Then that's all you have to use. Just call al_error_disable_throws() and
> > do it the C way.
>
> Well, having to call al_error_disable_throws() for each program would
> not look favorably for the API to me.

Could always make an al_init flag to make throwing on or off by default. eg:
al_init(AL_INIT_ALL | AL_NO_ERR_JUMPS);
You could still enable or disable them manually after this point.

> Yes. In a way it is nice. I just have learned in the past to dislike any
> hackish (using setjmp/longjmp always is hackish, and #defines like this
> are so even more) features in C code.

I don't see setjmp/longjmp as hackish. But like any feature, you just need to 
use it responsibly. In all honesty, I think this behavior is actually pretty 
close to what C++ itself does, just with a few more extra features built into 
the language.

> Yes, it shouldn't be a problem normally. A big danger I see is from
> something like:

Yes, but writing bad code is writing bad code. The library shouldn't be 
responsible for the coder's sloppiness.

> Also this will go wrong in a bad way:
>
> int my_init(void)
> {
>     al_error_catch {
>         al_audio_init();
>     }
>     al_error_try {
>
>     }
>     return 0;
> }

That would actually give you a compile error. al_catch would put in a close 
brace after calling to clear the last jump point, which would effectively 
close the function. But it's still improper code, and improper code can give 
you any range of problems (just look at C++ if you want to see errors that 
aren't really indicative of the actual error).

> Hm, or:
>
> int my_init(void)
> {
>     if (want_sound) {
>         al_error_try
>             al_audio_init();
>         else
>             printf("If you code python this one will happen to you :P\n");
>     }
> }
>
> In all of those, the C compiler will not even warn.

That would, because al_try puts in its own open brace, and a matching al_catch 
would put in the proper close brace, so the bracing would be left unbalanced 
and the compiler would throw an error.

> Something else which might be a problem (probably it's not) - how well
> will setjmp/longjmp work when using other languages?

Depends on how closely the language uses Allegro's functions. If it's not 
direct, then you can see the C++ wrapper example (replacing throw with 
whatever error handling feature the language uses). If it's more direct, it'd 
probably have to just disable throwing.

> Con:
>     - Easy to make very non-obvious mistakes, as is the problem with
> many macros trying to add language features to C which it simply does
> not have.

I wouldn't say it's trying to add a feature C doesn't have. It's just using 
features C has always had in a clever way. I'll concede the macros to make it 
read like C++ *might* be a bit too much, but if that's the case, then it 
could just be a bit less transparent. Something like:

if(al_error_test())
{
   ...code...
   al_error_end_test();
}
else
{
   ...user error handling...
}

Effectively the same, and more obvious to what it's doing (and could make it a 
bit easier since the user can call end_test() maually and return/jump/throw, 
whatever, without consequence). But it can also lead to more coding error if 
the user forgets to call end_test(), and you *won't* get a compile 
warning/error about it. As well, al_error_test would still need to be a 
macro, but it would simply be something like:

#define al_error_test()  setjmp(*_al_error_next_jump_point())

The reason it has to be a macro is because you can't jump back to a function 
which returned (so it has to be called directly).

>     - C++ users can as well use a proper C++ wrapper, which can use real
> exceptions.

I don't see why this is a con. The code doesn't interfere with this (if 
anything, it makes it easier).




Mail converted by MHonArc 2.6.19+ http://listengine.tuxfamily.org/