You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
406 lines
12 KiB
406 lines
12 KiB
#ifndef ERROR_MAP_HXX
|
|
#define ERROR_MAP_HXX
|
|
|
|
// @<COPYRIGHT_START>@
|
|
// ===============================================
|
|
// Copyright 2006 UGS Corp. All Rights Reserved.
|
|
// ===============================================
|
|
// @<COPYRIGHT_END>@
|
|
|
|
/**
|
|
@file
|
|
|
|
Set-based error reporting and enquiry.
|
|
Set-based functions report errors in two different ways.
|
|
|
|
1. *Hard* errors - throw an IFail object.
|
|
Execution is passed rapidly back to an enclosing catch block.
|
|
Any returned objects can, and should be, destroyed as usual. No other guarantee is made about program state.
|
|
An error is hard if:
|
|
- You could (in some valid implementation) find the same error on an empty-set input.
|
|
- The error has nothing to do with the current set member (array index), or any closely related object.
|
|
- It would be insane to continue execution.
|
|
|
|
2. *Soft* errors - return an ErrorMap object.
|
|
Processing of the current set member is aborted, and iteration over the next set member will begin.
|
|
There must be no observable state change for the aborted set member.
|
|
An error is soft if:
|
|
- There are no side effects from the current iteration, or the side effects have been undone.
|
|
- The error is associated with an individual set member (array index), or a closely related object.
|
|
- It is sensible to continue execution.
|
|
*/
|
|
|
|
/**
|
|
\page error_map_exception_policy ErrorMap exception policy
|
|
Error map additions may throw an IFail exception rather than return,
|
|
depending on the current exception policy.
|
|
See class Teamcenter::Configuration::ExceptionPolicy for details.
|
|
*/
|
|
|
|
#include <base_utils/SharedPtr.hxx>
|
|
#include <base_utils/TcBaseTypes.hxx>
|
|
#include <tc/tc_startup.h>
|
|
#include <base_utils/ErrorStoreBase.hxx>
|
|
#include <error.h>
|
|
|
|
class IFail;
|
|
class ResultStatus;
|
|
class status_t;
|
|
|
|
#include <fclasses/libfclasses_exports.h>
|
|
// \ref doxygen_namespace_bug
|
|
namespace Teamcenter
|
|
{
|
|
class Error;
|
|
class ExceptionPolicy;
|
|
|
|
// Implementation details.
|
|
namespace Private
|
|
{
|
|
/// \brief Take ownership of error stack into an Error object.
|
|
/// *Clear* the error stack ready for later use.
|
|
/// \ref error_map_exception_policy
|
|
FCLASSES_API Error takeErrorStack( int ifail );
|
|
/// \brief Take ownership of error stack into an Error object, and *clear*.
|
|
/// *Clear* the error stack ready for later use.
|
|
/// \ref error_map_exception_policy
|
|
FCLASSES_API Error takeErrorStack( IFail const& ifail );
|
|
/// \brief Take ownership of error stack into an Error object, and *clear*.
|
|
/// *Clear* the error stack ready for later use.
|
|
/// \ref error_map_exception_policy
|
|
FCLASSES_API Error takeErrorStack( status_t const& status );
|
|
|
|
/// \brief Read error stack into an Error object.
|
|
/// *Retain* the error stack.
|
|
/// \ref error_map_exception_policy
|
|
FCLASSES_API Error readErrorStack( int ifail );
|
|
|
|
/// \brief Push ifail to error stach and create an Error object.
|
|
/// *Retain* the error stack.
|
|
/// \ref error_map_exception_policy
|
|
FCLASSES_API Error pushErrorStack( int ifail, const char *s1=0, const char *s2=0, const char *s3=0, const char *s4=0, const char *s5=0, const char *s6=0, const char *s7=0 );
|
|
}
|
|
|
|
/**
|
|
\brief The most-recent error, and related information.
|
|
If required, we may turn this into an iterable error list, starting with the most recent.
|
|
|
|
If a function returns an Error, this can be tested for goodness in ResultStatus style...
|
|
sample: \code
|
|
// Declare function
|
|
Error func1( argdecls... );
|
|
try
|
|
{
|
|
// Call function returning an Error.
|
|
ResultStatus ithrow = func1( args... );
|
|
}
|
|
catch ( Ifail& )
|
|
{
|
|
// Handle error.
|
|
}
|
|
\endcode
|
|
|
|
\note
|
|
Default constructor, copy and assign required for std container insertion.
|
|
*/
|
|
class FCLASSES_API Error
|
|
{
|
|
public:
|
|
/// ITK_ok "error".
|
|
inline Error();
|
|
inline ~Error();
|
|
// Default copy and assign.
|
|
// Error( Error const& );
|
|
// Error& operator=( Error const& );
|
|
|
|
/// Is the most-recent ifail ITK_ok?
|
|
inline bool isOk() const;
|
|
/// Is the most-recent ifail not ITK_ok?
|
|
inline bool isError() const;
|
|
|
|
/// Integer ifail, errorMessage.
|
|
inline int ifail() const;
|
|
inline std::string errorMessage() const;
|
|
/// Throw IFail if not ITK_ok.
|
|
operator ResultStatus() const;
|
|
|
|
private:
|
|
friend Error Teamcenter::Private::takeErrorStack( int ifail );
|
|
friend Error Teamcenter::Private::takeErrorStack( IFail const& ifail );
|
|
friend Error Teamcenter::Private::takeErrorStack( status_t const& status );
|
|
|
|
friend Error Teamcenter::Private::readErrorStack( int ifail );
|
|
friend Error Teamcenter::Private::pushErrorStack( int ifail, const char *s1, const char *s2, const char *s3, const char *s4, const char *s5, const char *s6, const char *s7 );
|
|
|
|
/// Construct with ifail value, errorMessage.
|
|
inline explicit Error( int ifail );
|
|
|
|
/// Error data, cf. EMH_ask_errors.
|
|
int m_ifail;
|
|
std::string m_errorMessage;
|
|
};
|
|
|
|
/**
|
|
\brief An indexed map of errors.
|
|
Filters out ITK_ok errors on addition.
|
|
ErrorMap implements a set-based style of error reporting, very different
|
|
from Teamcenter ITK-style error stacks. We expect clients to return
|
|
ErrorMaps from set-based functions, and the class is optimized for this use case.
|
|
Clietns will associate each Error with an array index identifier. The ErrorMap class
|
|
_conceptually_ stacks up Errors under these index identifiers, returning the most recent.
|
|
Clients may need to re-map index identifiers as they pass ErrorMaps up the call chain.
|
|
|
|
sample: \code
|
|
ErrorMap errors;
|
|
errors += func1( args... );
|
|
errors += func2( args... );
|
|
return errors;
|
|
\endcode
|
|
|
|
\note A std::map<size_t, Error> almost does the trick, however we want to introduce some
|
|
new functions of our own. Since we should not derive from std::map, let's wrap it instead.
|
|
*/
|
|
class FCLASSES_API ErrorMap
|
|
{
|
|
public:
|
|
/// Empty set - no errors.
|
|
inline ErrorMap();
|
|
|
|
// Copy and assign.
|
|
inline ErrorMap( ErrorMap const& );
|
|
inline ErrorMap& operator=( ErrorMap const& );
|
|
|
|
/// \brief Add an individual error to the error set.
|
|
/// Discard all but the most recent error.
|
|
ErrorMap& add( size_t id, Error const& error );
|
|
/// \brief Add an individual integer fail code to the error set.
|
|
/// Handle the ifail by taking ownership of (*clearing*) the current error stack.
|
|
inline ErrorMap& add( size_t id, int ifail );
|
|
/// \brief Add an individual IFail to the error set.
|
|
/// Handle the ifail by taking ownership of (*clearing*) the current error stack.
|
|
inline ErrorMap& add( size_t id, IFail const& ifail );
|
|
/// \brief Add an individual status_t to the error set.
|
|
/// Handle the ifail by taking ownership of (*clearing*) the current error stack.
|
|
inline ErrorMap& add( size_t id, status_t const& status );
|
|
/// \brief Update with the latest errors.
|
|
/// More recent (right) errors, replace older (this) errors.
|
|
ErrorMap& operator+=( ErrorMap const& right );
|
|
|
|
/// stl-like typedefs.
|
|
typedef size_t key_type;
|
|
typedef Error mapped_type;
|
|
typedef StdSmMap< size_t, Error >::Map::value_type value_type;
|
|
|
|
/// stl-like iterators.
|
|
typedef StdSmMap< size_t, Error >::Map::iterator iterator;
|
|
typedef StdSmMap< size_t, Error >::Map::const_iterator const_iterator;
|
|
|
|
/// stl-like map size.
|
|
inline size_t size() const;
|
|
/// stl-like is map empty?
|
|
inline bool empty() const;
|
|
|
|
/// stl-like map lookup.
|
|
iterator find( size_t id );
|
|
const_iterator find( size_t id ) const;
|
|
|
|
/// stl-like iteration.
|
|
inline iterator begin();
|
|
inline iterator end();
|
|
inline const_iterator begin() const;
|
|
inline const_iterator end() const;
|
|
|
|
private:
|
|
typedef StdSmMap< size_t, Error >::Map StdErrorMap;
|
|
|
|
/// Ensure m_map is allocated, and return a reference.s
|
|
inline StdErrorMap& ensureMap();
|
|
|
|
/// Owned errors are stored in this map.
|
|
/// \note Pointer so that we can get cheap copies
|
|
/// (return ErrorMap; is common usage).
|
|
/// \note Allocated when first needed. Keep empty ErrorMap cheap.
|
|
shared_ptr< StdErrorMap > m_map;
|
|
|
|
/// Empty map for iteration when m_map is unallocated.
|
|
/// \note A class-static empty error map fails to link on wnti32
|
|
/// when used in inline functions (error LNK2001; 2006/04/18).
|
|
/// And we prefer the inlining over space, especially for end() (think loops).
|
|
StdErrorMap m_emptyMap;
|
|
};
|
|
|
|
/**
|
|
\brief Change from a bulk-reporting ErrorMap policy to an immediate-throw IFail exception policy.
|
|
RAII class for temporary change and restore.
|
|
*/
|
|
class FCLASSES_API ExceptionPolicy
|
|
{
|
|
public:
|
|
/// Change from a bulk-reporting to an immediate-throw policy
|
|
/// for the lifetime of this object.
|
|
/// \ref error_map_exception_policy
|
|
ExceptionPolicy();
|
|
/// Maybe change from a bulk-reporting to an immediate-throw policy
|
|
/// for the lifetime of this object.
|
|
/// Note that any active throw-on-error policy always wins!
|
|
/// \param[in] throwIfail.
|
|
/// If true, set immediate-throw
|
|
/// If false, leave the policy unchanged.
|
|
/// \ref error_map_exception_policy
|
|
explicit ExceptionPolicy( bool throwOnError );
|
|
/// Restore previous ErrorMap bulk-reporting policy (if different).
|
|
~ExceptionPolicy();
|
|
|
|
/// Get current immendiate-throw policy.
|
|
/// \ref error_map_exception_policy
|
|
static bool throwOnError();
|
|
|
|
private:
|
|
// Prohibit copy and assign.
|
|
ExceptionPolicy( ExceptionPolicy const& );
|
|
ExceptionPolicy& operator=( ExceptionPolicy const& );
|
|
|
|
/// Need to change state of ErrorMap::s_throwOnError?
|
|
bool m_setThrowOnError;
|
|
|
|
/// Bulk-reporting policy - false by default.
|
|
static bool s_throwOnError;
|
|
static bool s_overrideThrowOnError;
|
|
friend class IgnoreExceptionPolicy;
|
|
};
|
|
|
|
class FCLASSES_API IgnoreExceptionPolicy
|
|
{
|
|
public:
|
|
IgnoreExceptionPolicy();
|
|
~IgnoreExceptionPolicy();
|
|
};
|
|
|
|
//// Implementation details
|
|
|
|
inline Error::Error()
|
|
: m_ifail( ITK_ok ), m_errorMessage()
|
|
{
|
|
}
|
|
|
|
inline Error::~Error()
|
|
{
|
|
// Required to prevent warnings in std::vector-on-sm template compilation
|
|
// with msvc7.1 compiler.
|
|
}
|
|
|
|
inline Error::Error( int ifail )
|
|
: m_ifail( ifail ), m_errorMessage()
|
|
{
|
|
if ( ifail != ITK_ok )
|
|
{
|
|
m_errorMessage = Teamcenter::ErrorStoreBase::getInstance().ask_last_message( ifail ); // ifail must already been in ERROR_store
|
|
}
|
|
}
|
|
|
|
inline bool Error::isOk() const
|
|
{
|
|
return m_ifail == ITK_ok;
|
|
}
|
|
|
|
inline bool Error::isError() const
|
|
{
|
|
return m_ifail != ITK_ok;
|
|
}
|
|
|
|
inline int Error::ifail() const
|
|
{
|
|
return m_ifail;
|
|
}
|
|
|
|
inline std::string Error::errorMessage() const
|
|
{
|
|
return m_errorMessage;
|
|
}
|
|
|
|
inline ErrorMap::ErrorMap()
|
|
: m_map(),
|
|
m_emptyMap()
|
|
{
|
|
}
|
|
|
|
inline ErrorMap::ErrorMap( ErrorMap const& errorMap )
|
|
: m_map( errorMap.m_map ),
|
|
m_emptyMap()
|
|
{
|
|
}
|
|
|
|
inline ErrorMap& ErrorMap::operator=( ErrorMap const& errorMap )
|
|
{
|
|
// Deliberately not checking for self-assignment.
|
|
// Exception-safe classes rarely need to whatever QAZ says.
|
|
m_map = errorMap.m_map;
|
|
// No need to copy m_emptyMap. They are both empty!
|
|
return *this;
|
|
}
|
|
|
|
inline ErrorMap& ErrorMap::add( size_t id, int ifail )
|
|
{
|
|
return add( id, Teamcenter::Private::takeErrorStack( ifail ) );
|
|
}
|
|
|
|
inline ErrorMap& ErrorMap::add( size_t id, IFail const& ifail )
|
|
{
|
|
return add( id, Teamcenter::Private::takeErrorStack( ifail ) );
|
|
}
|
|
|
|
inline ErrorMap& ErrorMap::add( size_t id, status_t const& status )
|
|
{
|
|
return add( id, Teamcenter::Private::takeErrorStack( status ) );
|
|
}
|
|
|
|
inline size_t ErrorMap::size() const
|
|
{
|
|
if ( m_map )
|
|
return m_map->size();
|
|
else
|
|
return 0;
|
|
}
|
|
inline bool ErrorMap::empty() const
|
|
{
|
|
if ( m_map )
|
|
return m_map->empty();
|
|
else
|
|
return true;
|
|
}
|
|
|
|
inline ErrorMap::iterator ErrorMap::begin()
|
|
{
|
|
if ( m_map )
|
|
return m_map->begin();
|
|
else
|
|
return m_emptyMap.begin();
|
|
}
|
|
|
|
inline ErrorMap::iterator ErrorMap::end()
|
|
{
|
|
if ( m_map )
|
|
return m_map->end();
|
|
else
|
|
return m_emptyMap.end();
|
|
}
|
|
|
|
inline ErrorMap::const_iterator ErrorMap::begin() const
|
|
{
|
|
if ( m_map )
|
|
return m_map->begin();
|
|
else
|
|
return m_emptyMap.begin();
|
|
}
|
|
|
|
inline ErrorMap::const_iterator ErrorMap::end() const
|
|
{
|
|
if ( m_map )
|
|
return m_map->end();
|
|
else
|
|
return m_emptyMap.end();
|
|
}
|
|
} // namespace Teamcenter
|
|
#include <fclasses/libfclasses_undef.h>
|
|
#endif
|