aboutsummaryrefslogtreecommitdiffstats
path: root/src/libs/utils
diff options
context:
space:
mode:
authorMarco Bubke <marco.bubke@qt.io>2018-03-26 17:10:17 +0200
committerMarco Bubke <marco.bubke@qt.io>2018-04-04 13:34:20 +0000
commitb6cb22899c1e221397649b635a3e07c191971b93 (patch)
tree2e02839c647fbc6cd3a2ccf629f4839b67c20f76 /src/libs/utils
parent0ecd5436148edc2c8f0ffb12a4acb633c525046c (diff)
Utils: Improve SmallString
The small string control block moved to the beginning, so it is more cache local. The control block is cleanup too, so it should be easier to read. The alignment is removed because it is creating to big holes. Change-Id: I401aeb9d55455cbaa5e722dd8192e54b525ddc40 Reviewed-by: Ivan Donchevskii <ivan.donchevskii@qt.io>
Diffstat (limited to 'src/libs/utils')
-rw-r--r--src/libs/utils/smallstring.h28
-rw-r--r--src/libs/utils/smallstringiterator.h9
-rw-r--r--src/libs/utils/smallstringlayout.h176
-rw-r--r--src/libs/utils/smallstringliteral.h8
-rw-r--r--src/libs/utils/smallstringview.h6
5 files changed, 155 insertions, 72 deletions
diff --git a/src/libs/utils/smallstring.h b/src/libs/utils/smallstring.h
index b945a0f2fe..e8827c3f7b 100644
--- a/src/libs/utils/smallstring.h
+++ b/src/libs/utils/smallstring.h
@@ -93,9 +93,9 @@ public:
if (Q_LIKELY(capacity <= shortStringCapacity())) {
std::memcpy(m_data.shortString.string, string, size);
m_data.shortString.string[size] = 0;
- m_data.shortString.shortStringSize = uchar(size);
- m_data.shortString.isReference = false;
- m_data.shortString.isReadOnlyReference = false;
+ m_data.shortString.control.setShortStringSize(size);
+ m_data.shortString.control.setIsShortString(true);
+ m_data.shortString.control.setIsReadOnlyReference(false);
} else {
m_data.allocated.data.pointer = Memory::allocate(capacity + 1);
std::memcpy(m_data.allocated.data.pointer, string, size);
@@ -178,7 +178,7 @@ public:
BasicSmallString(BasicSmallString &&other) noexcept
: m_data(other.m_data)
{
- other.m_data = Internal::StringDataLayout<Size>();
+ other.m_data.reset();
}
BasicSmallString &operator=(BasicSmallString &&other) noexcept
@@ -413,7 +413,7 @@ public:
if (!isShortString())
return m_data.allocated.data.size;
- return m_data.shortString.shortStringSize;
+ return m_data.shortString.control.shortStringSize();
}
size_type capacity() const noexcept
@@ -532,9 +532,10 @@ public:
return size;
}
+ constexpr
size_type shortStringSize() const
{
- return m_data.shortString.shortStringSize;
+ return m_data.shortString.control.shortStringSize();
}
static
@@ -628,16 +629,19 @@ public:
}
unittest_public:
+ constexpr
bool isShortString() const noexcept
{
- return !m_data.shortString.isReference;
+ return m_data.shortString.control.isShortString();
}
+ constexpr
bool isReadOnlyReference() const noexcept
{
- return m_data.shortString.isReadOnlyReference;
+ return m_data.shortString.control.isReadOnlyReference();
}
+ constexpr
bool hasAllocatedMemory() const noexcept
{
return !isShortString() && !isReadOnlyReference();
@@ -712,9 +716,9 @@ private:
m_data.allocated.data.pointer[size] = 0;
m_data.allocated.data.size = size;
m_data.allocated.data.capacity = capacity;
- m_data.allocated.shortStringSize = 0;
- m_data.allocated.isReference = true;
- m_data.allocated.isReadOnlyReference = false;
+ m_data.shortString.control.setShortStringSize(0);
+ m_data.shortString.control.setIsReference(true);
+ m_data.shortString.control.setIsReadOnlyReference(false);
}
char &at(size_type index)
@@ -852,7 +856,7 @@ private:
void setSize(size_type size)
{
if (isShortString())
- m_data.shortString.shortStringSize = uchar(size);
+ m_data.shortString.control.setShortStringSize(size);
else
m_data.allocated.data.size = size;
}
diff --git a/src/libs/utils/smallstringiterator.h b/src/libs/utils/smallstringiterator.h
index 1217e4bd2b..82836d78c4 100644
--- a/src/libs/utils/smallstringiterator.h
+++ b/src/libs/utils/smallstringiterator.h
@@ -51,6 +51,7 @@ struct SmallStringIterator : public std::iterator<Category, Type, DistanceType,
{
return ++pointer_;
}
+
SmallStringIterator operator++(int) noexcept
{
return pointer_++;
@@ -121,16 +122,19 @@ struct SmallStringIterator : public std::iterator<Category, Type, DistanceType,
return pointer_;
}
+ constexpr
bool operator==(SmallStringIterator other) const noexcept
{
return pointer_ == other.pointer_;
}
+ constexpr
bool operator!=(SmallStringIterator other) const noexcept
{
return pointer_ != other.pointer_;
}
+ constexpr
bool operator<(SmallStringIterator other) const noexcept
{
return pointer_ < other.pointer_;
@@ -141,6 +145,11 @@ struct SmallStringIterator : public std::iterator<Category, Type, DistanceType,
return pointer_;
}
+ const Pointer data() const noexcept
+ {
+ return pointer_;
+ }
+
private:
Pointer pointer_ = nullptr;
};
diff --git a/src/libs/utils/smallstringlayout.h b/src/libs/utils/smallstringlayout.h
index 3a93fe8805..5f1406951e 100644
--- a/src/libs/utils/smallstringlayout.h
+++ b/src/libs/utils/smallstringlayout.h
@@ -28,113 +28,162 @@
#include <QtGlobal>
#include <cstdint>
+#include <memory>
#include <type_traits>
-#if defined(Q_CC_MSVC) && !defined(_WIN64)
-# define ALIGNAS_16
-#else
-# define ALIGNAS_16 alignas(16)
-#endif
-
namespace Utils {
namespace Internal {
using size_type = std::size_t;
-template<bool Bool>
-struct block_type
+template <uint MaximumShortStringDataAreaSize,
+ typename ControlType = typename std::conditional_t<(MaximumShortStringDataAreaSize < 64), uint8_t, uint16_t>>
+struct ControlBlock
{
- using type = uint8_t;
-};
+ using SizeType = ControlType;
+ constexpr ControlBlock() noexcept = default;
+ constexpr ControlBlock(ControlType shortStringSize, bool isReadOnlyReference, bool isReference) noexcept
+ : m_shortStringSize(shortStringSize),
+ m_isReadOnlyReference(isReadOnlyReference),
+ m_isReference(isReference)
+ {}
+
+ void setShortStringSize(size_type size)
+ {
+ m_shortStringSize = static_cast<SizeType>(size);
+ }
+
+ size_type shortStringSize() const
+ {
+ return m_shortStringSize;
+ }
+
+ void setIsReadOnlyReference(bool isReadOnlyReference)
+ {
+ m_isReadOnlyReference = isReadOnlyReference;
+ }
+
+ void setIsReference(bool isReference)
+ {
+ m_isReference = isReference;
+ }
-template<>
-struct block_type<false> {
- using type = uint16_t;
+ void setIsShortString(bool isShortString)
+ {
+ m_isReference = !isShortString;
+ }
+
+ constexpr
+ SizeType stringSize() const
+ {
+ return m_shortStringSize;
+ }
+
+ constexpr
+ bool isReadOnlyReference() const
+ {
+ return m_isReadOnlyReference;
+ }
+
+ constexpr
+ bool isReference() const
+ {
+ return m_isReference;
+ }
+
+ constexpr
+ bool isShortString() const
+ {
+ return !m_isReference;
+ }
+
+private:
+ ControlType m_shortStringSize : (sizeof(ControlType) * 8) - 2;
+ ControlType m_isReadOnlyReference : 1;
+ ControlType m_isReference : 1;
};
-template <uint MaximumShortStringDataAreaSize,
- typename BlockType = typename block_type<(MaximumShortStringDataAreaSize < 64)>::type>
-struct AllocatedLayout {
- struct Data {
+template <uint MaximumShortStringDataAreaSize>
+struct AllocatedLayout
+{
+ struct Data
+ {
char *pointer;
size_type size;
size_type capacity;
- } data;
- char dummy[MaximumShortStringDataAreaSize - sizeof(Data)];
- BlockType shortStringSize : (sizeof(BlockType) * 8) - 2;
- BlockType isReadOnlyReference : 1;
- BlockType isReference : 1;
+ };
+
+ ControlBlock<MaximumShortStringDataAreaSize> control;
+ Data data;
};
-template <uint MaximumShortStringDataAreaSize,
- typename BlockType = typename block_type<(MaximumShortStringDataAreaSize < 64)>::type>
-struct ReferenceLayout {
- struct Data {
+template <uint MaximumShortStringDataAreaSize>
+struct ReferenceLayout
+{
+ constexpr ReferenceLayout() noexcept = default;
+ constexpr ReferenceLayout(const char *stringPointer,
+ size_type size,
+ size_type capacity) noexcept
+ : control(0, true, true),
+ data{stringPointer, size, capacity}
+ {}
+
+ struct Data
+ {
const char *pointer;
size_type size;
size_type capacity;
- } data;
- char dummy[MaximumShortStringDataAreaSize - sizeof(Data)];
- BlockType shortStringSize : (sizeof(BlockType) * 8) - 2;
- BlockType isReadOnlyReference : 1;
- BlockType isReference : 1;
+ };
+
+ ControlBlock<MaximumShortStringDataAreaSize> control;
+ Data data;
};
-template <uint MaximumShortStringDataAreaSize,
- typename BlockType = typename block_type<(MaximumShortStringDataAreaSize < 64)>::type>
-struct ShortStringLayout {
+template <uint MaximumShortStringDataAreaSize>
+struct ShortStringLayout
+{
+ ControlBlock<MaximumShortStringDataAreaSize> control;
char string[MaximumShortStringDataAreaSize];
- BlockType shortStringSize : (sizeof(BlockType) * 8) - 2;
- BlockType isReadOnlyReference : 1;
- BlockType isReference : 1;
};
template <uint MaximumShortStringDataAreaSize>
-struct ALIGNAS_16 StringDataLayout {
+struct StringDataLayout {
static_assert(MaximumShortStringDataAreaSize >= 15, "Size must be greater equal than 15 bytes!");
static_assert(MaximumShortStringDataAreaSize < 64
? ((MaximumShortStringDataAreaSize + 1) % 16) == 0
: ((MaximumShortStringDataAreaSize + 2) % 16) == 0,
"Size + 1 must be dividable by 16 if under 64 and Size + 2 must be dividable by 16 if over 64!");
- constexpr StringDataLayout() noexcept = default;
+ constexpr
+ StringDataLayout() noexcept
+ {
+ reset();
+ }
constexpr StringDataLayout(const char *string,
size_type size) noexcept
- : reference({{string, size, 0}, {}, 0, true, true})
+ : reference(string, size, 0)
{
}
template<size_type Size,
typename std::enable_if_t<Size <= MaximumShortStringDataAreaSize, int> = 0>
- constexpr StringDataLayout(const char(&string)[Size]) noexcept
-#if __cpp_constexpr < 201304
- : reference({{string, Size - 1, 0}, {}, 0, true, true})
-#else
+ StringDataLayout(const char(&string)[Size]) noexcept
: shortString(ShortStringLayout<MaximumShortStringDataAreaSize>{})
-#endif
{
-#if __cpp_constexpr >= 201304
for (size_type i = 0; i < Size; ++i)
shortString.string[i] = string[i];
-#if defined(__GNUC__)
-#pragma GCC diagnostic push
-#pragma GCC diagnostic ignored "-Woverflow"
- shortString.shortStringSize = std::uint8_t(Size) - 1;
-#pragma GCC diagnostic pop
-#endif
- shortString.isReference = false;
- shortString.isReadOnlyReference = false;
-
-#endif
+ shortString.control.setShortStringSize(Size - 1);
+ shortString.control.setIsShortString(true);
+ shortString.control.setIsReadOnlyReference(false);
}
template<size_type Size,
typename std::enable_if_t<!(Size <= MaximumShortStringDataAreaSize), int> = 1>
constexpr StringDataLayout(const char(&string)[Size]) noexcept
- : reference({{string, Size - 1, 0}, {}, 0, true, true})
+ : reference(string, Size - 1, 0)
{
}
@@ -144,6 +193,19 @@ struct ALIGNAS_16 StringDataLayout {
return MaximumShortStringDataAreaSize - 1;
}
+ void reset()
+ {
+ shortString.control = ControlBlock<MaximumShortStringDataAreaSize>();
+ shortString.string[0] = '\0';
+ }
+
+ StringDataLayout &operator=(const StringDataLayout &other)
+ {
+ this->shortString = other.shortString;
+
+ return *this;
+ }
+
union {
AllocatedLayout<MaximumShortStringDataAreaSize> allocated;
ReferenceLayout<MaximumShortStringDataAreaSize> reference;
diff --git a/src/libs/utils/smallstringliteral.h b/src/libs/utils/smallstringliteral.h
index eedcf45d13..cf0c4953fb 100644
--- a/src/libs/utils/smallstringliteral.h
+++ b/src/libs/utils/smallstringliteral.h
@@ -63,7 +63,7 @@ public:
size_type size() const noexcept
{
- return Q_LIKELY(isShortString()) ? m_data.shortString.shortStringSize : m_data.allocated.data.size;
+ return Q_LIKELY(isShortString()) ? m_data.shortString.control.shortStringSize() : m_data.allocated.data.size;
}
constexpr
@@ -94,14 +94,16 @@ public:
return Internal::StringDataLayout<Size>::shortStringCapacity();
}
+ constexpr
bool isShortString() const noexcept
{
- return !m_data.shortString.isReference;
+ return m_data.shortString.control.isShortString();
}
+ constexpr
bool isReadOnlyReference() const noexcept
{
- return m_data.shortString.isReadOnlyReference;
+ return m_data.shortString.control.isReadOnlyReference();
}
constexpr
diff --git a/src/libs/utils/smallstringview.h b/src/libs/utils/smallstringview.h
index 4932a85cb4..0d8600e5de 100644
--- a/src/libs/utils/smallstringview.h
+++ b/src/libs/utils/smallstringview.h
@@ -79,6 +79,12 @@ public:
{
}
+ SmallStringView(const const_iterator begin, const const_iterator end) noexcept
+ : m_pointer(begin.data()),
+ m_size(std::size_t(end - begin))
+ {
+ }
+
template<typename String,
typename Utils::enable_if_has_char_data_pointer<String> = 0>
SmallStringView(const String &string) noexcept