DIP33: A standard exception hierarchy
H. S. Teoh
hsteoh at quickfur.ath.cx
Tue Apr 2 10:41:04 PDT 2013
On Tue, Apr 02, 2013 at 01:29:00PM -0400, Jonathan M Davis wrote:
> On Tuesday, April 02, 2013 17:56:07 Lars T. Kyllingstad wrote:
> > On Monday, 1 April 2013 at 22:26:39 UTC, Jonathan M Davis wrote:
> > > In general, I'd strongly suggest having subclasses for the various
> > > "Kind"s in addition to the kind field. That way, you have the
> > > specific exception types if you want to have separate catch blocks
> > > for different error types, and you have the kind field if you just
> > > want to catch the base exception.
> >
> > Then you'd have two points of maintenance when you wish to add or
> > remove an error category.
>
> True, but it's also trivial to do. But if we had to decide between
> basically putting error codes on exceptions and using sub-classes, I'd
> vote for subclasses in most cases - though errno would need to go the
> error code in the exception route, since it has different meanings in
> different contexts and would risk an absolute explosion of exception
> types anyway; though it should probably be translated to a more
> meaningful exception based on context with the errno exception being
> chained to it - which is what you suggest in the DIP IIRC. In general
> though, I'd favor subclasses, and I don't think that it's all that big
> a deal to give them each specific error codes when you want the base
> class to have an error code like you're suggesting.
[...]
IMO, errno should be stored as-is in a dedicated ErrnoException. Any
interpretation of errno thereof should wrap this ErrnoException inside
another hierarchy-appropriate exception. For example:
void lowLevelIORoutine(...) {
if (osRead(...) < 0) {
throw ErrnoException(errno);
}
...
}
void libraryRoutine(...) {
try {
lowLevelIORoutine(...);
} catch(ErrnoException e) {
if (e.errno == ENOENT) {
// Chain ErrnoException to FileNotFoundException
throw new FileNotFoundException(e.msg, e);
} else if (e.errno == ENOSPC) {
// Chain ErrnoException to DiskFullException
throw new DiskFullException(e.msg, e);
} else {
// etc.
...
}
}
}
This way, user code can catch IOException rather than ErrnoException,
but errno is still accessible via .next should the user code want to
deal directly with errno:
void userCode() {
try {
auto f = File("/some/path/to/file");
} catch(IOException e) {
if ((auto f = cast(ErrnoException) e.next) !is null)
{
handleErrno(f.errno);
}
...
}
I think this would be a good use of the current .next field in
Exception.
T
--
A mathematician is a device for turning coffee into theorems. -- P. Erdos
More information about the Digitalmars-d
mailing list