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

Reply via email to