1/****************************************************************************
2**
3** Copyright (C) 2016 The Qt Company Ltd.
4** Contact: https://www.qt.io/licensing/
5**
6** This file is part of the QtCore module of the Qt Toolkit.
7**
8** $QT_BEGIN_LICENSE:LGPL$
9** Commercial License Usage
10** Licensees holding valid commercial Qt licenses may use this file in
11** accordance with the commercial license agreement provided with the
12** Software or, alternatively, in accordance with the terms contained in
13** a written agreement between you and The Qt Company. For licensing terms
14** and conditions see https://www.qt.io/terms-conditions. For further
15** information use the contact form at https://www.qt.io/contact-us.
16**
17** GNU Lesser General Public License Usage
18** Alternatively, this file may be used under the terms of the GNU Lesser
19** General Public License version 3 as published by the Free Software
20** Foundation and appearing in the file LICENSE.LGPL3 included in the
21** packaging of this file. Please review the following information to
22** ensure the GNU Lesser General Public License version 3 requirements
23** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
24**
25** GNU General Public License Usage
26** Alternatively, this file may be used under the terms of the GNU
27** General Public License version 2.0 or (at your option) the GNU General
28** Public license version 3 or any later version approved by the KDE Free
29** Qt Foundation. The licenses are as published by the Free Software
30** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
31** included in the packaging of this file. Please review the following
32** information to ensure the GNU General Public License requirements will
33** be met: https://www.gnu.org/licenses/gpl-2.0.html and
34** https://www.gnu.org/licenses/gpl-3.0.html.
35**
36** $QT_END_LICENSE$
37**
38****************************************************************************/
39
40#include "qexception.h"
41#include "QtCore/qshareddata.h"
42
43#if !defined(QT_NO_EXCEPTIONS) || defined(Q_CLANG_QDOC)
44
45QT_BEGIN_NAMESPACE
46
47/*!
48 \class QException
49 \inmodule QtCore
50 \brief The QException class provides a base class for exceptions that can transferred across threads.
51 \since 5.0
52
53 Qt Concurrent supports throwing and catching exceptions across thread
54 boundaries, provided that the exception inherit from QException
55 and implement two helper functions:
56
57 \snippet code/src_corelib_thread_qexception.cpp 0
58
59 QException subclasses must be thrown by value and
60 caught by reference:
61
62 \snippet code/src_corelib_thread_qexception.cpp 1
63
64 If you throw an exception that is not a subclass of QException,
65 the Qt functions will throw a QUnhandledException
66 in the receiver thread.
67
68 When using QFuture, transferred exceptions will be thrown when calling the following functions:
69 \list
70 \li QFuture::waitForFinished()
71 \li QFuture::result()
72 \li QFuture::resultAt()
73 \li QFuture::results()
74 \endlist
75*/
76
77/*!
78 \fn QException::raise() const
79 In your QException subclass, reimplement raise() like this:
80
81 \snippet code/src_corelib_thread_qexception.cpp 2
82*/
83
84/*!
85 \fn QException::clone() const
86 In your QException subclass, reimplement clone() like this:
87
88 \snippet code/src_corelib_thread_qexception.cpp 3
89*/
90
91/*!
92 \class QUnhandledException
93 \inmodule QtCore
94
95 \brief The UnhandledException class represents an unhandled exception in a worker thread.
96 \since 5.0
97
98 If a worker thread throws an exception that is not a subclass of QException,
99 the Qt functions will throw a QUnhandledException
100 on the receiver thread side.
101
102 Inheriting from this class is not supported.
103*/
104
105/*!
106 \fn QUnhandledException::raise() const
107 \internal
108*/
109
110/*!
111 \fn QUnhandledException::clone() const
112 \internal
113*/
114
115QException::~QException()
116#ifdef Q_COMPILER_NOEXCEPT
117 noexcept
118#else
119 throw()
120#endif
121{
122 // must stay empty until ### Qt 6
123}
124
125void QException::raise() const
126{
127 QException e = *this;
128 throw e;
129}
130
131QException *QException::clone() const
132{
133 return new QException(*this);
134}
135
136QUnhandledException::~QUnhandledException()
137#ifdef Q_COMPILER_NOEXCEPT
138 noexcept
139#else
140 throw()
141#endif
142{
143 // must stay empty until ### Qt 6
144}
145
146void QUnhandledException::raise() const
147{
148 QUnhandledException e = *this;
149 throw e;
150}
151
152QUnhandledException *QUnhandledException::clone() const
153{
154 return new QUnhandledException(*this);
155}
156
157#if !defined(Q_CLANG_QDOC)
158
159namespace QtPrivate {
160
161class Base : public QSharedData
162{
163public:
164 Base(QException *exception)
165 : exception(exception), hasThrown(false) { }
166 ~Base() { delete exception; }
167
168 QException *exception;
169 bool hasThrown;
170};
171
172ExceptionHolder::ExceptionHolder(QException *exception)
173: base(exception ? new Base(exception) : nullptr) {}
174
175ExceptionHolder::ExceptionHolder(const ExceptionHolder &other)
176: base(other.base)
177{}
178
179void ExceptionHolder::operator=(const ExceptionHolder &other)
180{
181 base = other.base;
182}
183
184ExceptionHolder::~ExceptionHolder()
185{}
186
187QException *ExceptionHolder::exception() const
188{
189 if (!base)
190 return nullptr;
191 return base->exception;
192}
193
194void ExceptionStore::setException(const QException &e)
195{
196 if (hasException() == false)
197 exceptionHolder = ExceptionHolder(e.clone());
198}
199
200bool ExceptionStore::hasException() const
201{
202 return (exceptionHolder.exception() != nullptr);
203}
204
205ExceptionHolder ExceptionStore::exception()
206{
207 return exceptionHolder;
208}
209
210void ExceptionStore::throwPossibleException()
211{
212 if (hasException() ) {
213 exceptionHolder.base->hasThrown = true;
214 exceptionHolder.exception()->raise();
215 }
216}
217
218bool ExceptionStore::hasThrown() const { return exceptionHolder.base->hasThrown; }
219
220} // namespace QtPrivate
221
222#endif //Q_CLANG_QDOC
223
224QT_END_NAMESPACE
225
226#endif // QT_NO_EXCEPTIONS
227

source code of qtbase/src/corelib/thread/qexception.cpp