[Libreoffice-commits] online.git: loolwsd/LOOLSession.hpp loolwsd/LOOLWSD.cpp loolwsd/Makefile.am loolwsd/MessageQueue.cpp loolwsd/MessageQueue.hpp loolwsd/tsqueue.h
Jan Holesovsky
kendy at collabora.com
Mon Nov 9 02:54:35 PST 2015
loolwsd/LOOLSession.hpp | 4 -
loolwsd/LOOLWSD.cpp | 41 +++---------------
loolwsd/Makefile.am | 5 --
loolwsd/MessageQueue.cpp | 107 +++++++++++++++++++++++++++++++++++++++++++++++
loolwsd/MessageQueue.hpp | 82 ++++++++++++++++++++++++++++++++++++
loolwsd/tsqueue.h | 75 --------------------------------
6 files changed, 200 insertions(+), 114 deletions(-)
New commits:
commit 6a1477d8a9ba70e01bfe494f5850ba7eae8ee8c1
Author: Jan Holesovsky <kendy at collabora.com>
Date: Mon Nov 9 11:36:37 2015 +0100
loolwsd: Specialize the MessageQueue a bit.
Introduce a bit of hierarchy there, at some stage we'll want to re-order the
tile requests a bit so that it works better for collaborative editing; for the
moment, removing the duplicate entries is enough.
diff --git a/loolwsd/LOOLSession.hpp b/loolwsd/LOOLSession.hpp
index e84b5d1..2bee3cd 100644
--- a/loolwsd/LOOLSession.hpp
+++ b/loolwsd/LOOLSession.hpp
@@ -29,8 +29,8 @@
#include <Poco/StringTokenizer.h>
#include <Poco/Types.h>
+#include "MessageQueue.hpp"
#include "TileCache.hpp"
-#include "tsqueue.h"
// We have three kinds of Websocket sessions
// 1) Between the master loolwsd server to the end-user LOOL client
@@ -159,7 +159,7 @@ private:
int _curPart;
int _loadPart;
/// Kind::ToClient instances store URLs of completed 'save as' documents.
- tsqueue<std::string> _saveAsQueue;
+ MessageQueue _saveAsQueue;
};
class ChildProcessSession final : public LOOLSession
diff --git a/loolwsd/LOOLWSD.cpp b/loolwsd/LOOLWSD.cpp
index e1cf3d0..3626953 100644
--- a/loolwsd/LOOLWSD.cpp
+++ b/loolwsd/LOOLWSD.cpp
@@ -105,7 +105,7 @@ DEALINGS IN THE SOFTWARE.
#include "LOOLProtocol.hpp"
#include "LOOLSession.hpp"
#include "LOOLWSD.hpp"
-#include "tsqueue.h"
+#include "MessageQueue.hpp"
#include "Util.hpp"
using namespace LOOLProtocol;
@@ -149,7 +149,7 @@ using Poco::NamedMutex;
class QueueHandler: public Runnable
{
public:
- QueueHandler(tsqueue<std::string>& queue):
+ QueueHandler(MessageQueue& queue):
_queue(queue)
{
}
@@ -178,7 +178,7 @@ public:
private:
std::shared_ptr<LOOLSession> _session;
- tsqueue<std::string>& _queue;
+ MessageQueue& _queue;
};
/// Handles the filename part of the convert-to POST request payload.
@@ -347,7 +347,7 @@ public:
return;
}
- tsqueue<std::string> queue;
+ BasicTileQueue queue;
Thread queueHandlerThread;
QueueHandler handler(queue);
@@ -392,22 +392,7 @@ public:
if (kind == LOOLSession::Kind::ToClient && firstLine.size() == static_cast<std::string::size_type>(n))
{
- // Check if it is a "canceltiles" and in that case remove outstanding
- // "tile" messages from the queue.
- if (tokens.count() == 1 && tokens[0] == "canceltiles")
- {
- queue.remove_if([](std::string& x) {
- return (x.find("tile ") == 0 && x.find("id=") == std::string::npos);
- });
-
- // Also forward the "canceltiles" to the child process, if any
- session->handleInput(buffer, n);
- }
- // Filter out duplicated tile messages.
- else if ((firstLine.compare(0, 5, "tile ") != 0) || !queue.alreadyInQueue(firstLine))
- {
- queue.put(firstLine);
- }
+ queue.put(firstLine);
}
else
{
@@ -928,7 +913,7 @@ void LOOLWSD::componentMain()
std::string hello("child " + std::to_string(_childId) + " " + std::to_string(Process::id()));
session->sendTextFrame(hello);
- tsqueue<std::string> queue;
+ TileQueue queue;
Thread queueHandlerThread;
QueueHandler handler(queue);
@@ -950,19 +935,7 @@ void LOOLWSD::componentMain()
// The only kind of messages a child process receives are the single-line ones (?)
assert(firstLine.size() == static_cast<std::string::size_type>(n));
- // Check if it is a "canceltiles" and in that case remove outstanding
- // "tile" messages from the queue.
- if (tokens.count() == 1 && tokens[0] == "canceltiles")
- {
- queue.remove_if([](std::string& x) {
- return (x.find("tile ") == 0 && x.find("id=") == std::string::npos);
- });
- }
- // Filter out duplicated tile messages.
- else if ((firstLine.compare(0, 5, "tile ") != 0) || !queue.alreadyInQueue(firstLine))
- {
- queue.put(firstLine);
- }
+ queue.put(firstLine);
}
}
while (n > 0 && (flags & WebSocket::FRAME_OP_BITMASK) != WebSocket::FRAME_OP_CLOSE);
diff --git a/loolwsd/Makefile.am b/loolwsd/Makefile.am
index c86f449..be1bcb4 100644
--- a/loolwsd/Makefile.am
+++ b/loolwsd/Makefile.am
@@ -4,7 +4,7 @@ bin_PROGRAMS = loolwsd
dist_bin_SCRIPTS = loolwsd-systemplate-setup
-loolwsd_SOURCES = LOOLWSD.cpp LOOLSession.cpp TileCache.cpp Util.cpp LOOLProtocol.cpp
+loolwsd_SOURCES = LOOLWSD.cpp LOOLSession.cpp MessageQueue.cpp TileCache.cpp Util.cpp LOOLProtocol.cpp
noinst_PROGRAMS = loadtest connect lokitclient
@@ -14,8 +14,7 @@ connect_SOURCES = Connect.cpp Util.cpp LOOLProtocol.cpp
lokitclient_SOURCES = LOKitClient.cpp Util.cpp
-noinst_HEADERS = LOKitHelper.hpp LOOLProtocol.hpp LOOLSession.hpp LOOLWSD.hpp LoadTest.hpp TileCache.hpp Util.hpp \
- tsqueue.h \
+noinst_HEADERS = LOKitHelper.hpp LOOLProtocol.hpp LOOLSession.hpp LOOLWSD.hpp LoadTest.hpp MessageQueue.hpp TileCache.hpp Util.hpp \
bundled/include/LibreOfficeKit/LibreOfficeKit.h bundled/include/LibreOfficeKit/LibreOfficeKitEnums.h \
bundled/include/LibreOfficeKit/LibreOfficeKitInit.h bundled/include/LibreOfficeKit/LibreOfficeKitTypes.h
diff --git a/loolwsd/MessageQueue.cpp b/loolwsd/MessageQueue.cpp
new file mode 100644
index 0000000..f37c5b8
--- /dev/null
+++ b/loolwsd/MessageQueue.cpp
@@ -0,0 +1,107 @@
+/* -*- 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>
+
+MessageQueue::~MessageQueue()
+{
+ clear();
+}
+
+void MessageQueue::put(const std::string& value)
+{
+ std::unique_lock<std::mutex> lock(_mutex);
+ put_impl(value);
+ lock.unlock();
+ _cv.notify_one();
+}
+
+std::string MessageQueue::get()
+{
+ std::unique_lock<std::mutex> lock(_mutex);
+ _cv.wait(lock, [this] { return wait_impl(); });
+ return get_impl();
+}
+
+void MessageQueue::clear()
+{
+ std::unique_lock<std::mutex> lock(_mutex);
+ _queue.clear();
+}
+
+void MessageQueue::put_impl(const std::string& value)
+{
+ _queue.push_back(value);
+}
+
+bool MessageQueue::wait_impl() const
+{
+ return _queue.size() > 0;
+}
+
+std::string MessageQueue::get_impl()
+{
+ std::string result = _queue.front();
+ _queue.pop_front();
+ return result;
+}
+
+void MessageQueue::clear_impl()
+{
+ _queue.clear();
+}
+
+void BasicTileQueue::put_impl(const std::string& value)
+{
+ if (value == "canceltiles")
+ {
+ // remove all the existing tiles from the queue
+ _queue.erase(std::remove_if(_queue.begin(), _queue.end(),
+ [](const std::string& v) {
+ // must not remove the tiles with 'id=', they are special, used
+ // eg. for previews etc.
+ return (v.compare(0, 5, "tile ") == 0) && (v.find("id=") == std::string::npos);
+ }
+ ),
+ _queue.end());
+
+ // put the "canceltiles" in front of other messages
+ _queue.push_front(value);
+ }
+ else
+ MessageQueue::put_impl(value);
+}
+
+void TileQueue::put_impl(const std::string& value)
+{
+ if (value.compare(0, 5, "tile ") == 0)
+ {
+ // TODO: implement a real re-ordering here, so that the tiles closest to
+ // the cursor are returned first.
+ // * we will want to put just a general "tile" message to the queue
+ // * add a std::set that handles the tiles
+ // * change the get_impl() to decide which tile is the correct one to
+ // be returned
+ // * we will also need to be informed about the position of the cursor
+ // so that get_impl() returns optimal results
+ //
+ // For now: just don't put duplicates into the queue
+ for (auto it = _queue.cbegin(); it != _queue.cend(); ++it)
+ {
+ if (value == *it)
+ return;
+ }
+ }
+
+ BasicTileQueue::put_impl(value);
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/loolwsd/MessageQueue.hpp b/loolwsd/MessageQueue.hpp
new file mode 100644
index 0000000..f1b8996
--- /dev/null
+++ b/loolwsd/MessageQueue.hpp
@@ -0,0 +1,82 @@
+/* -*- 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/.
+ */
+
+#ifndef INCLUDED_MESSAGEQUEUE_HPP
+#define INCLUDED_MESSAGEQUEUE_HPP
+
+#include "config.h"
+
+#include <condition_variable>
+#include <mutex>
+#include <deque>
+
+/** Thread-safe message queue (FIFO).
+*/
+class MessageQueue
+{
+public:
+ MessageQueue() {}
+ virtual ~MessageQueue();
+
+ MessageQueue(const MessageQueue&) = delete;
+ MessageQueue& operator=(const MessageQueue&) = delete;
+
+ /// Thread safe insert the message.
+ void put(const std::string& value);
+
+ /// Thread safe obtaining of the message.
+ std::string get();
+
+ /// Thread safe removal of all the pending messages.
+ void clear();
+
+private:
+ std::mutex _mutex;
+ std::condition_variable _cv;
+
+protected:
+ virtual void put_impl(const std::string& value);
+
+ virtual bool wait_impl() const;
+
+ virtual std::string get_impl();
+
+ virtual void clear_impl();
+
+ std::deque<std::string> _queue;
+};
+
+/** MessageQueue specialized for handling of tiles.
+
+Used for basic handling of incoming requests, only can remove tiles when it
+gets a "canceltiles" command.
+*/
+class BasicTileQueue : public MessageQueue
+{
+protected:
+ virtual void put_impl(const std::string& value);
+};
+
+/** MessageQueue specialized for priority handling of tiles.
+
+This class builds on BasicTileQueuee, and additonaly provides de-duplication
+of tile requests.
+
+TODO: we'll need to add reordering of the tiles at some stage here too - so
+that the ones closest to the cursor position are returned first.
+*/
+class TileQueue : public BasicTileQueue
+{
+protected:
+ virtual void put_impl(const std::string& value);
+};
+
+#endif
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/loolwsd/tsqueue.h b/loolwsd/tsqueue.h
deleted file mode 100644
index 94a36cd..0000000
--- a/loolwsd/tsqueue.h
+++ /dev/null
@@ -1,75 +0,0 @@
-/* -*- 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/.
- */
-
-#ifndef INCLUDED_TSQUEUE_H
-#define INCLUDED_TSQUEUE_H
-
-#include "config.h"
-
-#include <condition_variable>
-#include <mutex>
-#include <deque>
-
-// Thread-safe queue
-
-template <class T>
-class tsqueue
-{
-public:
- void put(const T& value)
- {
- std::unique_lock<std::mutex> lock(_mutex);
- _queue.push_back(value);
- lock.unlock();
- _cv.notify_one();
- }
-
- T get()
- {
- std::unique_lock<std::mutex> lock(_mutex);
- _cv.wait(lock, [this] { return _queue.size() > 0; });
- T result = _queue.front();
- _queue.pop_front();
- return result;
- }
-
- void clear()
- {
- std::unique_lock<std::mutex> lock(_mutex);
- while (_queue.size())
- _queue.pop_front();
- }
-
- template<class UnaryPredicate>
- void remove_if(UnaryPredicate p)
- {
- std::unique_lock<std::mutex> lock(_mutex);
- _queue.erase(std::remove_if(_queue.begin(), _queue.end(), p),
- _queue.end());
- }
-
- bool alreadyInQueue(std::string cmd) {
- std::unique_lock<std::mutex> lock(_mutex);
- for (auto it = _queue.cbegin(); it != _queue.cend(); ++it) {
- if (cmd == *it) {
- return true;
- }
- }
- return false;
- }
-
-private:
- std::mutex _mutex;
- std::condition_variable _cv;
- std::deque<T> _queue;
-};
-
-#endif
-
-/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
More information about the Libreoffice-commits
mailing list