From 044f7302143cb4b714712ca52b5ce673bc5fb7d3 Mon Sep 17 00:00:00 2001 From: Simon Hausmann Date: Fri, 28 Feb 2020 16:14:21 +0100 Subject: Add documentation for QTaggedPointer MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The class remains \internal though, as it has a very narrow use-case for low-level code inside Qt. Change-Id: I9d2b6486ce29b290af7f930a0bfc78590a83cc01 Reviewed-by: Tor Arne Vestbø --- src/corelib/tools/qtaggedpointer.h | 16 +-- src/corelib/tools/qtaggedpointer.qdoc | 206 ++++++++++++++++++++++++++++++++++ 2 files changed, 214 insertions(+), 8 deletions(-) create mode 100644 src/corelib/tools/qtaggedpointer.qdoc diff --git a/src/corelib/tools/qtaggedpointer.h b/src/corelib/tools/qtaggedpointer.h index 2d4d688824..11f02d2807 100644 --- a/src/corelib/tools/qtaggedpointer.h +++ b/src/corelib/tools/qtaggedpointer.h @@ -80,7 +80,7 @@ public: static constexpr quintptr tagMask() { return QtPrivate::TagInfo::alignment - 1; } static constexpr quintptr pointerMask() { return ~tagMask(); } - explicit QTaggedPointer(Type *pointer = nullptr, TagType tag = TagType()) noexcept + explicit QTaggedPointer(T *pointer = nullptr, Tag tag = Tag()) noexcept : d(quintptr(pointer)) { Q_STATIC_ASSERT(sizeof(Type*) == sizeof(QTaggedPointer)); @@ -91,7 +91,7 @@ public: setTag(tag); } - Type &operator*() const + Type &operator*() const noexcept { Q_ASSERT(pointer()); return *pointer(); @@ -102,7 +102,7 @@ public: return pointer(); } - explicit operator bool() const + explicit operator bool() const noexcept { return !isNull(); } @@ -119,12 +119,12 @@ public: return *this; } - static constexpr TagType maximumTag() noexcept + static constexpr Tag maximumTag() noexcept { return TagType(typename QtPrivate::TagInfo::TagType(tagMask())); } - void setTag(TagType tag) + void setTag(Tag tag) { Q_ASSERT_X((static_cast::TagType>(tag) & pointerMask()) == 0, "QTaggedPointer::setTag", "Tag is larger than allowed by number of available tag bits"); @@ -132,12 +132,12 @@ public: d = (d & pointerMask()) | (static_cast::TagType>(tag) & tagMask()); } - TagType tag() const noexcept + Tag tag() const noexcept { return TagType(typename QtPrivate::TagInfo::TagType(d & tagMask())); } - Type* pointer() const noexcept + T* pointer() const noexcept { return reinterpret_cast(d & pointerMask()); } @@ -147,7 +147,7 @@ public: return !pointer(); } - void swap(QTaggedPointer &other) noexcept + void swap(QTaggedPointer &other) noexcept { qSwap(d, other.d); } diff --git a/src/corelib/tools/qtaggedpointer.qdoc b/src/corelib/tools/qtaggedpointer.qdoc new file mode 100644 index 0000000000..5b335e8739 --- /dev/null +++ b/src/corelib/tools/qtaggedpointer.qdoc @@ -0,0 +1,206 @@ +/**************************************************************************** +** +** Copyright (C) 2020 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the documentation of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:FDL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU Free Documentation License Usage +** Alternatively, this file may be used under the terms of the GNU Free +** Documentation License version 1.3 as published by the Free Software +** Foundation and appearing in the file included in the packaging of +** this file. Please review the following information to ensure +** the GNU Free Documentation License version 1.3 requirements +** will be met: https://www.gnu.org/licenses/fdl-1.3.html. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +/*! + \class QTaggedPointer + \internal + \inmodule QtCore + \brief The QTaggedPointer class provides a low-level wrapper around raw + pointers that makes it possible to store additional information in otherwise unused bits. + + \ingroup tools + \reentrant + + + Data structures in C++ tend to have a natural alignment in memory, based on + the alignment requirements of the members fields. For example a structure + containing an integer tends to be aligned to a 4-byte boundary in memory. That + means a pointer holding the address of an instance will always have the lower + two bits set to zero. QTaggedPointer makes it possible to store information + in these bits, such as a user provided enum. This is called a tag. The API allows + reading and writing the tag. When asked for the raw pointer, it will always return + a valid address with the bits used for the tag set to zero. + + This pattern may be useful when creating low-level data structures that + need to be as dense as possible. + + The first template parameter is the type the tagged pointer should point + to. The second template parameter is the type of the tag. If not specified it will + default to an unsigned integral. A more powerful pattern though is to define a + flag enum and use that as a tag type: + + \code + struct LinkedListItem + { + enum MyFlag { + NoOption = 0x0, + SomeOption = 0x1, + ThirdWay = 0x2 + }; + Q_DECLARE_FLAGS(MyFlags, MyFlag) + + QTaggedPointer next; + + ... + }; + + Q_DECLARE_OPERATORS_FOR_FLAGS(LinkedListItem::MyFlags) + + LinkedListItem &listItem = ... + listItem.next = new LinkedListItem; + listItem.next.setTag(LinkedListItem::SomeOption | LinkedListItem::ThirdWay); + \endcode + + \note QTaggedPointer does not provide ownership. You are responsible for deleting + the data the pointer points to. +*/ + +/*! + \typedef QTaggedPointer::Type + + Typedef for T. +*/ + +/*! + \typedef QTaggedPointer::TagType + + Typedef for Tag. +*/ + + +/*! + \fn template explicit QTaggedPointer::QTaggedPointer(T *pointer = nullptr, Tag tag = Tag()) noexcept + + Creates a tagged pointer that points to \a pointer and stores the specified \a tag. +*/ + +/*! + \fn template T &QTaggedPointer::operator*() const noexcept + + Provides access to the pointer's members. +*/ + +/*! + \fn template T *QTaggedPointer::operator->() const noexcept + + Provides access to the pointer's members. +*/ + +/*! + \fn template bool QTaggedPointer::operator!() const noexcept + + Returns \c true if the pointer is \nullptr. +*/ + +/*! + \fn template explicit QTaggedPointer::operator bool() const noexcept + + Returns \c true if the pointer is \e not null. +*/ + +/*! + \fn template QTaggedPointer &QTaggedPointer::operator=(T *other) noexcept + + Sets the pointer of this to \a other. The tag remains unchanged. +*/ + +/*! + \fn template void QTaggedPointer::setTag(Tag tag) + + Sets the tag value to the specified \a tag. The pointer remains unchanged. +*/ + +/*! + \fn template Tag QTaggedPointer::tag() const noexcept + + Returns the tag stored in the tagged pointer. +*/ + +/*! + \fn template Tag QTaggedPointer::pointer() const noexcept + + Returns the pointer stored in the tagged pointer. +*/ + +/*! + \fn template bool QTaggedPointer::isNull() const noexcept + + Returns \c true if the pointer is \nullptr; otherwise returns \c false. +*/ + +/*! + \fn template void QTaggedPointer::swap(QTaggedPointer &other) noexcept + + Swaps this instance's pointer and tag with the pointer and tag in \a other. +*/ + +/*! + \fn template inline bool operator==(const QTaggedPointer &lhs, const QTaggedPointer &rhs) noexcept + \relates QTaggedPointer + + Returns \c true if \a lhs is equal to \a rhs; otherwise returns \c false. + + Two tagged pointers are considered equal if they point to the same object. Their tags are not compared. +*/ + +/*! + \fn template inline bool operator!=(const QTaggedPointer &lhs, const QTaggedPointer &rhs) noexcept + \relates QTaggedPointer + + Returns \c true if \a lhs is not equal to \a rhs; otherwise returns \c false. + + Two tagged pointers are considered equal if they point to the same object. Their tags are not compared. +*/ + +/*! + \fn template inline bool operator==(const QTaggedPointer &lhs, std::nullptr_t) noexcept + \relates QTaggedPointer + + Returns \c true if \a lhs refers to \c nullptr. +*/ + +/*! + \fn template inline bool operator==(std::nullptr_t, const QTaggedPointer &rhs) noexcept + \relates QTaggedPointer + + Returns \c true if \a rhs refers to \c nullptr. +*/ + +/*! + \fn template inline bool operator!=(const QTaggedPointer &lhs, std::nullptr_t) noexcept + \relates QTaggedPointer + + Returns \c true if \a lhs refers to a valid (i.e. non-null) pointer. +*/ + +/*! + \fn template inline bool operator!=(std::nullptr_t, const QTaggedPointer &rhs) noexcept + \relates QTaggedPointer + + Returns \c true if \a rhs refers to a valid (i.e. non-null) pointer. +*/ + -- cgit v1.2.3