libcdio-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Libcdio-devel] RFC: C++ wrapper exception handling


From: R. Bernstein
Subject: [Libcdio-devel] RFC: C++ wrapper exception handling
Date: Sun, 15 Jan 2006 06:26:29 -0500

I've been working a little on wrapping libcdio for Python using SWIG
and one of the things I realized in the OO C++ wrapper was that
perhaps it would be more C++ idiomatic to raise exceptions on device
errors rather than give the status as a function return.

So as a test, I've converted all of the routines in cdio++/device.hpp
to throw an error. This test is in CVS and if folks want to give
comments on it -- (e.g. in favor of this approach or not?) -- I'd be
grateful. Lacking other guidance, I'll probably then convert the other
C++ routines that return driver_return_code_t into throwing
exceptions.

Here's the relevant portion of the code:

include/cdio++/cdio.hpp:
class CdioDevice
{
...
  class DriverOpException 
  {
  public:
    driver_return_code_t driver_return_code;
    DriverOpException( driver_return_code_t drc ) { 
      driver_return_code = drc; 
    };
    driver_return_code_t get_code(void) { 
      return driver_return_code; 
    };
    const char *get_msg(void) { 
      return cdio_driver_return_code_to_str(driver_return_code); 
    };
  };
...
private:
  void throw_device_exception(driver_return_code_t drc) 
  {
    if (DRIVER_OP_SUCCESS == drc) return;
    throw DriverOpException(drc);
  }
};

include/cdio++/device.hpp:
...
void closeTray (const char *psz_drive, /*in/out*/ driver_id_t &driver_id) 
{
  driver_return_code_t drc = cdio_close_tray (psz_drive, &driver_id);
  throw_device_exception(drc);
}
...

C++/OO/eject.cpp:
...
  try {
    device.ejectMedia(psz_drive);
    printf("CD in CD-ROM drive %s ejected.\n", psz_drive);
  }
  catch ( CdioDevice::DriverOpException e ) {
    printf("Ejecting CD from CD-ROM drive %s operation error:\n\t%s.\n", 
       psz_drive, e.get_msg());
  }
...

Stroustrup's C++ Programming Language book suggests subclassing 
exceptions, perhaps like this: 

cdio.hpp:
  class DriverOpException 
  {
  public:
    driver_return_code_t driver_return_code;
    DriverOpException( void ) {};
    DriverOpException( driver_return_code_t drc ) 
    ...
  }; 
  class DriverOpUnsupported: public DriverOpException {};
  // other DriverOp... exceptions

  ...
  void throw_device_exception(driver_return_code_t drc) 
  {
    switch (drc) {
    case DRIVER_OP_SUCCESS:
      return;
    case DRIVER_OP_UNSUPPORTED:
      throw DriverOpUnsupported();
    // cases for other exceptions...
    default:
      throw DriverOpException(drc);
    }

eject.cpp:
  ...
  try {
    device.ejectMedia(psz_drive);
    printf("CD in CD-ROM drive %s ejected.\n", psz_drive);
  }
  catch ( CdioDevice::DriverOpUnsupported e ) {
    printf("Ejecting CD from CD-ROM drive %s is unsupported on that device.\n",
       psz_drive);
  }
  catch ( CdioDevice::DriverOpException e ) {
    printf("Ejecting CD from CD-ROM drive %s operation error:\n\t%s.\n", 
       psz_drive, e.get_msg());
  }

The asserted benefit is that testing for a particular exception is one
via the "catch" rather than having another test inside the "catch"
using say get_code(). A downside looks like that every time an error
condition is changed that has to be reflected in this
subclassing. Also in the way that I've written this above either
driver_return_code_t will be set or not depending on the throw. No
doubt there's a way to fix this, but some simple attempts failed and I
find myself duplicating more and more code which doesn't seems good
for maintenance.

If however those devout C++ programmers find this (or something else)
better, I'll put it in.

Thanks.






reply via email to

[Prev in Thread] Current Thread [Next in Thread]