2015-11-09 04:36:37 -06:00
|
|
|
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; fill-column: 100 -*- */
|
|
|
|
/*
|
|
|
|
* This file is part of the LibreOffice project.
|
|
|
|
*
|
|
|
|
* This Source Code Form is subject to the terms of the Mozilla Public
|
|
|
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
|
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
|
|
|
*/
|
|
|
|
|
|
|
|
#include "MessageQueue.hpp"
|
|
|
|
|
|
|
|
#include <algorithm>
|
|
|
|
|
2016-09-20 18:59:06 -05:00
|
|
|
#include <Poco/StringTokenizer.h>
|
|
|
|
|
Get rid of some fragile string literal length counts
Basically, instead of foo.compare(0, 3, "bar") use
LOOLProtocol::getFirstToken(foo)!="bar". Using a separate length of a
string literal is very fragile, it is easy to get the length wrong, or
forget to change it in case the string changes. See
137e677eb0d6af1996701b2bd1b27a6eb3822613.
It isn't entirely sure to me whether was is kept in a message queue
follows LOOL protocol message syntax, but it seems to be so in
practice, so we can use LOOLProtocol::getFirstToken().
Also, calls like msg.compare(0, 4, "tile") add undocumented implicit
requirements that the token in question must be unique as an initial
substring of the first tokens of all messages. It actually isn't,
there is also "tilecombine". But in this case, that was taken care of
by checking for "tilecombine" first. Ugh. Whether that was by accident
or design is hard to say, but at least there was no comment indicating
intentionality.
We still have lots of similar fragile mis-use of std::string::find().
2016-09-26 12:13:50 -05:00
|
|
|
#include <LOOLProtocol.hpp>
|
2016-09-01 15:45:04 -05:00
|
|
|
#include <Log.hpp>
|
Get rid of some fragile string literal length counts
Basically, instead of foo.compare(0, 3, "bar") use
LOOLProtocol::getFirstToken(foo)!="bar". Using a separate length of a
string literal is very fragile, it is easy to get the length wrong, or
forget to change it in case the string changes. See
137e677eb0d6af1996701b2bd1b27a6eb3822613.
It isn't entirely sure to me whether was is kept in a message queue
follows LOOL protocol message syntax, but it seems to be so in
practice, so we can use LOOLProtocol::getFirstToken().
Also, calls like msg.compare(0, 4, "tile") add undocumented implicit
requirements that the token in question must be unique as an initial
substring of the first tokens of all messages. It actually isn't,
there is also "tilecombine". But in this case, that was taken care of
by checking for "tilecombine" first. Ugh. Whether that was by accident
or design is hard to say, but at least there was no comment indicating
intentionality.
We still have lots of similar fragile mis-use of std::string::find().
2016-09-26 12:13:50 -05:00
|
|
|
#include <TileDesc.hpp>
|
2016-09-01 15:45:04 -05:00
|
|
|
|
2016-09-20 18:59:06 -05:00
|
|
|
using Poco::StringTokenizer;
|
|
|
|
|
2015-11-09 04:36:37 -06:00
|
|
|
MessageQueue::~MessageQueue()
|
|
|
|
{
|
|
|
|
clear();
|
|
|
|
}
|
|
|
|
|
2016-03-26 21:32:29 -05:00
|
|
|
void MessageQueue::put(const Payload& value)
|
2015-11-09 04:36:37 -06:00
|
|
|
{
|
|
|
|
std::unique_lock<std::mutex> lock(_mutex);
|
|
|
|
put_impl(value);
|
|
|
|
lock.unlock();
|
|
|
|
_cv.notify_one();
|
|
|
|
}
|
|
|
|
|
2016-10-09 10:59:00 -05:00
|
|
|
MessageQueue::Payload MessageQueue::get(const unsigned timeoutMs)
|
2015-11-09 04:36:37 -06:00
|
|
|
{
|
|
|
|
std::unique_lock<std::mutex> lock(_mutex);
|
2016-10-09 10:59:00 -05:00
|
|
|
|
|
|
|
if (timeoutMs > 0)
|
|
|
|
{
|
|
|
|
if (!_cv.wait_for(lock, std::chrono::milliseconds(timeoutMs),
|
|
|
|
[this] { return wait_impl(); }))
|
|
|
|
{
|
|
|
|
throw std::runtime_error("Timed out waiting to get queue item.");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
_cv.wait(lock, [this] { return wait_impl(); });
|
|
|
|
}
|
|
|
|
|
2015-11-09 04:36:37 -06:00
|
|
|
return get_impl();
|
|
|
|
}
|
|
|
|
|
|
|
|
void MessageQueue::clear()
|
|
|
|
{
|
|
|
|
std::unique_lock<std::mutex> lock(_mutex);
|
2015-12-17 11:47:58 -06:00
|
|
|
clear_impl();
|
2015-11-09 04:36:37 -06:00
|
|
|
}
|
|
|
|
|
2016-04-27 07:58:33 -05:00
|
|
|
void MessageQueue::remove_if(const std::function<bool(const Payload&)>& pred)
|
2015-12-13 22:36:46 -06:00
|
|
|
{
|
|
|
|
std::unique_lock<std::mutex> lock(_mutex);
|
|
|
|
std::remove_if(_queue.begin(), _queue.end(), pred);
|
|
|
|
}
|
|
|
|
|
2016-03-26 21:32:29 -05:00
|
|
|
void MessageQueue::put_impl(const Payload& value)
|
2015-11-09 04:36:37 -06:00
|
|
|
{
|
2016-09-15 07:40:26 -05:00
|
|
|
const auto msg = std::string(value.data(), value.size());
|
2015-11-09 04:36:37 -06:00
|
|
|
_queue.push_back(value);
|
|
|
|
}
|
|
|
|
|
|
|
|
bool MessageQueue::wait_impl() const
|
|
|
|
{
|
|
|
|
return _queue.size() > 0;
|
|
|
|
}
|
|
|
|
|
2016-03-26 21:32:29 -05:00
|
|
|
MessageQueue::Payload MessageQueue::get_impl()
|
2015-11-09 04:36:37 -06:00
|
|
|
{
|
2016-09-26 03:35:20 -05:00
|
|
|
Payload result = _queue.front();
|
2015-11-09 04:36:37 -06:00
|
|
|
_queue.pop_front();
|
2016-03-29 06:36:30 -05:00
|
|
|
return result;
|
2015-11-09 04:36:37 -06:00
|
|
|
}
|
|
|
|
|
|
|
|
void MessageQueue::clear_impl()
|
|
|
|
{
|
|
|
|
_queue.clear();
|
|
|
|
}
|
|
|
|
|
2016-03-26 21:32:29 -05:00
|
|
|
void TileQueue::put_impl(const Payload& value)
|
2015-11-09 04:36:37 -06:00
|
|
|
{
|
2016-09-14 16:42:50 -05:00
|
|
|
const auto msg = std::string(value.data(), value.size());
|
Get rid of some fragile string literal length counts
Basically, instead of foo.compare(0, 3, "bar") use
LOOLProtocol::getFirstToken(foo)!="bar". Using a separate length of a
string literal is very fragile, it is easy to get the length wrong, or
forget to change it in case the string changes. See
137e677eb0d6af1996701b2bd1b27a6eb3822613.
It isn't entirely sure to me whether was is kept in a message queue
follows LOOL protocol message syntax, but it seems to be so in
practice, so we can use LOOLProtocol::getFirstToken().
Also, calls like msg.compare(0, 4, "tile") add undocumented implicit
requirements that the token in question must be unique as an initial
substring of the first tokens of all messages. It actually isn't,
there is also "tilecombine". But in this case, that was taken care of
by checking for "tilecombine" first. Ugh. Whether that was by accident
or design is hard to say, but at least there was no comment indicating
intentionality.
We still have lots of similar fragile mis-use of std::string::find().
2016-09-26 12:13:50 -05:00
|
|
|
const std::string firstToken = LOOLProtocol::getFirstToken(value);
|
2016-09-20 18:59:06 -05:00
|
|
|
|
Get rid of some fragile string literal length counts
Basically, instead of foo.compare(0, 3, "bar") use
LOOLProtocol::getFirstToken(foo)!="bar". Using a separate length of a
string literal is very fragile, it is easy to get the length wrong, or
forget to change it in case the string changes. See
137e677eb0d6af1996701b2bd1b27a6eb3822613.
It isn't entirely sure to me whether was is kept in a message queue
follows LOOL protocol message syntax, but it seems to be so in
practice, so we can use LOOLProtocol::getFirstToken().
Also, calls like msg.compare(0, 4, "tile") add undocumented implicit
requirements that the token in question must be unique as an initial
substring of the first tokens of all messages. It actually isn't,
there is also "tilecombine". But in this case, that was taken care of
by checking for "tilecombine" first. Ugh. Whether that was by accident
or design is hard to say, but at least there was no comment indicating
intentionality.
We still have lots of similar fragile mis-use of std::string::find().
2016-09-26 12:13:50 -05:00
|
|
|
if (firstToken == "canceltiles")
|
2016-09-20 18:59:06 -05:00
|
|
|
{
|
2016-11-16 07:46:58 -06:00
|
|
|
LOG_TRC("Processing [" << msg << "]. Before canceltiles have " << _queue.size() << " in queue.");
|
2016-09-20 18:59:06 -05:00
|
|
|
const auto seqs = msg.substr(12);
|
|
|
|
StringTokenizer tokens(seqs, ",", StringTokenizer::TOK_IGNORE_EMPTY | StringTokenizer::TOK_TRIM);
|
|
|
|
_queue.erase(std::remove_if(_queue.begin(), _queue.end(),
|
|
|
|
[&tokens](const Payload& v)
|
|
|
|
{
|
|
|
|
const std::string s(v.data(), v.size());
|
2016-11-01 17:40:11 -05:00
|
|
|
// Tile is for a thumbnail, don't cancel it
|
|
|
|
if (s.find("id=") != std::string::npos)
|
|
|
|
return false;
|
2016-09-20 18:59:06 -05:00
|
|
|
for (size_t i = 0; i < tokens.count(); ++i)
|
|
|
|
{
|
|
|
|
if (s.find("ver=" + tokens[i]) != std::string::npos)
|
|
|
|
{
|
2016-11-16 07:46:58 -06:00
|
|
|
LOG_TRC("Matched " << tokens[i] << ", Removing [" << s << "]");
|
2016-09-20 18:59:06 -05:00
|
|
|
return true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return false;
|
|
|
|
|
|
|
|
}), _queue.end());
|
|
|
|
|
|
|
|
// Don't push canceltiles into the queue.
|
2016-11-16 07:46:58 -06:00
|
|
|
LOG_TRC("After canceltiles have " << _queue.size() << " in queue.");
|
2016-09-20 18:59:06 -05:00
|
|
|
return;
|
|
|
|
}
|
Get rid of some fragile string literal length counts
Basically, instead of foo.compare(0, 3, "bar") use
LOOLProtocol::getFirstToken(foo)!="bar". Using a separate length of a
string literal is very fragile, it is easy to get the length wrong, or
forget to change it in case the string changes. See
137e677eb0d6af1996701b2bd1b27a6eb3822613.
It isn't entirely sure to me whether was is kept in a message queue
follows LOOL protocol message syntax, but it seems to be so in
practice, so we can use LOOLProtocol::getFirstToken().
Also, calls like msg.compare(0, 4, "tile") add undocumented implicit
requirements that the token in question must be unique as an initial
substring of the first tokens of all messages. It actually isn't,
there is also "tilecombine". But in this case, that was taken care of
by checking for "tilecombine" first. Ugh. Whether that was by accident
or design is hard to say, but at least there was no comment indicating
intentionality.
We still have lots of similar fragile mis-use of std::string::find().
2016-09-26 12:13:50 -05:00
|
|
|
else if (firstToken == "tilecombine")
|
2016-09-25 15:04:27 -05:00
|
|
|
{
|
2016-09-26 03:35:20 -05:00
|
|
|
// Breakup tilecombine and deduplicate (we are re-combining the tiles
|
|
|
|
// in the get_impl() again)
|
2016-09-25 15:04:27 -05:00
|
|
|
const auto tileCombined = TileCombined::parse(msg);
|
|
|
|
for (auto& tile : tileCombined.getTiles())
|
|
|
|
{
|
2016-09-26 03:35:20 -05:00
|
|
|
const std::string newMsg = tile.serialize("tile");
|
|
|
|
|
|
|
|
removeDuplicate(newMsg);
|
|
|
|
|
|
|
|
MessageQueue::put_impl(Payload(newMsg.data(), newMsg.data() + newMsg.size()));
|
2016-09-25 15:04:27 -05:00
|
|
|
}
|
2016-09-26 03:35:20 -05:00
|
|
|
return;
|
2016-09-25 15:04:27 -05:00
|
|
|
}
|
Get rid of some fragile string literal length counts
Basically, instead of foo.compare(0, 3, "bar") use
LOOLProtocol::getFirstToken(foo)!="bar". Using a separate length of a
string literal is very fragile, it is easy to get the length wrong, or
forget to change it in case the string changes. See
137e677eb0d6af1996701b2bd1b27a6eb3822613.
It isn't entirely sure to me whether was is kept in a message queue
follows LOOL protocol message syntax, but it seems to be so in
practice, so we can use LOOLProtocol::getFirstToken().
Also, calls like msg.compare(0, 4, "tile") add undocumented implicit
requirements that the token in question must be unique as an initial
substring of the first tokens of all messages. It actually isn't,
there is also "tilecombine". But in this case, that was taken care of
by checking for "tilecombine" first. Ugh. Whether that was by accident
or design is hard to say, but at least there was no comment indicating
intentionality.
We still have lots of similar fragile mis-use of std::string::find().
2016-09-26 12:13:50 -05:00
|
|
|
else if (firstToken == "tile")
|
2016-09-26 03:35:20 -05:00
|
|
|
{
|
|
|
|
removeDuplicate(msg);
|
2016-09-23 03:18:54 -05:00
|
|
|
|
2016-09-26 03:35:20 -05:00
|
|
|
MessageQueue::put_impl(value);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
// TODO probably we could deduplacite the invalidation callbacks (later
|
|
|
|
// one wins) the same way as we do for the tiles - to be tested.
|
|
|
|
|
|
|
|
MessageQueue::put_impl(value);
|
|
|
|
}
|
|
|
|
|
|
|
|
void TileQueue::removeDuplicate(const std::string& tileMsg)
|
|
|
|
{
|
Get rid of some fragile string literal length counts
Basically, instead of foo.compare(0, 3, "bar") use
LOOLProtocol::getFirstToken(foo)!="bar". Using a separate length of a
string literal is very fragile, it is easy to get the length wrong, or
forget to change it in case the string changes. See
137e677eb0d6af1996701b2bd1b27a6eb3822613.
It isn't entirely sure to me whether was is kept in a message queue
follows LOOL protocol message syntax, but it seems to be so in
practice, so we can use LOOLProtocol::getFirstToken().
Also, calls like msg.compare(0, 4, "tile") add undocumented implicit
requirements that the token in question must be unique as an initial
substring of the first tokens of all messages. It actually isn't,
there is also "tilecombine". But in this case, that was taken care of
by checking for "tilecombine" first. Ugh. Whether that was by accident
or design is hard to say, but at least there was no comment indicating
intentionality.
We still have lots of similar fragile mis-use of std::string::find().
2016-09-26 12:13:50 -05:00
|
|
|
assert(LOOLProtocol::getFirstToken(tileMsg) == "tile");
|
2016-09-26 03:35:20 -05:00
|
|
|
|
Get rid of some fragile string literal length counts
Basically, instead of foo.compare(0, 3, "bar") use
LOOLProtocol::getFirstToken(foo)!="bar". Using a separate length of a
string literal is very fragile, it is easy to get the length wrong, or
forget to change it in case the string changes. See
137e677eb0d6af1996701b2bd1b27a6eb3822613.
It isn't entirely sure to me whether was is kept in a message queue
follows LOOL protocol message syntax, but it seems to be so in
practice, so we can use LOOLProtocol::getFirstToken().
Also, calls like msg.compare(0, 4, "tile") add undocumented implicit
requirements that the token in question must be unique as an initial
substring of the first tokens of all messages. It actually isn't,
there is also "tilecombine". But in this case, that was taken care of
by checking for "tilecombine" first. Ugh. Whether that was by accident
or design is hard to say, but at least there was no comment indicating
intentionality.
We still have lots of similar fragile mis-use of std::string::find().
2016-09-26 12:13:50 -05:00
|
|
|
// FIXME: This looks rather fragile; but OTOH if I understand correctly this doesn't handle
|
|
|
|
// input from clients, but strings we have created ourselves here in C++ code, so probably we
|
|
|
|
// can be sure that the "ver" parameter is always in such a location that this does what we
|
|
|
|
// mean.
|
2016-10-04 07:23:42 -05:00
|
|
|
// FIXME: also the ver=... is only for debugging from what I can see, so
|
|
|
|
// double-check if we can actually avoid the 'ver' everywhere in the non-debug
|
|
|
|
// builds
|
2016-09-26 03:35:20 -05:00
|
|
|
const std::string newMsg = tileMsg.substr(0, tileMsg.find(" ver"));
|
|
|
|
|
|
|
|
for (size_t i = 0; i < _queue.size(); ++i)
|
2015-11-09 04:36:37 -06:00
|
|
|
{
|
2016-09-26 03:35:20 -05:00
|
|
|
auto& it = _queue[i];
|
|
|
|
const std::string old(it.data(), it.size());
|
|
|
|
const std::string oldMsg = old.substr(0, old.find(" ver"));
|
|
|
|
if (newMsg == oldMsg)
|
2015-11-09 04:36:37 -06:00
|
|
|
{
|
2016-11-16 07:46:58 -06:00
|
|
|
LOG_DBG("Remove duplicate message: " << old << " -> " << tileMsg);
|
2016-09-26 03:35:20 -05:00
|
|
|
_queue.erase(_queue.begin() + i);
|
|
|
|
break;
|
2015-11-09 04:36:37 -06:00
|
|
|
}
|
|
|
|
}
|
2016-09-14 16:42:50 -05:00
|
|
|
}
|
|
|
|
|
2016-09-30 15:00:20 -05:00
|
|
|
int TileQueue::priority(const std::string& tileMsg)
|
2016-09-14 16:42:50 -05:00
|
|
|
{
|
|
|
|
auto tile = TileDesc::parse(tileMsg); //FIXME: Expensive, avoid.
|
|
|
|
|
2016-09-30 15:38:20 -05:00
|
|
|
for (int i = static_cast<int>(_viewOrder.size()) - 1; i >= 0; --i)
|
2016-09-14 16:42:50 -05:00
|
|
|
{
|
2016-09-30 15:00:20 -05:00
|
|
|
auto& cursor = _cursorPositions[_viewOrder[i]];
|
2016-09-23 03:37:33 -05:00
|
|
|
if (tile.intersectsWithRect(cursor.X, cursor.Y, cursor.Width, cursor.Height))
|
2016-09-30 15:00:20 -05:00
|
|
|
return i;
|
2016-09-14 16:42:50 -05:00
|
|
|
}
|
|
|
|
|
2016-09-30 15:00:20 -05:00
|
|
|
return -1;
|
2015-11-09 04:36:37 -06:00
|
|
|
}
|
|
|
|
|
2016-10-04 07:23:42 -05:00
|
|
|
void TileQueue::deprioritizePreviews()
|
|
|
|
{
|
|
|
|
for (size_t i = 0; i < _queue.size(); ++i)
|
|
|
|
{
|
|
|
|
const auto front = _queue.front();
|
|
|
|
const std::string message(front.data(), front.size());
|
|
|
|
|
|
|
|
// stop at the first non-tile or non-'id' (preview) message
|
|
|
|
std::string id;
|
2016-11-16 07:47:11 -06:00
|
|
|
if (LOOLProtocol::getFirstToken(message) != "tile" ||
|
|
|
|
!LOOLProtocol::getTokenStringFromMessage(message, "id", id))
|
|
|
|
{
|
2016-10-04 07:23:42 -05:00
|
|
|
break;
|
2016-11-16 07:47:11 -06:00
|
|
|
}
|
2016-10-04 07:23:42 -05:00
|
|
|
|
|
|
|
_queue.pop_front();
|
|
|
|
_queue.push_back(front);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-09-15 07:40:26 -05:00
|
|
|
MessageQueue::Payload TileQueue::get_impl()
|
|
|
|
{
|
|
|
|
const auto front = _queue.front();
|
|
|
|
|
|
|
|
auto msg = std::string(front.data(), front.size());
|
|
|
|
|
Get rid of some fragile string literal length counts
Basically, instead of foo.compare(0, 3, "bar") use
LOOLProtocol::getFirstToken(foo)!="bar". Using a separate length of a
string literal is very fragile, it is easy to get the length wrong, or
forget to change it in case the string changes. See
137e677eb0d6af1996701b2bd1b27a6eb3822613.
It isn't entirely sure to me whether was is kept in a message queue
follows LOOL protocol message syntax, but it seems to be so in
practice, so we can use LOOLProtocol::getFirstToken().
Also, calls like msg.compare(0, 4, "tile") add undocumented implicit
requirements that the token in question must be unique as an initial
substring of the first tokens of all messages. It actually isn't,
there is also "tilecombine". But in this case, that was taken care of
by checking for "tilecombine" first. Ugh. Whether that was by accident
or design is hard to say, but at least there was no comment indicating
intentionality.
We still have lots of similar fragile mis-use of std::string::find().
2016-09-26 12:13:50 -05:00
|
|
|
std::string id;
|
2016-10-04 07:23:42 -05:00
|
|
|
bool isTile = (LOOLProtocol::getFirstToken(msg) == "tile");
|
|
|
|
bool isPreview = isTile && LOOLProtocol::getTokenStringFromMessage(msg, "id", id);
|
|
|
|
if (!isTile || isPreview)
|
2016-09-15 07:40:26 -05:00
|
|
|
{
|
|
|
|
// Don't combine non-tiles or tiles with id.
|
2016-11-16 07:46:58 -06:00
|
|
|
LOG_TRC("MessageQueue res: " << msg);
|
2016-09-23 03:18:54 -05:00
|
|
|
_queue.pop_front();
|
2016-10-04 07:23:42 -05:00
|
|
|
|
|
|
|
// de-prioritize the other tiles with id - usually the previews in
|
|
|
|
// Impress
|
|
|
|
if (isPreview)
|
|
|
|
deprioritizePreviews();
|
|
|
|
|
2016-09-15 07:40:26 -05:00
|
|
|
return front;
|
|
|
|
}
|
|
|
|
|
2016-09-23 03:18:54 -05:00
|
|
|
// We are handling a tile; first try to find one that is at the cursor's
|
|
|
|
// position, otherwise handle the one that is at the front
|
2016-09-30 15:00:20 -05:00
|
|
|
int prioritized = 0;
|
|
|
|
int prioritySoFar = -1;
|
2016-09-23 03:18:54 -05:00
|
|
|
for (size_t i = 0; i < _queue.size(); ++i)
|
|
|
|
{
|
|
|
|
auto& it = _queue[i];
|
|
|
|
const std::string prio(it.data(), it.size());
|
2016-09-26 03:12:45 -05:00
|
|
|
|
|
|
|
// avoid starving - stop the search when we reach a non-tile,
|
|
|
|
// otherwise we may keep growing the queue of unhandled stuff (both
|
|
|
|
// tiles and non-tiles)
|
2016-11-16 07:47:11 -06:00
|
|
|
if (LOOLProtocol::getFirstToken(prio) != "tile" ||
|
|
|
|
LOOLProtocol::getTokenStringFromMessage(prio, "id", id))
|
|
|
|
{
|
2016-09-26 03:12:45 -05:00
|
|
|
break;
|
2016-11-16 07:47:11 -06:00
|
|
|
}
|
2016-09-26 03:12:45 -05:00
|
|
|
|
2016-11-16 07:47:11 -06:00
|
|
|
const int p = priority(prio);
|
2016-09-30 15:38:20 -05:00
|
|
|
if (p > prioritySoFar)
|
2016-09-23 03:18:54 -05:00
|
|
|
{
|
2016-09-30 15:00:20 -05:00
|
|
|
prioritySoFar = p;
|
|
|
|
prioritized = i;
|
2016-09-23 03:18:54 -05:00
|
|
|
msg = prio;
|
2016-09-30 16:06:26 -05:00
|
|
|
|
|
|
|
// found the highest priority already?
|
|
|
|
if (prioritySoFar == static_cast<int>(_viewOrder.size()) - 1)
|
2016-11-16 07:47:11 -06:00
|
|
|
{
|
2016-09-30 16:06:26 -05:00
|
|
|
break;
|
2016-11-16 07:47:11 -06:00
|
|
|
}
|
2016-09-23 03:18:54 -05:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-09-30 15:00:20 -05:00
|
|
|
_queue.erase(_queue.begin() + prioritized);
|
2016-09-23 03:18:54 -05:00
|
|
|
|
2016-10-04 07:23:42 -05:00
|
|
|
std::vector<TileDesc> tiles;
|
2016-09-15 07:40:26 -05:00
|
|
|
tiles.emplace_back(TileDesc::parse(msg));
|
|
|
|
|
|
|
|
// Combine as many tiles as possible with the top one.
|
2016-09-25 20:30:56 -05:00
|
|
|
for (size_t i = 0; i < _queue.size(); )
|
2016-09-15 07:40:26 -05:00
|
|
|
{
|
2016-09-25 20:30:56 -05:00
|
|
|
auto& it = _queue[i];
|
|
|
|
msg = std::string(it.data(), it.size());
|
2016-11-16 07:47:11 -06:00
|
|
|
if (LOOLProtocol::getFirstToken(msg) != "tile" ||
|
|
|
|
LOOLProtocol::getTokenStringFromMessage(msg, "id", id))
|
2016-09-15 07:40:26 -05:00
|
|
|
{
|
2016-09-25 20:30:56 -05:00
|
|
|
// Don't combine non-tiles or tiles with id.
|
|
|
|
++i;
|
|
|
|
continue;
|
|
|
|
}
|
2016-09-15 07:40:26 -05:00
|
|
|
|
2016-09-25 20:30:56 -05:00
|
|
|
auto tile2 = TileDesc::parse(msg);
|
2016-11-16 07:46:58 -06:00
|
|
|
LOG_TRC("Combining candidate: " << msg);
|
2016-09-15 07:40:26 -05:00
|
|
|
|
2016-09-25 20:30:56 -05:00
|
|
|
// Check if it's on the same row.
|
|
|
|
if (tiles[0].onSameRow(tile2))
|
|
|
|
{
|
|
|
|
tiles.emplace_back(tile2);
|
|
|
|
_queue.erase(_queue.begin() + i);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
++i;
|
2016-09-20 18:20:23 -05:00
|
|
|
}
|
2016-09-15 07:40:26 -05:00
|
|
|
}
|
2016-09-20 18:20:23 -05:00
|
|
|
|
2016-11-16 07:46:58 -06:00
|
|
|
LOG_TRC("Combined " << tiles.size() << " tiles, leaving " << _queue.size() << " in queue.");
|
2016-09-15 07:40:26 -05:00
|
|
|
|
|
|
|
if (tiles.size() == 1)
|
|
|
|
{
|
|
|
|
msg = tiles[0].serialize("tile");
|
2016-11-16 07:46:58 -06:00
|
|
|
LOG_TRC("MessageQueue res: " << msg);
|
2016-09-15 07:40:26 -05:00
|
|
|
return Payload(msg.data(), msg.data() + msg.size());
|
|
|
|
}
|
|
|
|
|
|
|
|
auto tileCombined = TileCombined::create(tiles).serialize("tilecombine");
|
2016-11-16 07:46:58 -06:00
|
|
|
LOG_TRC("MessageQueue res: " << tileCombined);
|
2016-09-15 07:40:26 -05:00
|
|
|
return Payload(tileCombined.data(), tileCombined.data() + tileCombined.size());
|
|
|
|
}
|
|
|
|
|
2015-11-09 04:36:37 -06:00
|
|
|
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|