// Scroll down to line 85 for example of usage
// _________________[uncaught_exception_count.hpp]_____________________ //
// Copyright Evgeny Panasyuk 2012.
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at
// http://w...content-available-to-author-only...t.org/LICENSE_1_0.txt)
// e-mail: E?????[dot]P???????[at]gmail.???
#ifndef BOOST_UNCAUGHT_EXCEPTION_COUNT_HPP_39A1E90FC11647e08D5F6ED16CD34B34
#define BOOST_UNCAUGHT_EXCEPTION_COUNT_HPP_39A1E90FC11647e08D5F6ED16CD34B34
#if defined(_MSC_VER) || defined(__GNUG__) || defined(__CLANG__)
#define BOOST_UNCAUGHT_EXCEPTION_COUNT_SUPPORTED 1
#endif
namespace boost
{
namespace exception_detail
{
template<typename To> inline
To *unrelated_pointer_cast(void *from)
{
return static_cast<To*>(from);
}
}
// uncaught_exception_count is a function similar to std::uncaught_exception from standard library,
// but instead of boolean result it returns unsigned int showing current count of uncaught exceptions.
#if defined(_MSC_VER)
namespace exception_detail
{
extern "C" char * __cdecl _getptd();
}
inline unsigned uncaught_exception_count()
{
// MSVC specific. Tested on {MSVC2005SP1,MSVC2008SP1,MSVC2010SP1,MSVC2012}x{x32,x64}.
return *exception_detail::unrelated_pointer_cast<unsigned>
(
exception_detail::_getptd() + (sizeof(void*)==8 ? 0x100 : 0x90)
);
}
#elif defined(__GNUG__) || defined(__CLANG__)
namespace exception_detail
{
extern "C" char * __cxa_get_globals();
}
inline unsigned uncaught_exception_count()
{
// Tested on {Clang 3.2,GCC 3.4.6,GCC 4.1.2,GCC 4.4.6,GCC 4.4.7}x{x32,x64}
return *exception_detail::unrelated_pointer_cast<unsigned>
(
exception_detail::__cxa_get_globals() + (sizeof(void*)==8 ? 0x8 : 0x4)
);
}
#endif
// Within one scope uncaught_exception_count can be changed only by +1.
// uncaught_exception_count_latch is primitive which helps to determine such transition.
// Internally it stores and compares only last bit of uncaught_exception_count value
#ifdef BOOST_UNCAUGHT_EXCEPTION_COUNT_SUPPORTED
class uncaught_exception_count_latch
{
unsigned char enter_state;
public:
uncaught_exception_count_latch()
: enter_state(static_cast<unsigned char>( uncaught_exception_count() & 1 ))
{
}
bool transitioned() const
{
return enter_state != ( uncaught_exception_count() & 1 );
}
};
#endif
}
#endif
// ______________[end of uncaught_exception_count.hpp]_________________ //
#include <iostream>
#include <ostream>
using namespace std;
void success()
{
cout << "\tsuccess()" << endl;
}
void failure()
{
cout << "\tfailure()" << endl;
}
class ScopeGuard
{
bool commited;
public:
ScopeGuard() : commited(false) {}
bool commit()
{
commited = true;
}
~ScopeGuard()
{
if(commited)
success();
else
failure();
}
};
class ScopeAction
{
boost::uncaught_exception_count_latch exception_state;
public:
~ScopeAction()
{
if(exception_state.transitioned())
failure();
else
success();
}
};
int main()
{
{
cout << "ScopeGuard:" << endl;
try
{
ScopeGuard guard;
throw 1;
guard.commit();
}
catch(int) {}
{
ScopeGuard guard;
// ...
guard.commit();
}
}
{
cout << "ScopeAction:" << endl;
try
{
ScopeAction guard;
throw 1;
}
catch(int) {}
{
ScopeAction guard;
// ...
}
}
}