diff options
Diffstat (limited to 'src/corelib/concurrent/qtconcurrentexception.cpp')
-rw-r--r-- | src/corelib/concurrent/qtconcurrentexception.cpp | 228 |
1 files changed, 228 insertions, 0 deletions
diff --git a/src/corelib/concurrent/qtconcurrentexception.cpp b/src/corelib/concurrent/qtconcurrentexception.cpp new file mode 100644 index 0000000..cce1c31 --- /dev/null +++ b/src/corelib/concurrent/qtconcurrentexception.cpp @@ -0,0 +1,228 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the QtCore module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain +** additional rights. These rights are described in the Nokia Qt LGPL +** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qtconcurrentexception.h" + +#ifndef QT_NO_QFUTURE +#ifndef QT_NO_EXCEPTIONS + +QT_BEGIN_NAMESPACE + +/*! + \class QtConcurrent::Exception + \brief The Exception class provides a base class for exceptions that can transferred across threads. + \since 4.4 + + Qt Concurrent supports throwing and catching exceptions across thread + boundaries, provided that the exception inherit from QtConcurrent::Exception + and implement two helper functions: + + \snippet doc/src/snippets/code/src_corelib_concurrent_qtconcurrentexception.cpp 0 + + QtConcurrent::Exception subclasses must be thrown by value and + caught by reference: + + \snippet doc/src/snippets/code/src_corelib_concurrent_qtconcurrentexception.cpp 1 + + If you throw an exception that is not a subclass of QtConcurrent::Exception, + the Qt Concurrent functions will throw a QtConcurrent::UnhandledException + in the receiver thread. + + When using QFuture, transferred exceptions willl be thrown when calling the following functions: + \list + \o QFuture::waitForFinished() + \o QFuture::result() + \o QFuture::resultAt() + \o QFuture::results() + \endlist +*/ + +/*! + \fn QtConcurrent::Exception::raise() const + In your QtConcurrent::Exception subclass, reimplement raise() like this: + + \snippet doc/src/snippets/code/src_corelib_concurrent_qtconcurrentexception.cpp 2 +*/ + +/*! + \fn QtConcurrent::Exception::clone() const + In your QtConcurrent::Exception subclass, reimplement clone() like this: + + \snippet doc/src/snippets/code/src_corelib_concurrent_qtconcurrentexception.cpp 3 +*/ + +/*! + \class QtConcurrent::UnhandledException + + \brief The UnhandledException class represents an unhandled exception in a worker thread. + \since 4.4 + + If a worker thread throws an exception that is not a subclass of QtConcurrent::Exception, + the Qt Concurrent functions will throw a QtConcurrent::UnhandledException + on the receiver thread side. + + Inheriting from this class is not supported. +*/ + +/*! + \fn QtConcurrent::UnhandledException::raise() const + \internal +*/ + +/*! + \fn QtConcurrent::UnhandledException::clone() const + \internal +*/ + +namespace QtConcurrent +{ + +void Exception::raise() const +{ + Exception e = *this; + throw e; +} + +Exception *Exception::clone() const +{ + return new Exception(*this); +} + +void UnhandledException::raise() const +{ + UnhandledException e = *this; + throw e; +} + +Exception *UnhandledException::clone() const +{ + return new UnhandledException(*this); +} + +#ifndef qdoc + +namespace internal { + +class Base +{ +public: + Base(Exception *exception) + : exception(exception), refCount(1), hasThrown(false) { } + ~Base() { delete exception; } + + Exception *exception; + QAtomicInt refCount; + bool hasThrown; +}; + +ExceptionHolder::ExceptionHolder(Exception *exception) +: base(new Base(exception)) {} + +ExceptionHolder::ExceptionHolder(const ExceptionHolder &other) +: base(other.base) +{ + base->refCount.ref(); +} + +void ExceptionHolder::operator=(const ExceptionHolder &other) +{ + if (base == other.base) + return; + + if (base->refCount.deref() == false) + delete base; + + base = other.base; + base->refCount.ref(); +} + +ExceptionHolder::~ExceptionHolder() +{ + if (base->refCount.deref() == 0) + delete base; +} + +Exception *ExceptionHolder::exception() const +{ + return base->exception; +} + +void ExceptionStore::setException(const Exception &e) +{ + if (hasException() == false) + exceptionHolder = ExceptionHolder(e.clone()); +} + +bool ExceptionStore::hasException() const +{ + return (exceptionHolder.exception() != 0); +} + +ExceptionHolder ExceptionStore::exception() +{ + return exceptionHolder; +} + +void ExceptionStore::throwPossibleException() +{ + /* On win32-g++, with GCC 3.4.2 std::uncaught_exception() isn't reliable. */ + if (hasException() +#ifndef Q_CC_MINGW + && std::uncaught_exception() == false +#endif + ) { + exceptionHolder.base->hasThrown = true; + exceptionHolder.exception()->raise(); + } +} + +bool ExceptionStore::hasThrown() const { return exceptionHolder.base->hasThrown; } + +} // namespace internal + +#endif //qdoc + +} // namespace QtConcurrent + +QT_END_NAMESPACE + +#endif // QT_NO_EXCEPTIONS +#endif // QT_NO_CONCURRENT |