more ISL code, mutex fixes

This commit is contained in:
Max-Wilhelm Bruker 2012-03-12 00:36:44 +01:00
parent 0ae18d7b2e
commit 572e4eaafa
9 changed files with 107 additions and 48 deletions

View file

@ -34,6 +34,8 @@
Server::Server(QObject *parent)
: QObject(parent), serverMutex(QMutex::Recursive), nextGameId(0), nextReplayId(0)
{
qRegisterMetaType<ServerInfo_Game>("ServerInfo_Game");
qRegisterMetaType<ServerInfo_Room>("ServerInfo_Room");
}
Server::~Server()
@ -170,22 +172,22 @@ void Server::externalUserLeft(QString userName)
clients[i]->sendProtocolItem(*se);
}
void Server::broadcastRoomUpdate()
void Server::broadcastRoomUpdate(const ServerInfo_Room &roomInfo, bool sendToIsl)
{
QMutexLocker locker(&serverMutex);
Server_Room *room = static_cast<Server_Room *>(sender());
Event_ListRooms event;
ServerInfo_Room *roomInfo = event.add_room_list();
room->roomMutex.lock();
roomInfo->CopyFrom(room->getInfo(false, false, true));
room->roomMutex.unlock();
event.add_room_list()->CopyFrom(roomInfo);
SessionEvent *se = Server_ProtocolHandler::prepareSessionEvent(event);
serverMutex.lock();
for (int i = 0; i < clients.size(); ++i)
if (clients[i]->getAcceptsRoomListChanges())
clients[i]->sendProtocolItem(*se);
serverMutex.unlock();
if (sendToIsl)
sendIslMessage(*se);
delete se;
}
@ -193,7 +195,7 @@ void Server::addRoom(Server_Room *newRoom)
{
QMutexLocker locker(&serverMutex);
rooms.insert(newRoom->getId(), newRoom);
connect(newRoom, SIGNAL(roomInfoChanged()), this, SLOT(broadcastRoomUpdate()));
connect(newRoom, SIGNAL(roomInfoChanged(ServerInfo_Room)), this, SLOT(broadcastRoomUpdate(const ServerInfo_Room &)), Qt::QueuedConnection);
}
int Server::getUsersCount() const

View file

@ -6,6 +6,7 @@
#include <QMap>
#include <QMutex>
#include "pb/serverinfo_user.pb.h"
#include "pb/serverinfo_room.pb.h"
class Server_Game;
class Server_Room;
@ -26,7 +27,7 @@ class Server : public QObject
signals:
void pingClockTimeout();
private slots:
void broadcastRoomUpdate();
void broadcastRoomUpdate(const ServerInfo_Room &roomInfo, bool sendToIsl = false);
public:
mutable QMutex serverMutex;
Server(QObject *parent = 0);
@ -68,6 +69,7 @@ public:
protected slots:
void externalUserJoined(ServerInfo_User userInfo);
void externalUserLeft(QString userName);
void externalRoomUpdated(ServerInfo_Room roomInfo);
protected:
void prepareDestroy();
QList<Server_ProtocolHandler *> clients;

View file

@ -271,7 +271,7 @@ void Server_Game::doStartGameIfReady()
nextTurn();
locker.unlock();
room->broadcastGameListUpdate(this);
emit gameInfoChanged(getInfo());
}
void Server_Game::startGameIfReady()
@ -364,7 +364,7 @@ Server_Player *Server_Game::addPlayer(Server_ProtocolHandler *handler, bool spec
}
if (broadcastUpdate)
room->broadcastGameListUpdate(this);
emit gameInfoChanged(getInfo());
return newPlayer;
}
@ -409,7 +409,7 @@ void Server_Game::removePlayer(Server_Player *player)
if (gameStarted && playerActive)
nextTurn();
}
room->broadcastGameListUpdate(this);
emit gameInfoChanged(getInfo());
}
void Server_Game::removeArrowsToPlayer(GameEventStorage &ges, Server_Player *player)

View file

@ -67,6 +67,7 @@ private:
GameReplay *currentReplay;
signals:
void sigStartGameIfReady();
void gameInfoChanged(ServerInfo_Game gameInfo);
private slots:
void pingClockTimeout();
void doStartGameIfReady();

View file

@ -695,11 +695,16 @@ Response::ResponseCode Server_ProtocolHandler::cmdCreateGame(const Command_Creat
QString description = QString::fromStdString(cmd.description());
if (description.size() > 60)
description = description.left(60);
Server_Game *game = room->createGame(description, QString::fromStdString(cmd.password()), cmd.max_players(), gameTypes, cmd.only_buddies(), cmd.only_registered(), cmd.spectators_allowed(), cmd.spectators_need_password(), cmd.spectators_can_talk(), cmd.spectators_see_everything(), this);
Server_Game *game = new Server_Game(this, server->getNextGameId(), description, QString::fromStdString(cmd.password()), cmd.max_players(), gameTypes, cmd.only_buddies(), cmd.only_registered(), cmd.spectators_allowed(), cmd.spectators_need_password(), cmd.spectators_can_talk(), cmd.spectators_see_everything(), room);
game->moveToThread(room->thread());
QMutexLocker gameListLocker(&gameListMutex);
game->gameMutex.lock();
room->addGame(game);
Server_Player *creator = game->getPlayers().values().first();
QMutexLocker gameListLocker(&gameListMutex);
games.insert(game->getGameId(), QPair<Server_Game *, Server_Player *>(game, creator));
Event_GameJoined event1;

View file

@ -12,6 +12,7 @@
Server_Room::Server_Room(int _id, const QString &_name, const QString &_description, bool _autoJoin, const QString &_joinMessage, const QStringList &_gameTypes, Server *parent)
: QObject(parent), id(_id), name(_name), description(_description), autoJoin(_autoJoin), joinMessage(_joinMessage), gameTypes(_gameTypes), roomMutex(QMutex::Recursive)
{
connect(this, SIGNAL(gameListChanged(ServerInfo_Game)), this, SLOT(broadcastGameListUpdate(ServerInfo_Game)), Qt::QueuedConnection);
}
Server_Room::~Server_Room()
@ -32,14 +33,14 @@ Server *Server_Room::getServer() const
return static_cast<Server *>(parent());
}
ServerInfo_Room Server_Room::getInfo(bool complete, bool showGameTypes, bool updating) const
ServerInfo_Room Server_Room::getInfo(bool complete, bool showGameTypes, bool updating, bool includeExternalData) const
{
QMutexLocker locker(&roomMutex);
ServerInfo_Room result;
result.set_room_id(id);
result.set_game_count(games.size());
result.set_player_count(userList.size());
result.set_game_count(games.size() + externalGames.size());
result.set_player_count(userList.size() + externalUsers.size());
if (!updating) {
result.set_name(name.toStdString());
@ -51,9 +52,19 @@ ServerInfo_Room Server_Room::getInfo(bool complete, bool showGameTypes, bool upd
QMapIterator<int, Server_Game *> gameIterator(games);
while (gameIterator.hasNext())
result.add_game_list()->CopyFrom(gameIterator.next().value()->getInfo());
if (includeExternalData) {
QMapIterator<int, ServerInfo_Game> externalGameIterator(externalGames);
while (externalGameIterator.hasNext())
result.add_game_list()->CopyFrom(externalGameIterator.next().value());
}
for (int i = 0; i < userList.size(); ++i)
result.add_user_list()->CopyFrom(userList[i]->copyUserInfo(false));
if (includeExternalData) {
QMapIterator<QString, ServerInfo_User_Container> externalUserIterator(externalUsers);
while (externalUserIterator.hasNext())
result.add_user_list()->CopyFrom(externalUserIterator.next().value().copyUserInfo(false));
}
}
if (complete || showGameTypes)
for (int i = 0; i < gameTypes.size(); ++i) {
@ -83,7 +94,7 @@ void Server_Room::addClient(Server_ProtocolHandler *client)
userList.append(client);
roomMutex.unlock();
emit roomInfoChanged();
emit roomInfoChanged(getInfo(false, false, true));
}
void Server_Room::removeClient(Server_ProtocolHandler *client)
@ -96,7 +107,34 @@ void Server_Room::removeClient(Server_ProtocolHandler *client)
event.set_name(client->getUserInfo()->name());
sendRoomEvent(prepareRoomEvent(event));
emit roomInfoChanged();
emit roomInfoChanged(getInfo(false, false, true));
}
void Server_Room::addExternalUser(const ServerInfo_User &userInfo)
{
ServerInfo_User_Container userInfoContainer(userInfo);
Event_JoinRoom event;
event.mutable_user_info()->CopyFrom(userInfoContainer.copyUserInfo(false));
sendRoomEvent(prepareRoomEvent(event), false);
roomMutex.lock();
externalUsers.insert(QString::fromStdString(userInfo.name()), userInfoContainer);
roomMutex.unlock();
emit roomInfoChanged(getInfo(false, false, true));
}
void Server_Room::removeExternalUser(const QString &name)
{
roomMutex.lock();
externalUsers.remove(name);
roomMutex.unlock();
Event_LeaveRoom event;
event.set_name(name.toStdString());
sendRoomEvent(prepareRoomEvent(event), false);
emit roomInfoChanged(getInfo(false, false, true));
}
void Server_Room::say(Server_ProtocolHandler *client, const QString &s)
@ -107,39 +145,34 @@ void Server_Room::say(Server_ProtocolHandler *client, const QString &s)
sendRoomEvent(prepareRoomEvent(event));
}
void Server_Room::sendRoomEvent(RoomEvent *event)
void Server_Room::sendRoomEvent(RoomEvent *event, bool sendToIsl)
{
QMutexLocker locker(&roomMutex);
roomMutex.lock();
for (int i = 0; i < userList.size(); ++i)
userList[i]->sendProtocolItem(*event);
roomMutex.unlock();
if (sendToIsl)
static_cast<Server *>(parent())->sendIslMessage(*event);
delete event;
}
void Server_Room::broadcastGameListUpdate(Server_Game *game)
void Server_Room::broadcastGameListUpdate(ServerInfo_Game gameInfo)
{
QMutexLocker locker(&roomMutex);
Event_ListGames event;
event.add_game_list()->CopyFrom(game->getInfo());
event.add_game_list()->CopyFrom(gameInfo);
sendRoomEvent(prepareRoomEvent(event));
}
Server_Game *Server_Room::createGame(const QString &description, const QString &password, int maxPlayers, const QList<int> &gameTypes, bool onlyBuddies, bool onlyRegistered, bool spectatorsAllowed, bool spectatorsNeedPassword, bool spectatorsCanTalk, bool spectatorsSeeEverything, Server_ProtocolHandler *creator)
void Server_Room::addGame(Server_Game *game)
{
QMutexLocker locker(&roomMutex);
// Lock roomMutex and gameMutex before calling this
Server_Game *newGame = new Server_Game(creator, static_cast<Server *>(parent())->getNextGameId(), description, password, maxPlayers, gameTypes, onlyBuddies, onlyRegistered, spectatorsAllowed, spectatorsNeedPassword, spectatorsCanTalk, spectatorsSeeEverything, this);
newGame->moveToThread(thread());
// This mutex needs to be unlocked by the caller.
newGame->gameMutex.lock();
games.insert(newGame->getGameId(), newGame);
broadcastGameListUpdate(newGame);
emit roomInfoChanged();
return newGame;
connect(game, SIGNAL(gameInfoChanged(ServerInfo_Game)), this, SLOT(broadcastGameListUpdate(ServerInfo_Game)));
games.insert(game->getGameId(), game);
emit gameListChanged(game->getInfo());
emit roomInfoChanged(getInfo(false, false, true));
}
void Server_Room::removeGame(Server_Game *game)
@ -147,10 +180,11 @@ void Server_Room::removeGame(Server_Game *game)
// No need to lock roomMutex or gameMutex. This method is only
// called from ~Server_Game, which locks both mutexes anyway beforehand.
broadcastGameListUpdate(game);
disconnect(game, 0, this, 0);
emit gameListChanged(game->getInfo());
games.remove(game->getGameId());
emit roomInfoChanged();
emit roomInfoChanged(getInfo(false, false, true));
}
int Server_Room::getGamesCreatedByUser(const QString &userName) const

View file

@ -6,7 +6,9 @@
#include <QObject>
#include <QStringList>
#include <QMutex>
#include <QMetaType>
#include "pb/serverinfo_room.pb.h"
#include "serverinfo_user_container.h"
class Server_ProtocolHandler;
class RoomEvent;
@ -19,7 +21,8 @@ class Server;
class Server_Room : public QObject {
Q_OBJECT
signals:
void roomInfoChanged();
void roomInfoChanged(ServerInfo_Room roomInfo);
void gameListChanged(ServerInfo_Game gameInfo);
private:
int id;
QString name;
@ -28,7 +31,11 @@ private:
QString joinMessage;
QStringList gameTypes;
QMap<int, Server_Game *> games;
QMap<int, ServerInfo_Game> externalGames;
QList<Server_ProtocolHandler *> userList;
QMap<QString, ServerInfo_User_Container> externalUsers;
private slots:
void broadcastGameListUpdate(ServerInfo_Game gameInfo);
public:
mutable QMutex roomMutex;
Server_Room(int _id, const QString &_name, const QString &_description, bool _autoJoin, const QString &_joinMessage, const QStringList &_gameTypes, Server *parent);
@ -41,19 +48,26 @@ public:
const QStringList &getGameTypes() const { return gameTypes; }
const QMap<int, Server_Game *> &getGames() const { return games; }
Server *getServer() const;
ServerInfo_Room getInfo(bool complete, bool showGameTypes = false, bool updating = false) const;
ServerInfo_Room getInfo(bool complete, bool showGameTypes = false, bool updating = false, bool includeExternalData = true) const;
int getGamesCreatedByUser(const QString &name) const;
QList<ServerInfo_Game> getGamesOfUser(const QString &name) const;
void addClient(Server_ProtocolHandler *client);
void removeClient(Server_ProtocolHandler *client);
void addExternalUser(const ServerInfo_User &userInfo);
void removeExternalUser(const QString &name);
void say(Server_ProtocolHandler *client, const QString &s);
void broadcastGameListUpdate(Server_Game *game);
Server_Game *createGame(const QString &description, const QString &password, int maxPlayers, const QList<int> &_gameTypes, bool onlyBuddies, bool onlyRegistered, bool spectatorsAllowed, bool spectatorsNeedPassword, bool spectatorsCanTalk, bool spectatorsSeeEverything, Server_ProtocolHandler *creator);
void addGame(Server_Game *game);
void removeGame(Server_Game *game);
void sendRoomEvent(RoomEvent *event);
void sendRoomEvent(RoomEvent *event, bool sendToIsl = true);
RoomEvent *prepareRoomEvent(const ::google::protobuf::Message &roomEvent);
};
Q_DECLARE_METATYPE(ServerInfo_Game)
Q_DECLARE_METATYPE(ServerInfo_Room)
#endif

View file

@ -107,7 +107,7 @@ void IslInterface::initServer()
while (roomIterator.hasNext()) {
Server_Room *room = roomIterator.next().value();
room->roomMutex.lock();
event.add_room_list()->CopyFrom(room->getInfo(true, true, false));
event.add_room_list()->CopyFrom(room->getInfo(true, true, false, false));
}
IslMessage message;

View file

@ -856,6 +856,7 @@ void Servatrice::addIslInterface(int serverId, IslInterface *interface)
islInterfaces.insert(serverId, interface);
connect(interface, SIGNAL(externalUserJoined(ServerInfo_User)), this, SLOT(externalUserJoined(ServerInfo_User)));
connect(interface, SIGNAL(externalUserLeft(QString)), this, SLOT(externalUserLeft(QString)));
connect(interface, SIGNAL(externalRoomUpdated(ServerInfo_Room)), this, SLOT(externalRoomUpdated(const ServerInfo_Room &)));
}
void Servatrice::removeIslInterface(int serverId)