PageRenderTime 54ms CodeModel.GetById 21ms RepoModel.GetById 0ms app.codeStats 0ms

/src/qt/qtbase/src/corelib/tools/qsharedpointer.cpp

https://gitlab.com/x33n/phantomjs
C++ | 1336 lines | 86 code | 87 blank | 1163 comment | 13 complexity | 679f6d96a64b1793876dccfee411977d MD5 | raw file
  1. /****************************************************************************
  2. **
  3. ** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
  4. ** Contact: http://www.qt-project.org/legal
  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 Digia. For licensing terms and
  14. ** conditions see http://qt.digia.com/licensing. For further information
  15. ** use the contact form at http://qt.digia.com/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 2.1 as published by the Free Software
  20. ** Foundation and appearing in the file LICENSE.LGPL included in the
  21. ** packaging of this file. Please review the following information to
  22. ** ensure the GNU Lesser General Public License version 2.1 requirements
  23. ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
  24. **
  25. ** In addition, as a special exception, Digia gives you certain additional
  26. ** rights. These rights are described in the Digia Qt LGPL Exception
  27. ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
  28. **
  29. ** GNU General Public License Usage
  30. ** Alternatively, this file may be used under the terms of the GNU
  31. ** General Public License version 3.0 as published by the Free Software
  32. ** Foundation and appearing in the file LICENSE.GPL included in the
  33. ** packaging of this file. Please review the following information to
  34. ** ensure the GNU General Public License version 3.0 requirements will be
  35. ** met: http://www.gnu.org/copyleft/gpl.html.
  36. **
  37. **
  38. ** $QT_END_LICENSE$
  39. **
  40. ****************************************************************************/
  41. #include "qsharedpointer.h"
  42. // to be sure we aren't causing a namespace clash:
  43. #include "qshareddata.h"
  44. /*!
  45. \class QSharedPointer
  46. \inmodule QtCore
  47. \brief The QSharedPointer class holds a strong reference to a shared pointer
  48. \since 4.5
  49. \reentrant
  50. The QSharedPointer is an automatic, shared pointer in C++. It
  51. behaves exactly like a normal pointer for normal purposes,
  52. including respect for constness.
  53. QSharedPointer will delete the pointer it is holding when it goes
  54. out of scope, provided no other QSharedPointer objects are
  55. referencing it.
  56. A QSharedPointer object can be created from a normal pointer,
  57. another QSharedPointer object or by promoting a
  58. QWeakPointer object to a strong reference.
  59. \section1 Thread-Safety
  60. QSharedPointer and QWeakPointer are thread-safe and operate
  61. atomically on the pointer value. Different threads can also access
  62. the QSharedPointer or QWeakPointer pointing to the same object at
  63. the same time without need for locking mechanisms.
  64. It should be noted that, while the pointer value can be accessed
  65. in this manner, QSharedPointer and QWeakPointer provide no
  66. guarantee about the object being pointed to. Thread-safety and
  67. reentrancy rules for that object still apply.
  68. \section1 Other Pointer Classes
  69. Qt also provides two other pointer wrapper classes: QPointer and
  70. QSharedDataPointer. They are incompatible with one another, since
  71. each has its very different use case.
  72. QSharedPointer holds a shared pointer by means of an external
  73. reference count (i.e., a reference counter placed outside the
  74. object). Like its name indicates, the pointer value is shared
  75. among all instances of QSharedPointer and QWeakPointer. The
  76. contents of the object pointed to by the pointer should not be
  77. considered shared, however: there is only one object. For that
  78. reason, QSharedPointer does not provide a way to detach or make
  79. copies of the pointed object.
  80. QSharedDataPointer, on the other hand, holds a pointer to shared
  81. data (i.e., a class derived from QSharedData). It does so by means
  82. of an internal reference count, placed in the QSharedData base
  83. class. This class can, therefore, detach based on the type of
  84. access made to the data being guarded: if it's a non-const access,
  85. it creates a copy atomically for the operation to complete.
  86. QExplicitlySharedDataPointer is a variant of QSharedDataPointer, except
  87. that it only detaches if QExplicitlySharedDataPointer::detach() is
  88. explicitly called (hence the name).
  89. QScopedPointer simply holds a pointer to a heap allocated object and
  90. deletes it in its destructor. This class is useful when an object needs to
  91. be heap allocated and deleted, but no more. QScopedPointer is lightweight,
  92. it makes no use of additional structure or reference counting.
  93. Finally, QPointer holds a pointer to a QObject-derived object, but it
  94. does so weakly. QWeakPointer has the same functionality, but its use for
  95. that function is deprecated.
  96. \section1 Optional pointer tracking
  97. A feature of QSharedPointer that can be enabled at compile-time for
  98. debugging purposes is a pointer tracking mechanism. When enabled,
  99. QSharedPointer registers in a global set all the pointers that it tracks.
  100. This allows one to catch mistakes like assigning the same pointer to two
  101. QSharedPointer objects.
  102. This function is enabled by defining the \tt{QT_SHAREDPOINTER_TRACK_POINTERS}
  103. macro before including the QSharedPointer header.
  104. It is safe to use this feature even with code compiled without the
  105. feature. QSharedPointer will ensure that the pointer is removed from the
  106. tracker even from code compiled without pointer tracking.
  107. Note, however, that the pointer tracking feature has limitations on
  108. multiple- or virtual-inheritance (that is, in cases where two different
  109. pointer addresses can refer to the same object). In that case, if a
  110. pointer is cast to a different type and its value changes,
  111. QSharedPointer's pointer tracking mechanism may fail to detect that the
  112. object being tracked is the same.
  113. \omit
  114. \secton1 QSharedPointer internals
  115. QSharedPointer has two "private" members: the pointer itself being tracked
  116. and a d-pointer. Those members are private to the class, but QSharedPointer
  117. is friends with QWeakPointer and other QSharedPointer with different
  118. template arguments. (On some compilers, template friends are not supported,
  119. so the members are technically public)
  120. The reason for keeping the pointer value itself outside the d-pointer is
  121. because of multiple inheritance needs. If you have two QSharedPointer
  122. objects of different pointer types, but pointing to the same object in
  123. memory, it could happen that the pointer values are different. The \tt
  124. differentPointers autotest exemplifies this problem. The same thing could
  125. happen in the case of virtual inheritance: a pointer of class matching
  126. the virtual base has different address compared to the pointer of the
  127. complete object. See the \tt virtualBaseDifferentPointers autotest for
  128. this problem.
  129. The d pointer is a pointer to QtSharedPointer::ExternalRefCountData, but it
  130. always points to one of the two classes derived from ExternalRefCountData.
  131. \section2 d-pointer
  132. \section3 QtSharedPointer::ExternalRefCountData
  133. It is basically a reference-counted reference-counter plus a pointer to the
  134. function to be used to delete the pointer. It has three members: \tt
  135. strongref, \tt weakref, and \tt destroyer. The strong reference counter is
  136. controlling the lifetime of the object tracked by QSharedPointer. A
  137. positive value indicates that the object is alive. It's also the number of
  138. QSharedObject instances that are attached to this Data.
  139. When the strong reference count decreases to zero, the object is deleted
  140. (see below for information on custom deleters). The strong reference count
  141. can also exceptionally be -1, indicating that there are no QSharedPointers
  142. attached to an object, which is tracked too. The only case where this is
  143. possible is that of QWeakPointers and QPointers tracking a QObject. Note
  144. that QWeakPointers tracking a QObject is a deprecated feature as of Qt 5.0,
  145. kept only for compatibility with Qt 4.x.
  146. The weak reference count controls the lifetime of the d-pointer itself.
  147. It can be thought of as an internal/intrusive reference count for
  148. ExternalRefCountData itself. This count is equal to the number of
  149. QSharedPointers and QWeakPointers that are tracking this object. In case
  150. the object is a QObject being tracked by QPointer, this number is increased
  151. by 1, since QObjectPrivate tracks it too.
  152. The third member is a pointer to the function that is used to delete the
  153. pointer being tracked. That happens when the destroy() function is called.
  154. The size of this class is the size of the two atomic ints plus the size of
  155. a pointer. On 32-bit architectures, that's 12 bytes, whereas on 64-bit ones
  156. it's 16 bytes. There is no padding.
  157. \section3 QtSharedPointer::ExternalRefCountWithCustomDeleter
  158. This class derives from ExternalRefCountData and is a template class. As
  159. template parameters, it has the type of the pointer being tracked (\tt T)
  160. and a \tt Deleter, which is anything. It adds two fields to its parent
  161. class, matching those template parameters: a member of type \tt Deleter and
  162. a member of type \tt T*. Those members are actually inside a template
  163. struct of type CustomDeleter, which is partially-specialized for normal
  164. deletion. See below for more details on that.
  165. The purpose of this class is to store the pointer to be deleted and the
  166. deleter code along with the d-pointer. This allows the last strong
  167. reference to call any arbitrary function that disposes of the object. For
  168. example, this allows calling QObject::deleteLater() on a given object.
  169. The pointer to the object is kept here because it needs to match the actual
  170. deleter function's parameters, regardless of what template argument the
  171. last QSharedPointer instance had.
  172. This class is never instantiated directly: the constructors and
  173. destructor are private and, in C++11, deleted. Only the create() function
  174. may be called to return an object of this type. See below for construction
  175. details.
  176. The size of this class depends on the size of \tt Deleter. If it's an empty
  177. functor (i.e., no members), ABIs generally assign it the size of 1. But
  178. given that it's followed by a pointer, padding bytes may be inserted so
  179. that the alignment of the class and of the pointer are correct. In that
  180. case, the size of this class is 12+4+4 = 20 bytes on 32-bit architectures,
  181. or 16+8+8 = 40 bytes on 64-bit architectures. If \tt Deleter is a function
  182. pointer, the size should be the same as the empty structure case. If \tt
  183. Deleter is a pointer to a member function (PMF), the size will be bigger
  184. and will depend on the ABI. For architectures using the Itanium C++ ABI, a
  185. PMF is twice the size of a normal pointer. In that case, the size of this
  186. structure will be 12+8+4 = 24 bytes on 32-bit architectures, 16+16+8 = 40
  187. bytes on 64-bit ones.
  188. If the deleter was not specified when creating the QSharedPointer object
  189. (i.e., if a standard \tt delete call is expected), then there's an
  190. optimization that avoids the need to store another function pointer in
  191. ExternalRefCountWithCustomDeleter. Instead, a template specialization makes
  192. a direct delete call. The size of the structure, in this case, is 12+4 = 16
  193. bytes on 32-bit architectures, 16+8 = 24 bytes on 64-bit ones.
  194. \section3 QtSharedPointer::ExternalRefCountWithContiguousData
  195. This class also derives from ExternalRefCountData and it is
  196. also a template class. The template parameter is the type \tt T of the
  197. class which QSharedPointer tracks. It adds only one member to its parent,
  198. which is of type \tt T (the actual type, not a pointer to it).
  199. The purpose of this class is to lay the \tt T object out next to the
  200. reference counts, saving one memory allocation per shared pointer. This
  201. is particularly interesting for small \tt T or for the cases when there
  202. are few if any QWeakPointer tracking the object. This class exists to
  203. implement the QSharedPointer::create() call.
  204. Like ExternalRefCountWithCustomDeleter, this class is never instantiated
  205. directly. This class also provides a create() member that returns the
  206. pointer, and hides its constructors and destructor. With C++11, they're
  207. deleted.
  208. The size of this class depends on the size of \tt T.
  209. \section3 Instantiating ExternalRefCountWithCustomDeleter and ExternalRefCountWithContiguousData
  210. Like explained above, these classes have private constructors. Moreover,
  211. they are not defined anywhere, so trying to call \tt{new ClassType} would
  212. result in a compilation or linker error. Instead, these classes must be
  213. constructed via their create() methods.
  214. Instead of instantiating the class by the normal way, the create() method
  215. calls \tt{operator new} directly with the size of the class, then calls
  216. the parent class's constructor only (that is, ExternalRefCountData's constructor).
  217. This ensures that the inherited members are initialised properly.
  218. After initialising the base class, the
  219. ExternalRefCountWithCustomDeleter::create() function initialises the new
  220. members directly, by using the placement \tt{operator new}. In the case
  221. of the ExternalRefCountWithContiguousData::create() function, the address
  222. to the still-uninitialised \tt T member is saved for the callee to use.
  223. The member is only initialised in QSharedPointer::create(), so that we
  224. avoid having many variants of the internal functions according to the
  225. arguments in use for calling the constructor.
  226. When initialising the parent class, the create() functions pass the
  227. address of the static deleter() member function. That is, when the
  228. destroy() function is called by QSharedPointer, the deleter() functions
  229. are called instead. These functions static_cast the ExternalRefCountData*
  230. parameter to their own type and execute their deletion: for the
  231. ExternalRefCountWithCustomDeleter::deleter() case, it runs the user's
  232. custom deleter, then destroys the deleter; for
  233. ExternalRefCountWithContiguousData::deleter, it simply calls the \tt T
  234. destructor directly.
  235. Only one non-inline function is required per template, which is
  236. the deleter() static member. All the other functions can be inlined.
  237. What's more, the address of deleter() is calculated only in code, which
  238. can be resolved at link-time if the linker can determine that the
  239. function lies in the current application or library module (since these
  240. classes are not exported, that is the case for Windows or for builds with
  241. \tt{-fvisibility=hidden}).
  242. \section3 Modifications due to pointer-tracking
  243. To ensure that pointers created with pointer-tracking enabled get
  244. un-tracked when destroyed, even if destroyed by code compiled without the
  245. feature, QSharedPointer modifies slightly the instructions of the
  246. previous sections.
  247. When ExternalRefCountWithCustomDeleter or
  248. ExternalRefCountWithContiguousData are used, their create() functions
  249. will set the ExternalRefCountData::destroyer function
  250. pointer to safetyCheckDeleter() instead. These static member functions
  251. simply call internalSafetyCheckRemove() before passing control to the
  252. normal deleter() function.
  253. If neither custom deleter nor QSharedPointer::create() are used, then
  254. QSharedPointer uses a custom deleter of its own: the normalDeleter()
  255. function, which simply calls \tt delete. By using a custom deleter, the
  256. safetyCheckDeleter() procedure described above kicks in.
  257. \endomit
  258. \sa QSharedDataPointer, QWeakPointer, QScopedPointer
  259. */
  260. /*!
  261. \class QWeakPointer
  262. \inmodule QtCore
  263. \brief The QWeakPointer class holds a weak reference to a shared pointer
  264. \since 4.5
  265. \reentrant
  266. The QWeakPointer is an automatic weak reference to a
  267. pointer in C++. It cannot be used to dereference the pointer
  268. directly, but it can be used to verify if the pointer has been
  269. deleted or not in another context.
  270. QWeakPointer objects can only be created by assignment from a
  271. QSharedPointer.
  272. It's important to note that QWeakPointer provides no automatic casting
  273. operators to prevent mistakes from happening. Even though QWeakPointer
  274. tracks a pointer, it should not be considered a pointer itself, since it
  275. doesn't guarantee that the pointed object remains valid.
  276. Therefore, to access the pointer that QWeakPointer is tracking, you must
  277. first promote it to QSharedPointer and verify if the resulting object is
  278. null or not. QSharedPointer guarantees that the object isn't deleted, so
  279. if you obtain a non-null object, you may use the pointer. See
  280. QWeakPointer::toStrongRef() for an example.
  281. QWeakPointer also provides the QWeakPointer::data() method that returns
  282. the tracked pointer without ensuring that it remains valid. This function
  283. is provided if you can guarantee by external means that the object will
  284. not get deleted (or if you only need the pointer value) and the cost of
  285. creating a QSharedPointer using toStrongRef() is too high.
  286. \omit
  287. \secton1 QWeakPointer internals
  288. QWeakPointer shares most of its internal functionality with
  289. \l{QSharedPointer#qsharedpointer-internals}{QSharedPointer}, so see that
  290. class's internal documentation for more information.
  291. QWeakPointer requires an external reference counter in order to operate.
  292. Therefore, it is incompatible by design with \l QSharedData-derived
  293. classes.
  294. It has a special QObject constructor, which works by calling
  295. QtSharedPointer::ExternalRefCountData::getAndRef, which retrieves the
  296. d-pointer from QObjectPrivate. If one isn't set yet, that function
  297. creates the d-pointer and atomically sets it.
  298. If getAndRef needs to create a d-pointer, it sets the strongref to -1,
  299. indicating that the QObject is not shared: QWeakPointer is used only to
  300. determine whether the QObject has been deleted. In that case, it cannot
  301. be upgraded to QSharedPointer (see the previous section).
  302. \endomit
  303. \sa QSharedPointer, QScopedPointer
  304. */
  305. /*!
  306. \fn QSharedPointer::QSharedPointer()
  307. Creates a QSharedPointer that points to null (0).
  308. */
  309. /*!
  310. \fn QSharedPointer::~QSharedPointer()
  311. Destroys this QSharedPointer object. If it is the last reference to
  312. the pointer stored, this will delete the pointer as well.
  313. */
  314. /*!
  315. \fn QSharedPointer::QSharedPointer(T *ptr)
  316. Creates a QSharedPointer that points to \a ptr. The pointer \a ptr
  317. becomes managed by this QSharedPointer and must not be passed to
  318. another QSharedPointer object or deleted outside this object.
  319. */
  320. /*!
  321. \fn QSharedPointer::QSharedPointer(T *ptr, Deleter deleter)
  322. Creates a QSharedPointer that points to \a ptr. The pointer \a ptr
  323. becomes managed by this QSharedPointer and must not be passed to
  324. another QSharedPointer object or deleted outside this object.
  325. The \a deleter parameter specifies the custom deleter for this
  326. object. The custom deleter is called, instead of the operator delete(),
  327. when the strong reference count drops to 0. This is useful,
  328. for instance, for calling deleteLater() on a QObject instead:
  329. \code
  330. static void doDeleteLater(MyObject *obj)
  331. {
  332. obj->deleteLater();
  333. }
  334. void otherFunction()
  335. {
  336. QSharedPointer<MyObject> obj =
  337. QSharedPointer<MyObject>(new MyObject, doDeleteLater);
  338. // continue using obj
  339. obj.clear(); // calls obj->deleteLater();
  340. }
  341. \endcode
  342. It is also possible to specify a member function directly, as in:
  343. \code
  344. QSharedPointer<MyObject> obj =
  345. QSharedPointer<MyObject>(new MyObject, &QObject::deleteLater);
  346. \endcode
  347. \sa clear()
  348. */
  349. /*!
  350. \fn QSharedPointer::QSharedPointer(const QSharedPointer<T> &other)
  351. Creates a QSharedPointer object that shares \a other's pointer.
  352. If \tt T is a derived type of the template parameter of this class,
  353. QSharedPointer will perform an automatic cast. Otherwise, you will
  354. get a compiler error.
  355. */
  356. /*!
  357. \fn QSharedPointer::QSharedPointer(const QWeakPointer<T> &other)
  358. Creates a QSharedPointer by promoting the weak reference \a other
  359. to strong reference and sharing its pointer.
  360. If \tt T is a derived type of the template parameter of this
  361. class, QSharedPointer will perform an automatic cast. Otherwise,
  362. you will get a compiler error.
  363. \sa QWeakPointer::toStrongRef()
  364. */
  365. /*!
  366. \fn QSharedPointer &QSharedPointer::operator=(const QSharedPointer<T> &other)
  367. Makes this object share \a other's pointer. The current pointer
  368. reference is discarded and, if it was the last, the pointer will
  369. be deleted.
  370. If \tt T is a derived type of the template parameter of this
  371. class, QSharedPointer will perform an automatic cast. Otherwise,
  372. you will get a compiler error.
  373. */
  374. /*!
  375. \fn QSharedPointer &QSharedPointer::operator=(const QWeakPointer<T> &other)
  376. Promotes \a other to a strong reference and makes this object
  377. share a reference to the pointer referenced by it. The current pointer
  378. reference is discarded and, if it was the last, the pointer will
  379. be deleted.
  380. If \tt T is a derived type of the template parameter of this
  381. class, QSharedPointer will perform an automatic cast. Otherwise,
  382. you will get a compiler error.
  383. */
  384. /*!
  385. \fn void QSharedPointer::swap(QSharedPointer<T> &other);
  386. \since 5.3
  387. Swaps this shared pointer instance with \a other. This function is
  388. very fast and never fails.
  389. */
  390. /*!
  391. \fn T *QSharedPointer::data() const
  392. Returns the value of the pointer referenced by this object.
  393. Note: do not delete the pointer returned by this function or pass
  394. it to another function that could delete it, including creating
  395. QSharedPointer or QWeakPointer objects.
  396. */
  397. /*!
  398. \fn T &QSharedPointer::operator *() const
  399. Provides access to the shared pointer's members.
  400. \sa isNull()
  401. */
  402. /*!
  403. \fn T *QSharedPointer::operator ->() const
  404. Provides access to the shared pointer's members.
  405. \sa isNull()
  406. */
  407. /*!
  408. \fn bool QSharedPointer::isNull() const
  409. Returns \c true if this object is holding a reference to a null
  410. pointer.
  411. */
  412. /*!
  413. \fn QSharedPointer::operator bool() const
  414. Returns \c true if this object is not null. This function is suitable
  415. for use in \tt if-constructs, like:
  416. \code
  417. if (sharedptr) { ... }
  418. \endcode
  419. \sa isNull()
  420. */
  421. /*!
  422. \fn bool QSharedPointer::operator !() const
  423. Returns \c true if this object is null. This function is suitable
  424. for use in \tt if-constructs, like:
  425. \code
  426. if (!sharedptr) { ... }
  427. \endcode
  428. \sa isNull()
  429. */
  430. /*!
  431. \fn QSharedPointer<X> QSharedPointer::staticCast() const
  432. Performs a static cast from this pointer's type to \tt X and returns
  433. a QSharedPointer that shares the reference. This function can be
  434. used for up- and for down-casting, but is more useful for
  435. up-casting.
  436. Note: the template type \c X must have the same const and volatile
  437. qualifiers as the template of this object, or the cast will
  438. fail. Use constCast() if you need to drop those qualifiers.
  439. \sa dynamicCast(), constCast(), qSharedPointerCast()
  440. */
  441. /*!
  442. \fn QSharedPointer<X> QSharedPointer::dynamicCast() const
  443. Performs a dynamic cast from this pointer's type to \tt X and
  444. returns a QSharedPointer that shares the reference. If this
  445. function is used to up-cast, then QSharedPointer will perform a \tt
  446. dynamic_cast, which means that if the object being pointed by this
  447. QSharedPointer is not of type \tt X, the returned object will be
  448. null.
  449. Note: the template type \c X must have the same const and volatile
  450. qualifiers as the template of this object, or the cast will
  451. fail. Use constCast() if you need to drop those qualifiers.
  452. \sa qSharedPointerDynamicCast()
  453. */
  454. /*!
  455. \fn QSharedPointer<X> QSharedPointer::constCast() const
  456. Performs a \tt const_cast from this pointer's type to \tt X and returns
  457. a QSharedPointer that shares the reference. This function can be
  458. used for up- and for down-casting, but is more useful for
  459. up-casting.
  460. \sa isNull(), qSharedPointerConstCast()
  461. */
  462. /*!
  463. \fn QSharedPointer<X> QSharedPointer::objectCast() const
  464. \since 4.6
  465. Performs a \l qobject_cast() from this pointer's type to \tt X and
  466. returns a QSharedPointer that shares the reference. If this
  467. function is used to up-cast, then QSharedPointer will perform a \tt
  468. qobject_cast, which means that if the object being pointed by this
  469. QSharedPointer is not of type \tt X, the returned object will be
  470. null.
  471. Note: the template type \c X must have the same const and volatile
  472. qualifiers as the template of this object, or the cast will
  473. fail. Use constCast() if you need to drop those qualifiers.
  474. \sa qSharedPointerObjectCast()
  475. */
  476. /*!
  477. \fn QSharedPointer<T> QSharedPointer::create()
  478. \since 5.1
  479. Creates a QSharedPointer object and allocates a new item of type \tt T. The
  480. QSharedPointer internals and the object are allocated in one single memory
  481. allocation, which could help reduce memory fragmentation in a long-running
  482. application.
  483. This function calls the default constructor for type \tt T.
  484. */
  485. /*!
  486. \fn QSharedPointer<T> QSharedPointer::create(...)
  487. \overload
  488. \since 5.1
  489. Creates a QSharedPointer object and allocates a new item of type \tt T. The
  490. QSharedPointer internals and the object are allocated in one single memory
  491. allocation, which could help reduce memory fragmentation in a long-running
  492. application.
  493. This function will attempt to call a constructor for type \tt T that can
  494. accept all the arguments passed. Arguments will be perfectly-forwarded.
  495. \note This function is only available with a C++11 compiler that supports
  496. perfect forwarding of an arbitrary number of arguments. If the compiler
  497. does not support the necessary C++11 features, you must use the overload
  498. that calls the default constructor.
  499. */
  500. /*!
  501. \fn QWeakPointer<T> QSharedPointer::toWeakRef() const
  502. Returns a weak reference object that shares the pointer referenced
  503. by this object.
  504. \sa QWeakPointer::QWeakPointer()
  505. */
  506. /*!
  507. \fn void QSharedPointer::clear()
  508. Clears this QSharedPointer object, dropping the reference that it
  509. may have had to the pointer. If this was the last reference, then
  510. the pointer itself will be deleted.
  511. */
  512. /*!
  513. \fn void QSharedPointer::reset()
  514. \since 5.0
  515. Same as clear(). For std::shared_ptr compatibility.
  516. */
  517. /*!
  518. \fn void QSharedPointer::reset(T *t)
  519. \since 5.0
  520. Resets this QSharedPointer object to point to \a t
  521. instead. Equivalent to:
  522. \code
  523. QSharedPointer<T> other(t); this->swap(other);
  524. \endcode
  525. */
  526. /*!
  527. \fn void QSharedPointer::reset(T *t, Deleter deleter)
  528. \since 5.0
  529. Resets this QSharedPointer object to point to \a t
  530. instead, with deleter \a deleter. Equivalent to:
  531. \code
  532. QSharedPointer<T> other(t, deleter); this->swap(other);
  533. \endcode
  534. */
  535. /*!
  536. \fn QWeakPointer::QWeakPointer()
  537. Creates a QWeakPointer that points to nothing.
  538. */
  539. /*!
  540. \fn QWeakPointer::~QWeakPointer()
  541. Destroys this QWeakPointer object. The pointer referenced
  542. by this object will not be deleted.
  543. */
  544. /*!
  545. \fn QWeakPointer::QWeakPointer(const QWeakPointer<T> &other)
  546. Creates a QWeakPointer that holds a weak reference to the
  547. pointer referenced by \a other.
  548. If \tt T is a derived type of the template parameter of this
  549. class, QWeakPointer will perform an automatic cast. Otherwise,
  550. you will get a compiler error.
  551. */
  552. /*!
  553. \fn QWeakPointer::QWeakPointer(const QSharedPointer<T> &other)
  554. Creates a QWeakPointer that holds a weak reference to the
  555. pointer referenced by \a other.
  556. If \tt T is a derived type of the template parameter of this
  557. class, QWeakPointer will perform an automatic cast. Otherwise,
  558. you will get a compiler error.
  559. */
  560. /*!
  561. \fn QWeakPointer::QWeakPointer(const QObject *obj)
  562. \since 4.6
  563. \deprecated
  564. Creates a QWeakPointer that holds a weak reference directly to the
  565. QObject \a obj. This constructor is only available if the template type
  566. \tt T is QObject or derives from it (otherwise a compilation error will
  567. result).
  568. You can use this constructor with any QObject, even if they were not
  569. created with \l QSharedPointer.
  570. Note that QWeakPointers created this way on arbitrary QObjects usually
  571. cannot be promoted to QSharedPointer.
  572. \sa QSharedPointer, QPointer
  573. */
  574. /*!
  575. \fn QWeakPointer &QWeakPointer::operator=(const QObject *obj)
  576. \since 4.6
  577. \deprecated
  578. Makes this QWeakPointer hold a weak reference directly to the QObject
  579. \a obj. This function is only available if the template type \tt T is
  580. QObject or derives from it.
  581. \sa QPointer
  582. */
  583. /*!
  584. \fn QWeakPointer &QWeakPointer::operator=(const QWeakPointer<T> &other)
  585. Makes this object share \a other's pointer. The current pointer
  586. reference is discarded but is not deleted.
  587. If \tt T is a derived type of the template parameter of this
  588. class, QWeakPointer will perform an automatic cast. Otherwise,
  589. you will get a compiler error.
  590. */
  591. /*!
  592. \fn QWeakPointer &QWeakPointer::operator=(const QSharedPointer<T> &other)
  593. Makes this object share \a other's pointer. The current pointer
  594. reference is discarded but is not deleted.
  595. If \tt T is a derived type of the template parameter of this
  596. class, QWeakPointer will perform an automatic cast. Otherwise,
  597. you will get a compiler error.
  598. */
  599. /*!
  600. \fn bool QWeakPointer::isNull() const
  601. Returns \c true if this object is holding a reference to a null
  602. pointer.
  603. Note that, due to the nature of weak references, the pointer that
  604. QWeakPointer references can become null at any moment, so
  605. the value returned from this function can change from false to
  606. true from one call to the next.
  607. */
  608. /*!
  609. \fn QWeakPointer::operator bool() const
  610. Returns \c true if this object is not null. This function is suitable
  611. for use in \tt if-constructs, like:
  612. \code
  613. if (weakref) { ... }
  614. \endcode
  615. Note that, due to the nature of weak references, the pointer that
  616. QWeakPointer references can become null at any moment, so
  617. the value returned from this function can change from true to
  618. false from one call to the next.
  619. \sa isNull()
  620. */
  621. /*!
  622. \fn bool QWeakPointer::operator !() const
  623. Returns \c true if this object is null. This function is suitable
  624. for use in \tt if-constructs, like:
  625. \code
  626. if (!weakref) { ... }
  627. \endcode
  628. Note that, due to the nature of weak references, the pointer that
  629. QWeakPointer references can become null at any moment, so
  630. the value returned from this function can change from false to
  631. true from one call to the next.
  632. \sa isNull()
  633. */
  634. /*!
  635. \fn T *QWeakPointer::data() const
  636. \since 4.6
  637. Returns the value of the pointer being tracked by this QWeakPointer,
  638. \b without ensuring that it cannot get deleted. To have that guarantee,
  639. use toStrongRef(), which returns a QSharedPointer object. If this
  640. function can determine that the pointer has already been deleted, it
  641. returns 0.
  642. It is ok to obtain the value of the pointer and using that value itself,
  643. like for example in debugging statements:
  644. \code
  645. qDebug("Tracking %p", weakref.data());
  646. \endcode
  647. However, dereferencing the pointer is only allowed if you can guarantee
  648. by external means that the pointer does not get deleted. For example,
  649. if you can be certain that no other thread can delete it, nor the
  650. functions that you may call.
  651. If that is the case, then the following code is valid:
  652. \code
  653. // this pointer cannot be used in another thread
  654. // so other threads cannot delete it
  655. QWeakPointer<int> weakref = obtainReference();
  656. Object *obj = weakref.data();
  657. if (obj) {
  658. // if the pointer wasn't deleted yet, we know it can't get
  659. // deleted by our own code here nor the functions we call
  660. otherFunction(obj);
  661. }
  662. \endcode
  663. Use this function with care.
  664. \sa isNull(), toStrongRef()
  665. */
  666. /*!
  667. \fn QSharedPointer<T> QWeakPointer::toStrongRef() const
  668. Promotes this weak reference to a strong one and returns a
  669. QSharedPointer object holding that reference. When promoting to
  670. QSharedPointer, this function verifies if the object has been deleted
  671. already or not. If it hasn't, this function increases the reference
  672. count to the shared object, thus ensuring that it will not get
  673. deleted.
  674. Since this function can fail to obtain a valid strong reference to the
  675. shared object, you should always verify if the conversion succeeded,
  676. by calling QSharedPointer::isNull() on the returned object.
  677. For example, the following code promotes a QWeakPointer that was held
  678. to a strong reference and, if it succeeded, it prints the value of the
  679. integer that was held:
  680. \code
  681. QWeakPointer<int> weakref;
  682. // ...
  683. QSharedPointer<int> strong = weakref.toStrongRef();
  684. if (strong)
  685. qDebug() << "The value is:" << *strong;
  686. else
  687. qDebug() << "The value has already been deleted";
  688. \endcode
  689. \sa QSharedPointer::QSharedPointer()
  690. */
  691. /*!
  692. \fn void QWeakPointer::clear()
  693. Clears this QWeakPointer object, dropping the reference that it
  694. may have had to the pointer.
  695. */
  696. /*!
  697. \fn bool operator==(const QSharedPointer<T> &ptr1, const QSharedPointer<X> &ptr2)
  698. \relates QSharedPointer
  699. Returns \c true if the pointer referenced by \a ptr1 is the
  700. same pointer as that referenced by \a ptr2.
  701. If \a ptr2's template parameter is different from \a ptr1's,
  702. QSharedPointer will attempt to perform an automatic \tt static_cast
  703. to ensure that the pointers being compared are equal. If \a ptr2's
  704. template parameter is not a base or a derived type from
  705. \a ptr1's, you will get a compiler error.
  706. */
  707. /*!
  708. \fn bool operator!=(const QSharedPointer<T> &ptr1, const QSharedPointer<X> &ptr2)
  709. \relates QSharedPointer
  710. Returns \c true if the pointer referenced by \a ptr1 is not the
  711. same pointer as that referenced by \a ptr2.
  712. If \a ptr2's template parameter is different from \a ptr1's,
  713. QSharedPointer will attempt to perform an automatic \tt static_cast
  714. to ensure that the pointers being compared are equal. If \a ptr2's
  715. template parameter is not a base or a derived type from
  716. \a ptr1's, you will get a compiler error.
  717. */
  718. /*!
  719. \fn bool operator==(const QSharedPointer<T> &ptr1, const X *ptr2)
  720. \relates QSharedPointer
  721. Returns \c true if the pointer referenced by \a ptr1 is the
  722. same pointer as \a ptr2.
  723. If \a ptr2's type is different from \a ptr1's,
  724. QSharedPointer will attempt to perform an automatic \tt static_cast
  725. to ensure that the pointers being compared are equal. If \a ptr2's
  726. type is not a base or a derived type from this
  727. \a ptr1's, you will get a compiler error.
  728. */
  729. /*!
  730. \fn bool operator!=(const QSharedPointer<T> &ptr1, const X *ptr2)
  731. \relates QSharedPointer
  732. Returns \c true if the pointer referenced by \a ptr1 is not the
  733. same pointer as \a ptr2.
  734. If \a ptr2's type is different from \a ptr1's,
  735. QSharedPointer will attempt to perform an automatic \tt static_cast
  736. to ensure that the pointers being compared are equal. If \a ptr2's
  737. type is not a base or a derived type from this
  738. \a ptr1's, you will get a compiler error.
  739. */
  740. /*!
  741. \fn bool operator==(const T *ptr1, const QSharedPointer<X> &ptr2)
  742. \relates QSharedPointer
  743. Returns \c true if the pointer \a ptr1 is the
  744. same pointer as that referenced by \a ptr2.
  745. If \a ptr2's template parameter is different from \a ptr1's type,
  746. QSharedPointer will attempt to perform an automatic \tt static_cast
  747. to ensure that the pointers being compared are equal. If \a ptr2's
  748. template parameter is not a base or a derived type from
  749. \a ptr1's type, you will get a compiler error.
  750. */
  751. /*!
  752. \fn bool operator!=(const T *ptr1, const QSharedPointer<X> &ptr2)
  753. \relates QSharedPointer
  754. Returns \c true if the pointer \a ptr1 is not the
  755. same pointer as that referenced by \a ptr2.
  756. If \a ptr2's template parameter is different from \a ptr1's type,
  757. QSharedPointer will attempt to perform an automatic \tt static_cast
  758. to ensure that the pointers being compared are equal. If \a ptr2's
  759. template parameter is not a base or a derived type from
  760. \a ptr1's type, you will get a compiler error.
  761. */
  762. /*!
  763. \fn bool operator==(const QSharedPointer<T> &ptr1, const QWeakPointer<X> &ptr2)
  764. \relates QWeakPointer
  765. Returns \c true if the pointer referenced by \a ptr1 is the
  766. same pointer as that referenced by \a ptr2.
  767. If \a ptr2's template parameter is different from \a ptr1's,
  768. QSharedPointer will attempt to perform an automatic \tt static_cast
  769. to ensure that the pointers being compared are equal. If \a ptr2's
  770. template parameter is not a base or a derived type from
  771. \a ptr1's, you will get a compiler error.
  772. */
  773. /*!
  774. \fn bool operator!=(const QSharedPointer<T> &ptr1, const QWeakPointer<X> &ptr2)
  775. \relates QWeakPointer
  776. Returns \c true if the pointer referenced by \a ptr1 is not the
  777. same pointer as that referenced by \a ptr2.
  778. If \a ptr2's template parameter is different from \a ptr1's,
  779. QSharedPointer will attempt to perform an automatic \tt static_cast
  780. to ensure that the pointers being compared are equal. If \a ptr2's
  781. template parameter is not a base or a derived type from
  782. \a ptr1's, you will get a compiler error.
  783. */
  784. /*!
  785. \fn bool operator==(const QWeakPointer<T> &ptr1, const QSharedPointer<X> &ptr2)
  786. \relates QWeakPointer
  787. Returns \c true if the pointer referenced by \a ptr1 is the
  788. same pointer as that referenced by \a ptr2.
  789. If \a ptr2's template parameter is different from \a ptr1's,
  790. QSharedPointer will attempt to perform an automatic \tt static_cast
  791. to ensure that the pointers being compared are equal. If \a ptr2's
  792. template parameter is not a base or a derived type from
  793. \a ptr1's, you will get a compiler error.
  794. */
  795. /*!
  796. \fn bool operator!=(const QWeakPointer<T> &ptr1, const QSharedPointer<X> &ptr2)
  797. \relates QWeakPointer
  798. Returns \c true if the pointer referenced by \a ptr1 is not the
  799. same pointer as that referenced by \a ptr2.
  800. If \a ptr2's template parameter is different from \a ptr1's,
  801. QSharedPointer will attempt to perform an automatic \tt static_cast
  802. to ensure that the pointers being compared are equal. If \a ptr2's
  803. template parameter is not a base or a derived type from
  804. \a ptr1's, you will get a compiler error.
  805. */
  806. /*!
  807. \fn QSharedPointer<X> qSharedPointerCast(const QSharedPointer<T> &other)
  808. \relates QSharedPointer
  809. Returns a shared pointer to the pointer held by \a other, cast to
  810. type \tt X. The types \tt T and \tt X must belong to one
  811. hierarchy for the \tt static_cast to succeed.
  812. Note that \tt X must have the same cv-qualifiers (\tt const and
  813. \tt volatile) that \tt T has, or the code will fail to
  814. compile. Use qSharedPointerConstCast to cast away the constness.
  815. \sa QSharedPointer::staticCast(), qSharedPointerDynamicCast(), qSharedPointerConstCast()
  816. */
  817. /*!
  818. \fn QSharedPointer<X> qSharedPointerCast(const QWeakPointer<T> &other)
  819. \relates QSharedPointer
  820. \relates QWeakPointer
  821. Returns a shared pointer to the pointer held by \a other, cast to
  822. type \tt X. The types \tt T and \tt X must belong to one
  823. hierarchy for the \tt static_cast to succeed.
  824. The \a other object is converted first to a strong reference. If
  825. that conversion fails (because the object it's pointing to has
  826. already been deleted), this function returns a null
  827. QSharedPointer.
  828. Note that \tt X must have the same cv-qualifiers (\tt const and
  829. \tt volatile) that \tt T has, or the code will fail to
  830. compile. Use qSharedPointerConstCast to cast away the constness.
  831. \sa QWeakPointer::toStrongRef(), qSharedPointerDynamicCast(), qSharedPointerConstCast()
  832. */
  833. /*!
  834. \fn QSharedPointer<X> qSharedPointerDynamicCast(const QSharedPointer<T> &other)
  835. \relates QSharedPointer
  836. Returns a shared pointer to the pointer held by \a other, using a
  837. dynamic cast to type \tt X to obtain an internal pointer of the
  838. appropriate type. If the \tt dynamic_cast fails, the object
  839. returned will be null.
  840. Note that \tt X must have the same cv-qualifiers (\tt const and
  841. \tt volatile) that \tt T has, or the code will fail to
  842. compile. Use qSharedPointerConstCast to cast away the constness.
  843. \sa QSharedPointer::dynamicCast(), qSharedPointerCast(), qSharedPointerConstCast()
  844. */
  845. /*!
  846. \fn QSharedPointer<X> qSharedPointerDynamicCast(const QWeakPointer<T> &other)
  847. \relates QSharedPointer
  848. \relates QWeakPointer
  849. Returns a shared pointer to the pointer held by \a other, using a
  850. dynamic cast to type \tt X to obtain an internal pointer of the
  851. appropriate type. If the \tt dynamic_cast fails, the object
  852. returned will be null.
  853. The \a other object is converted first to a strong reference. If
  854. that conversion fails (because the object it's pointing to has
  855. already been deleted), this function also returns a null
  856. QSharedPointer.
  857. Note that \tt X must have the same cv-qualifiers (\tt const and
  858. \tt volatile) that \tt T has, or the code will fail to
  859. compile. Use qSharedPointerConstCast to cast away the constness.
  860. \sa QWeakPointer::toStrongRef(), qSharedPointerCast(), qSharedPointerConstCast()
  861. */
  862. /*!
  863. \fn QSharedPointer<X> qSharedPointerConstCast(const QSharedPointer<T> &other)
  864. \relates QSharedPointer
  865. Returns a shared pointer to the pointer held by \a other, cast to
  866. type \tt X. The types \tt T and \tt X must belong to one
  867. hierarchy for the \tt const_cast to succeed. The \tt const and \tt
  868. volatile differences between \tt T and \tt X are ignored.
  869. \sa QSharedPointer::constCast(), qSharedPointerCast(), qSharedPointerDynamicCast()
  870. */
  871. /*!
  872. \fn QSharedPointer<X> qSharedPointerConstCast(const QWeakPointer<T> &other)
  873. \relates QSharedPointer
  874. \relates QWeakPointer
  875. Returns a shared pointer to the pointer held by \a other, cast to
  876. type \tt X. The types \tt T and \tt X must belong to one
  877. hierarchy for the \tt const_cast to succeed. The \tt const and
  878. \tt volatile differences between \tt T and \tt X are ignored.
  879. The \a other object is converted first to a strong reference. If
  880. that conversion fails (because the object it's pointing to has
  881. already been deleted), this function returns a null
  882. QSharedPointer.
  883. \sa QWeakPointer::toStrongRef(), qSharedPointerCast(), qSharedPointerDynamicCast()
  884. */
  885. /*!
  886. \fn QSharedPointer<X> qSharedPointerObjectCast(const QSharedPointer<T> &other)
  887. \relates QSharedPointer
  888. \since 4.6
  889. \brief The qSharedPointerObjectCast function is for casting a shared pointer.
  890. Returns a shared pointer to the pointer held by \a other, using a
  891. \l qobject_cast() to type \tt X to obtain an internal pointer of the
  892. appropriate type. If the \tt qobject_cast fails, the object
  893. returned will be null.
  894. Note that \tt X must have the same cv-qualifiers (\tt const and
  895. \tt volatile) that \tt T has, or the code will fail to
  896. compile. Use qSharedPointerConstCast to cast away the constness.
  897. \sa QSharedPointer::objectCast(), qSharedPointerCast(), qSharedPointerConstCast()
  898. */
  899. /*!
  900. \fn QSharedPointer<X> qSharedPointerObjectCast(const QWeakPointer<T> &other)
  901. \relates QSharedPointer
  902. \relates QWeakPointer
  903. \since 4.6
  904. \brief The qSharedPointerObjectCast function is for casting a shared pointer.
  905. Returns a shared pointer to the pointer held by \a other, using a
  906. \l qobject_cast() to type \tt X to obtain an internal pointer of the
  907. appropriate type. If the \tt qobject_cast fails, the object
  908. returned will be null.
  909. The \a other object is converted first to a strong reference. If
  910. that conversion fails (because the object it's pointing to has
  911. already been deleted), this function also returns a null
  912. QSharedPointer.
  913. Note that \tt X must have the same cv-qualifiers (\tt const and
  914. \tt volatile) that \tt T has, or the code will fail to
  915. compile. Use qSharedPointerConstCast to cast away the constness.
  916. \sa QWeakPointer::toStrongRef(), qSharedPointerCast(), qSharedPointerConstCast()
  917. */
  918. /*!
  919. \fn QWeakPointer<X> qWeakPointerCast(const QWeakPointer<T> &other)
  920. \relates QWeakPointer
  921. Returns a weak pointer to the pointer held by \a other, cast to
  922. type \tt X. The types \tt T and \tt X must belong to one
  923. hierarchy for the \tt static_cast to succeed.
  924. Note that \tt X must have the same cv-qualifiers (\tt const and
  925. \tt volatile) that \tt T has, or the code will fail to
  926. compile. Use qSharedPointerConstCast to cast away the constness.
  927. */
  928. #include <qset.h>
  929. #include <qmutex.h>
  930. #if !defined(QT_NO_QOBJECT)
  931. #include "private/qobject_p.h"
  932. QT_BEGIN_NAMESPACE
  933. /*!
  934. \internal
  935. This function is called for a just-created QObject \a obj, to enable
  936. the use of QSharedPointer and QWeakPointer in the future.
  937. */
  938. void QtSharedPointer::ExternalRefCountData::setQObjectShared(const QObject *, bool)
  939. {}
  940. /*!
  941. \internal
  942. This function is called when a QSharedPointer is created from a QWeakPointer
  943. We check that the QWeakPointer was really created from a QSharedPointer, and
  944. not from a QObject.
  945. */
  946. void QtSharedPointer::ExternalRefCountData::checkQObjectShared(const QObject *)
  947. {
  948. if (strongref.load() < 0)
  949. qWarning("QSharedPointer: cannot create a QSharedPointer from a QObject-tracking QWeakPointer");
  950. }
  951. QtSharedPointer::ExternalRefCountData *QtSharedPointer::ExternalRefCountData::getAndRef(const QObject *obj)
  952. {
  953. Q_ASSERT(obj);
  954. QObjectPrivate *d = QObjectPrivate::get(const_cast<QObject *>(obj));
  955. Q_ASSERT_X(!d->wasDeleted, "QWeakPointer", "Detected QWeakPointer creation in a QObject being deleted");
  956. ExternalRefCountData *that = d->sharedRefcount.load();
  957. if (that) {
  958. that->weakref.ref();
  959. return that;
  960. }
  961. // we can create the refcount data because it doesn't exist
  962. ExternalRefCountData *x = new ExternalRefCountData(Qt::Uninitialized);
  963. x->strongref.store(-1);
  964. x->weakref.store(2); // the QWeakPointer that called us plus the QObject itself
  965. if (!d->sharedRefcount.testAndSetRelease(0, x)) {
  966. delete x;
  967. x = d->sharedRefcount.loadAcquire();
  968. x->weakref.ref();
  969. }
  970. return x;
  971. }
  972. /**
  973. \internal
  974. Returns a QSharedPointer<QObject> if the variant contains
  975. a QSharedPointer<T> where T inherits QObject. Otherwise the behaviour is undefined.
  976. */
  977. QSharedPointer<QObject> QtSharedPointer::sharedPointerFromVariant_internal(const QVariant &variant)
  978. {
  979. Q_ASSERT(QMetaType::typeFlags(variant.userType()) & QMetaType::SharedPointerToQObject);
  980. return *reinterpret_cast<const QSharedPointer<QObject>*>(variant.constData());
  981. }
  982. /**
  983. \internal
  984. Returns a QWeakPointer<QObject> if the variant contains
  985. a QWeakPointer<T> where T inherits QObject. Otherwise the behaviour is undefined.
  986. */
  987. QWeakPointer<QObject> QtSharedPointer::weakPointerFromVariant_internal(const QVariant &variant)
  988. {
  989. Q_ASSERT(QMetaType::typeFlags(variant.userType()) & QMetaType::WeakPointerToQObject || QMetaType::typeFlags(variant.userType()) & QMetaType::TrackingPointerToQObject);
  990. return *reinterpret_cast<const QWeakPointer<QObject>*>(variant.constData());
  991. }
  992. QT_END_NAMESPACE
  993. #endif
  994. //# define QT_SHARED_POINTER_BACKTRACE_SUPPORT
  995. # ifdef QT_SHARED_POINTER_BACKTRACE_SUPPORT
  996. # if defined(__GLIBC__) && (__GLIBC__ >= 2) && !defined(__UCLIBC__) && !defined(QT_LINUXBASE)
  997. # define BACKTRACE_SUPPORTED
  998. # elif defined(Q_OS_MAC)
  999. # define BACKTRACE_SUPPORTED
  1000. # endif
  1001. # endif
  1002. # if defined(BACKTRACE_SUPPORTED)
  1003. # include <sys/types.h>
  1004. # include <execinfo.h>
  1005. # include <stdio.h>
  1006. # include <unistd.h>
  1007. # include <sys/wait.h>
  1008. QT_BEGIN_NAMESPACE
  1009. static inline QByteArray saveBacktrace() __attribute__((always_inline));
  1010. static inline QByteArray saveBacktrace()
  1011. {
  1012. static const int maxFrames = 32;
  1013. QByteArray stacktrace;
  1014. stacktrace.resize(sizeof(void*) * maxFrames);
  1015. int stack_size = backtrace((void**)stacktrace.data(), maxFrames);
  1016. stacktrace.resize(sizeof(void*) * stack_size);
  1017. return stacktrace;
  1018. }
  1019. static void printBacktrace(QByteArray stacktrace)
  1020. {
  1021. void *const *stack = (void *const *)stacktrace.constData();
  1022. int stack_size = stacktrace.size() / sizeof(void*);
  1023. char **stack_symbols = backtrace_symbols(stack, stack_size);
  1024. int filter[2];
  1025. pid_t child = -1;
  1026. if (pipe(filter) != -1)
  1027. child = fork();
  1028. if (child == 0) {
  1029. // child process
  1030. dup2(fileno(stderr), fileno(stdout));
  1031. dup2(filter[0], fileno(stdin));
  1032. close(filter[0]);
  1033. close(filter[1]);
  1034. execlp("c++filt", "c++filt", "-n", NULL);
  1035. // execlp failed
  1036. exe