From 45890b836b195713c9c27c430498eaafb3e7c058 Mon Sep 17 00:00:00 2001 From: Max-Wilhelm Bruker Date: Tue, 22 Mar 2011 20:45:18 +0100 Subject: [PATCH] added send buffer to limit socket operations to one thread --- common/server.h | 2 ++ common/server_protocolhandler.cpp | 8 ++++++++ common/server_protocolhandler.h | 4 ++++ servatrice/src/serversocketinterface.cpp | 26 +++++++++++++++++------- servatrice/src/serversocketinterface.h | 7 +++++++ 5 files changed, 40 insertions(+), 7 deletions(-) diff --git a/common/server.h b/common/server.h index 552fd8ea..324ae860 100644 --- a/common/server.h +++ b/common/server.h @@ -4,6 +4,7 @@ #include #include #include +#include class Server_Game; class Server_Room; @@ -22,6 +23,7 @@ private slots: void gameClosing(int gameId); void broadcastRoomUpdate(); public: + mutable QMutex serverMutex; Server(QObject *parent = 0); ~Server(); AuthenticationResult loginUser(Server_ProtocolHandler *session, QString &name, const QString &password); diff --git a/common/server_protocolhandler.cpp b/common/server_protocolhandler.cpp index 69014487..6aa78e03 100644 --- a/common/server_protocolhandler.cpp +++ b/common/server_protocolhandler.cpp @@ -17,6 +17,7 @@ Server_ProtocolHandler::Server_ProtocolHandler(Server *_server, QObject *parent) : QObject(parent), server(_server), authState(PasswordWrong), acceptsUserListChanges(false), acceptsRoomListChanges(false), userInfo(0), timeRunning(0), lastDataReceived(0) { connect(server, SIGNAL(pingClockTimeout()), this, SLOT(pingClockTimeout())); + connect(this, SIGNAL(sigGameCreated(Server_Game *)), this, SLOT(processSigGameCreated(Server_Game *)), Qt::QueuedConnection); } Server_ProtocolHandler::~Server_ProtocolHandler() @@ -430,6 +431,13 @@ ResponseCode Server_ProtocolHandler::cmdCreateGame(Command_CreateGame *cmd, Comm void Server_ProtocolHandler::gameCreated(Server_Game *game) { + emit sigGameCreated(game); +} + +void Server_ProtocolHandler::processSigGameCreated(Server_Game *game) +{ + QMutexLocker locker(&game->gameMutex); + Server_Player *creator = game->getPlayers().values().first(); games.insert(game->getGameId(), QPair(game, creator)); diff --git a/common/server_protocolhandler.h b/common/server_protocolhandler.h index 075ba0cf..3234bdb3 100644 --- a/common/server_protocolhandler.h +++ b/common/server_protocolhandler.h @@ -91,7 +91,11 @@ private: ResponseCode processCommandHelper(Command *command, CommandContainer *cont); private slots: void pingClockTimeout(); + void processSigGameCreated(Server_Game *game); +signals: + void sigGameCreated(Server_Game *game); public: + mutable QMutex protocolHandlerMutex; Server_ProtocolHandler(Server *_server, QObject *parent = 0); ~Server_ProtocolHandler(); void playerRemovedFromGame(Server_Game *game); diff --git a/servatrice/src/serversocketinterface.cpp b/servatrice/src/serversocketinterface.cpp index 2a65e8b6..ff91c99c 100644 --- a/servatrice/src/serversocketinterface.cpp +++ b/servatrice/src/serversocketinterface.cpp @@ -35,18 +35,18 @@ ServerSocketInterface::ServerSocketInterface(Servatrice *_server, QTcpSocket *_socket, QObject *parent) : Server_ProtocolHandler(_server, parent), servatrice(_server), socket(_socket), topLevelItem(0) { - xmlWriter = new QXmlStreamWriter; - xmlWriter->setDevice(socket); - + xmlWriter = new QXmlStreamWriter(&xmlBuffer); xmlReader = new QXmlStreamReader; connect(socket, SIGNAL(readyRead()), this, SLOT(readClient())); connect(socket, SIGNAL(disconnected()), this, SLOT(deleteLater())); connect(socket, SIGNAL(error(QAbstractSocket::SocketError)), this, SLOT(catchSocketError(QAbstractSocket::SocketError))); + connect(this, SIGNAL(xmlBufferChanged()), this, SLOT(flushXmlBuffer()), Qt::QueuedConnection); xmlWriter->writeStartDocument(); xmlWriter->writeStartElement("cockatrice_server_stream"); xmlWriter->writeAttribute("version", QString::number(ProtocolItem::protocolVersion)); + flushXmlBuffer(); int maxUsers = _server->getMaxUsersPerAddress(); if ((maxUsers > 0) && (_server->getUsersWithAddress(socket->peerAddress()) >= maxUsers)) { @@ -58,6 +58,8 @@ ServerSocketInterface::ServerSocketInterface(Servatrice *_server, QTcpSocket *_s ServerSocketInterface::~ServerSocketInterface() { + QMutexLocker locker(&protocolHandlerMutex); + logger->logMessage("ServerSocketInterface destructor"); socket->flush(); @@ -75,8 +77,18 @@ void ServerSocketInterface::processProtocolItem(ProtocolItem *item) processCommandContainer(cont); } +void ServerSocketInterface::flushXmlBuffer() +{ + QMutexLocker locker(&xmlBufferMutex); + socket->write(xmlBuffer.toUtf8()); + socket->flush(); + xmlBuffer.clear(); +} + void ServerSocketInterface::readClient() { + QMutexLocker locker(&protocolHandlerMutex); + QByteArray data = socket->readAll(); logger->logMessage(QString(data)); xmlReader->addData(data); @@ -101,13 +113,13 @@ void ServerSocketInterface::catchSocketError(QAbstractSocket::SocketError socket void ServerSocketInterface::sendProtocolItem(ProtocolItem *item, bool deleteItem) { - static QMutex mutex; - mutex.lock(); + QMutexLocker locker(&xmlBufferMutex); + item->write(xmlWriter); - socket->flush(); - mutex.unlock(); if (deleteItem) delete item; + + emit xmlBufferChanged(); } int ServerSocketInterface::getUserIdInDB(const QString &name) const diff --git a/servatrice/src/serversocketinterface.h b/servatrice/src/serversocketinterface.h index f55dfd12..8f7b937e 100644 --- a/servatrice/src/serversocketinterface.h +++ b/servatrice/src/serversocketinterface.h @@ -22,6 +22,7 @@ #include #include +#include #include "server_protocolhandler.h" class QTcpSocket; @@ -30,6 +31,7 @@ class QXmlStreamReader; class QXmlStreamWriter; class DeckList; class TopLevelProtocolItem; +class QByteArray; class ServerSocketInterface : public Server_ProtocolHandler { @@ -38,11 +40,16 @@ private slots: void readClient(); void catchSocketError(QAbstractSocket::SocketError socketError); void processProtocolItem(ProtocolItem *item); + void flushXmlBuffer(); +signals: + void xmlBufferChanged(); private: + QMutex xmlBufferMutex; Servatrice *servatrice; QTcpSocket *socket; QXmlStreamWriter *xmlWriter; QXmlStreamReader *xmlReader; + QString xmlBuffer; TopLevelProtocolItem *topLevelItem; int getUserIdInDB(const QString &name) const;