Rewrite & optimize LimitedQueue (#3798)
* Use circular buffer for LimitedQueue * Reduce copying of snapshot * Small optimizations * Remove unneeded lock statements * Add LimitedQueue tests * Fix includes for limited queue benchmark * Update CHANGELOG.md * Use correct boost version iterators * Use a shared_mutex to clarify reads and writes * Update `find`/`rfind` to return the result as a boost::optional * Use `[[nodiscard]]` where applicable * Update comments * Add a couple more doc comments * Replace size with get get is a safe (locked & checked) version of at * Use std::vector in LimitedQueueSnapshot * Update LimitedQueue benchmarks * Add mutex guard to buffer accessors We do not know whether T is an atomic type or not so we can't safely say that we can copy the value at a certain address of the buffer. See https://stackoverflow.com/a/2252478 * Update doc comments, add first/last getters * Make limit_ const * Omit `else` if the if-case always returns * Title case category comments * Remove `at` * Fix `get` comment * Privatize/comment/lock property accessors - `limit` is now private - `space` is now private - `full` has been removed - `empty` now locks * Remove `front` function * Remove `back` method * Add comment to `first` * Add comment to `last` Co-authored-by: Rasmus Karlsson <rasmus.karlsson@pajlada.com>
This commit is contained in:
@@ -381,7 +381,7 @@ void ChannelView::performLayout(bool causedByScrollbar)
|
||||
// BenchmarkGuard benchmark("layout");
|
||||
|
||||
/// Get messages and check if there are at least 1
|
||||
auto messages = this->getMessagesSnapshot();
|
||||
auto &messages = this->getMessagesSnapshot();
|
||||
|
||||
this->showingLatestMessages_ =
|
||||
this->scrollBar_->isAtBottom() || !this->scrollBar_->isVisible();
|
||||
@@ -502,7 +502,7 @@ QString ChannelView::getSelectedText()
|
||||
{
|
||||
QString result = "";
|
||||
|
||||
LimitedQueueSnapshot<MessageLayoutPtr> messagesSnapshot =
|
||||
LimitedQueueSnapshot<MessageLayoutPtr> &messagesSnapshot =
|
||||
this->getMessagesSnapshot();
|
||||
|
||||
Selection _selection = this->selection_;
|
||||
@@ -561,7 +561,7 @@ const boost::optional<MessageElementFlags> &ChannelView::getOverrideFlags()
|
||||
return this->overrideFlags_;
|
||||
}
|
||||
|
||||
LimitedQueueSnapshot<MessageLayoutPtr> ChannelView::getMessagesSnapshot()
|
||||
LimitedQueueSnapshot<MessageLayoutPtr> &ChannelView::getMessagesSnapshot()
|
||||
{
|
||||
if (!this->paused() /*|| this->scrollBar_->isVisible()*/)
|
||||
{
|
||||
@@ -682,11 +682,9 @@ void ChannelView::setChannel(ChannelPtr underlyingChannel)
|
||||
|
||||
auto snapshot = underlyingChannel->getMessageSnapshot();
|
||||
|
||||
for (size_t i = 0; i < snapshot.size(); i++)
|
||||
for (const auto &msg : snapshot)
|
||||
{
|
||||
MessageLayoutPtr deleted;
|
||||
|
||||
auto messageLayout = new MessageLayout(snapshot[i]);
|
||||
auto messageLayout = new MessageLayout(msg);
|
||||
|
||||
if (this->lastMessageHasAlternateBackground_)
|
||||
{
|
||||
@@ -700,11 +698,10 @@ void ChannelView::setChannel(ChannelPtr underlyingChannel)
|
||||
messageLayout->flags.set(MessageLayoutFlag::IgnoreHighlights);
|
||||
}
|
||||
|
||||
this->messages_.pushBack(MessageLayoutPtr(messageLayout), deleted);
|
||||
this->messages_.pushBack(MessageLayoutPtr(messageLayout));
|
||||
if (this->showScrollbarHighlights())
|
||||
{
|
||||
this->scrollBar_->addHighlight(
|
||||
snapshot[i]->getScrollBarHighlight());
|
||||
this->scrollBar_->addHighlight(msg->getScrollBarHighlight());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -776,8 +773,6 @@ bool ChannelView::hasSourceChannel() const
|
||||
void ChannelView::messageAppended(MessagePtr &message,
|
||||
boost::optional<MessageFlags> overridingFlags)
|
||||
{
|
||||
MessageLayoutPtr deleted;
|
||||
|
||||
auto *messageFlags = &message->flags;
|
||||
if (overridingFlags)
|
||||
{
|
||||
@@ -809,7 +804,7 @@ void ChannelView::messageAppended(MessagePtr &message,
|
||||
loop.exec();
|
||||
}
|
||||
|
||||
if (this->messages_.pushBack(MessageLayoutPtr(messageRef), deleted))
|
||||
if (this->messages_.pushBack(MessageLayoutPtr(messageRef)))
|
||||
{
|
||||
if (this->paused())
|
||||
{
|
||||
@@ -915,22 +910,16 @@ void ChannelView::messageRemoveFromStart(MessagePtr &message)
|
||||
|
||||
void ChannelView::messageReplaced(size_t index, MessagePtr &replacement)
|
||||
{
|
||||
if (index >= this->messages_.getSnapshot().size())
|
||||
auto oMessage = this->messages_.get(index);
|
||||
if (!oMessage)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
auto message = *oMessage;
|
||||
|
||||
MessageLayoutPtr newItem(new MessageLayout(replacement));
|
||||
auto snapshot = this->messages_.getSnapshot();
|
||||
if (index >= snapshot.size())
|
||||
{
|
||||
qCDebug(chatterinoWidget)
|
||||
<< "Tried to replace out of bounds message. Index:" << index
|
||||
<< ". Length:" << snapshot.size();
|
||||
return;
|
||||
}
|
||||
|
||||
const auto &message = snapshot[index];
|
||||
if (message->flags.has(MessageLayoutFlag::AlternateBackground))
|
||||
{
|
||||
newItem->flags.set(MessageLayoutFlag::AlternateBackground);
|
||||
@@ -945,11 +934,9 @@ void ChannelView::messageReplaced(size_t index, MessagePtr &replacement)
|
||||
|
||||
void ChannelView::updateLastReadMessage()
|
||||
{
|
||||
auto _snapshot = this->getMessagesSnapshot();
|
||||
|
||||
if (_snapshot.size() > 0)
|
||||
if (auto lastMessage = this->messages_.last())
|
||||
{
|
||||
this->lastReadMessage_ = _snapshot[_snapshot.size() - 1];
|
||||
this->lastReadMessage_ = *lastMessage;
|
||||
}
|
||||
|
||||
this->update();
|
||||
@@ -1055,7 +1042,7 @@ void ChannelView::paintEvent(QPaintEvent * /*event*/)
|
||||
// such as the grey overlay when a message is disabled
|
||||
void ChannelView::drawMessages(QPainter &painter)
|
||||
{
|
||||
auto messagesSnapshot = this->getMessagesSnapshot();
|
||||
auto &messagesSnapshot = this->getMessagesSnapshot();
|
||||
|
||||
size_t start = size_t(this->scrollBar_->getCurrentValue());
|
||||
|
||||
@@ -1122,7 +1109,7 @@ void ChannelView::drawMessages(QPainter &painter)
|
||||
// add all messages on screen to the map
|
||||
for (size_t i = start; i < messagesSnapshot.size(); ++i)
|
||||
{
|
||||
std::shared_ptr<MessageLayout> layout = messagesSnapshot[i];
|
||||
const std::shared_ptr<MessageLayout> &layout = messagesSnapshot[i];
|
||||
|
||||
this->messagesOnScreen_.insert(layout);
|
||||
|
||||
@@ -1153,7 +1140,7 @@ void ChannelView::wheelEvent(QWheelEvent *event)
|
||||
qreal desired = this->scrollBar_->getDesiredValue();
|
||||
qreal delta = event->angleDelta().y() * qreal(1.5) * mouseMultiplier;
|
||||
|
||||
auto snapshot = this->getMessagesSnapshot();
|
||||
auto &snapshot = this->getMessagesSnapshot();
|
||||
int snapshotLength = int(snapshot.size());
|
||||
int i = std::min<int>(int(desired), snapshotLength);
|
||||
|
||||
@@ -1553,7 +1540,7 @@ void ChannelView::mousePressEvent(QMouseEvent *event)
|
||||
if (!tryGetMessageAt(event->pos(), layout, relativePos, messageIndex))
|
||||
{
|
||||
setCursor(Qt::ArrowCursor);
|
||||
auto messagesSnapshot = this->getMessagesSnapshot();
|
||||
auto &messagesSnapshot = this->getMessagesSnapshot();
|
||||
if (messagesSnapshot.size() == 0)
|
||||
{
|
||||
return;
|
||||
@@ -2387,7 +2374,7 @@ bool ChannelView::tryGetMessageAt(QPoint p,
|
||||
std::shared_ptr<MessageLayout> &_message,
|
||||
QPoint &relativePos, int &index)
|
||||
{
|
||||
auto messagesSnapshot = this->getMessagesSnapshot();
|
||||
auto &messagesSnapshot = this->getMessagesSnapshot();
|
||||
|
||||
size_t start = this->scrollBar_->getCurrentValue();
|
||||
|
||||
|
||||
Reference in New Issue
Block a user