1
0
mirror of https://github.com/cookiengineer/audacity synced 2025-07-03 22:19:07 +02:00

Doxygen commentary for AudacityException.h

This commit is contained in:
Paul Licameli 2020-08-25 01:00:23 -04:00
parent cc08455453
commit 1119dde68a
2 changed files with 74 additions and 70 deletions

@ -1,23 +1,13 @@
/********************************************************************** /*!********************************************************************
Audacity: A Digital Audio Editor Audacity: A Digital Audio Editor
AudacityException @file AudacityException.cpp
@brief Implements AudacityException and related
Paul Licameli Paul Licameli
********************************************************************//** ***********************************************************************/
\class AudacityException
\brief root of a hierarchy of classes that are thrown and caught
by Audacity.
\class MessageBoxException
\brief an AudacityException that pops up a single message box even if
there were multiple exceptions of the same kind before it actually
got to show.
*//********************************************************************/
#include "Audacity.h" #include "Audacity.h"
#include "AudacityException.h" #include "AudacityException.h"

@ -1,19 +1,14 @@
#ifndef __AUDACITY_EXCEPTION__ #ifndef __AUDACITY_EXCEPTION__
#define __AUDACITY_EXCEPTION__ #define __AUDACITY_EXCEPTION__
/********************************************************************** /*!********************************************************************
Audacity: A Digital Audio Editor Audacity: A Digital Audio Editor
AudacityException.h @file AudacityException.h
@brief Declare abstract class AudacityException, some often-used subclasses, and @ref GuardedCall
Paul Licameli Paul Licameli
Define the root of a hierarchy of classes that are thrown and caught
by Audacity.
Define some subclasses. Not all subclasses need be defined here.
**********************************************************************/ **********************************************************************/
#include "MemoryX.h" #include "MemoryX.h"
@ -22,59 +17,67 @@
#include "Internat.h" #include "Internat.h"
//! Base class for exceptions specially processed by the application
/*! Objects of this type can be thrown and caught in any thread, stored, and then used by the main
thread in later idle time to explain the error condition to the user.
*/
class AudacityException /* not final */ class AudacityException /* not final */
{ {
public: public:
AudacityException() {} AudacityException() {}
virtual ~AudacityException() = 0; virtual ~AudacityException() = 0;
// Action to do in the main thread at idle time of the event loop. //! Action to do in the main thread at idle time of the event loop.
virtual void DelayedHandlerAction() = 0; virtual void DelayedHandlerAction() = 0;
protected: protected:
// Make this protected to prevent slicing copies //! Make this protected to prevent slicing copies
AudacityException( const AudacityException& ) = default; AudacityException( const AudacityException& ) = default;
// Don't allow moves of this class or subclasses //! Don't allow moves of this class or subclasses
// see https://bugzilla.audacityteam.org/show_bug.cgi?id=2442 // see https://bugzilla.audacityteam.org/show_bug.cgi?id=2442
AudacityException( AudacityException&& ) = delete; AudacityException( AudacityException&& ) = delete;
// Disallow assignment //! Disallow assignment
AudacityException &operator = ( const AudacityException & ) = delete; AudacityException &operator = ( const AudacityException & ) = delete;
}; };
/// \brief A subclass of AudacityException whose delayed handler action displays //! Abstract AudacityException subclass displays a message, specified by further subclass
/// a message box. The message is specified by further subclasses. /*! At most one message will be displayed for each pass through the main event idle loop,
/// Not more than one message box will be displayed for each pass through no matter how many exceptions were caught. */
/// the main event idle loop.
class MessageBoxException /* not final */ : public AudacityException class MessageBoxException /* not final */ : public AudacityException
{ {
// Do not allow subclasses to change this behavior further, except //! Privatize the inherited function
// by overriding ErrorMessage()
using AudacityException::DelayedHandlerAction; using AudacityException::DelayedHandlerAction;
void DelayedHandlerAction() override;
//! Do not allow subclasses to change behavior, except by overriding ErrorMessage().
void DelayedHandlerAction() final;
protected: protected:
// If default-constructed with empty caption, it makes no message box. //! If default-constructed with empty caption, it makes no message box.
explicit MessageBoxException( const TranslatableString &caption = {} ); explicit MessageBoxException(
const TranslatableString &caption = {} //!< Shown in message box's frame; not the actual message
);
~MessageBoxException() override; ~MessageBoxException() override;
MessageBoxException( const MessageBoxException& ); MessageBoxException( const MessageBoxException& );
// Format a default error message for this exception. //! %Format the error message for this exception.
virtual TranslatableString ErrorMessage() const = 0; virtual TranslatableString ErrorMessage() const = 0;
private: private:
TranslatableString caption; TranslatableString caption; //!< Stored caption
mutable bool moved { false }; mutable bool moved { false }; //!< Whether @c *this has been the source of a copy
}; };
/// \brief A MessageBoxException that shows a given, unvarying string. //! A MessageBoxException that shows a given, unvarying string.
class SimpleMessageBoxException /* not final */ : public MessageBoxException class SimpleMessageBoxException /* not final */ : public MessageBoxException
{ {
public: public:
explicit SimpleMessageBoxException( const TranslatableString &message_, explicit SimpleMessageBoxException(
const TranslatableString &caption = XO("Message") ) const TranslatableString &message_, //<! Message to show
const TranslatableString &caption = XO("Message") //<! Short caption in frame around message
)
: MessageBoxException{ caption } : MessageBoxException{ caption }
, message{ message_ } , message{ message_ }
{} {}
@ -88,11 +91,11 @@ public:
virtual TranslatableString ErrorMessage() const override; virtual TranslatableString ErrorMessage() const override;
private: private:
TranslatableString message; TranslatableString message; //!< Stored message
}; };
/// \brief performs the delayed configured action, when invoked. //! A default template parameter for @ref GuardedCall
struct DefaultDelayedHandlerAction struct DefaultDelayedHandlerAction
{ {
void operator () (AudacityException *pException) const void operator () (AudacityException *pException) const
@ -102,26 +105,32 @@ struct DefaultDelayedHandlerAction
} }
}; };
/// \brief SimpleGuard classes add the second argument of GuardedCall: //! A default template parameter for @ref GuardedCall<R>
/// Frequently useful converter of all exceptions to some failure constant /*! @tparam R return type from GuardedCall (or convertible to it) */
template <typename R> struct SimpleGuard template <typename R> struct SimpleGuard
{ {
explicit SimpleGuard( R value ) : m_value{ value } {} explicit SimpleGuard(
R value //!< The value to return from GurdedCall when an exception is handled
)
: m_value{ value } {}
R operator () ( AudacityException * ) const { return m_value; } R operator () ( AudacityException * ) const { return m_value; }
const R m_value; const R m_value;
}; };
/// \brief SimpleGuard specialization that returns bool, and defines Default //! Specialization of SimpleGuard, also defining a default value
template<> struct SimpleGuard<bool> template<> struct SimpleGuard<bool>
{ {
explicit SimpleGuard( bool value ) : m_value{ value } {} explicit SimpleGuard(
bool value //!< The value to return from @ref GaurdedCall when an exception is handled
)
: m_value{ value } {}
bool operator () ( AudacityException * ) const { return m_value; } bool operator () ( AudacityException * ) const { return m_value; }
static SimpleGuard Default() static SimpleGuard Default()
{ return SimpleGuard{ false }; } { return SimpleGuard{ false }; }
const bool m_value; const bool m_value;
}; };
/// \brief SimpleGuard specialization that returns nothing, and defines Default //! Specialization of SimpleGuard, also defining a default value
template<> struct SimpleGuard<void> template<> struct SimpleGuard<void>
{ {
SimpleGuard() {} SimpleGuard() {}
@ -129,33 +138,36 @@ template<> struct SimpleGuard<void>
static SimpleGuard Default() { return {}; } static SimpleGuard Default() { return {}; }
}; };
//! Convert a value to a handler function returning that value, suitable for @ref GuardedCall<R>
template < typename R > template < typename R >
SimpleGuard< R > MakeSimpleGuard( R value ) SimpleGuard< R > MakeSimpleGuard( R value )
{ return SimpleGuard< R >{ value }; } { return SimpleGuard< R >{ value }; }
//! Convert a value to a no-op handler function, suitable for @ref GuardedCall<void>
inline SimpleGuard< void > MakeSimpleGuard() { return {}; } inline SimpleGuard< void > MakeSimpleGuard() { return {}; }
/*** /*!
\brief GuardedCall performs a body action, and provided there is no Executes a given function (typically a lamba), in any thread.
exception a handler action on completion. If there is an exception,
it queues up the delayed handler action for execution later in
the idle event loop
The template is rather configurable, and default behaviours can be
overridden. GuardedCall makes use of SimpleGuard for the handler action.
GuardedCall calls the body function (usually a lambda) inside a try block.
The handler intercepts exceptions, and is passed nullptr if the If there is any exception, can invoke another given function as handler, which may rethrow that or
exception is of a type not defined by Audacity. It may return a value another exception, but usually just returns the value for the GuardedCall.
for the guarded call or throw the same or another exception.
The handler executes in the same thread as the body.
If the handler is passed non-null and does not throw, then delayedHandler If AudacityException is handled, then it queues up a delayed handler action for execution later in
executes later in the main thread, in idle time of the event loop. the event loop at idle time, on the main thread; typically this informs the user of the error.
The default delayed handler action is simply to invoke a method of the AudacityException, but this
too can be specified otherwise by a third function.
@tparam R Return type, defaulted to void, or else the only explicit template parameter
@tparam F1 deduced type of body function; takes no arguments, returns @b R
@tparam F2 deduced type of handler function, or defaulted to @ref SimpleGuard<R>;
takes pointer to AudacityException, which is null when some other type of exception is caught;
return value is converted to @b R
@tparam F3 deduced type of delayed handler function, if a nondefault argument is given;
takes pointer to AudacityException, return value is unused
*/ */
template < template <
typename R = void, // return type typename R = void,
typename F1, // function object with signature R() typename F1, // function object with signature R()
@ -165,10 +177,12 @@ template <
typename F3 = typename F3 =
DefaultDelayedHandlerAction // Any( AudacityException * ), ignore return DefaultDelayedHandlerAction // Any( AudacityException * ), ignore return
> >
R GuardedCall //! Execute some code on any thread; catch any AudacityException; enqueue error report on the main thread
( const F1 &body, R GuardedCall(
const F2 &handler = F2::Default(), const F1 &body, //!< typically a lambda
const F3 &delayedHandler = {} ) const F2 &handler = F2::Default(), //!< default just returns false or void; see also @ref MakeSimpleGuard
const F3 &delayedHandler = {} //!< called later in the main thread, passing it a stored exception; usually defaulted
)
{ {
try { return body(); } try { return body(); }
catch ( AudacityException &e ) { catch ( AudacityException &e ) {