From d61d9c98a0aaf9dae085f2d8418b0f8453b1d48f Mon Sep 17 00:00:00 2001 From: Fabio Bas Date: Tue, 19 Jul 2016 11:32:00 +0200 Subject: [PATCH] Avoid locking on local server shutdown --- cockatrice/src/localserver.cpp | 4 ++++ common/server.cpp | 22 ---------------------- servatrice/src/servatrice.cpp | 24 ++++++++++++++++++++++++ 3 files changed, 28 insertions(+), 22 deletions(-) diff --git a/cockatrice/src/localserver.cpp b/cockatrice/src/localserver.cpp index c02a0562..e9035e82 100644 --- a/cockatrice/src/localserver.cpp +++ b/cockatrice/src/localserver.cpp @@ -11,6 +11,10 @@ LocalServer::LocalServer(QObject *parent) LocalServer::~LocalServer() { + // LocalServer is single threaded so it doesn't need locks on this + while (!clients.isEmpty()) + clients.first()->prepareDestroy(); + prepareDestroy(); } diff --git a/common/server.cpp b/common/server.cpp index df590227..768fb752 100644 --- a/common/server.cpp +++ b/common/server.cpp @@ -59,28 +59,6 @@ Server::~Server() void Server::prepareDestroy() { - // dirty :( - clientsLock.lockForRead(); - for (int i = 0; i < clients.size(); ++i) - QMetaObject::invokeMethod(clients.at(i), "prepareDestroy", Qt::QueuedConnection); - clientsLock.unlock(); - - bool done = false; - - class SleeperThread : public QThread - { - public: - static void msleep(unsigned long msecs) { QThread::usleep(msecs); } - }; - - do { - SleeperThread::msleep(10); - clientsLock.lockForRead(); - if (clients.isEmpty()) - done = true; - clientsLock.unlock(); - } while (!done); - roomsLock.lockForWrite(); QMapIterator roomIterator(rooms); while (roomIterator.hasNext()) diff --git a/servatrice/src/servatrice.cpp b/servatrice/src/servatrice.cpp index 3aaac10f..88e942dc 100644 --- a/servatrice/src/servatrice.cpp +++ b/servatrice/src/servatrice.cpp @@ -181,6 +181,30 @@ Servatrice::Servatrice(QObject *parent) Servatrice::~Servatrice() { gameServer->close(); + + // clients live in other threads, we need to lock them + clientsLock.lockForRead(); + for (int i = 0; i < clients.size(); ++i) + QMetaObject::invokeMethod(clients.at(i), "prepareDestroy", Qt::QueuedConnection); + clientsLock.unlock(); + + // client destruction is asynchronous, wait for all clients to be gone + bool done = false; + + class SleeperThread : public QThread + { + public: + static void msleep(unsigned long msecs) { QThread::usleep(msecs); } + }; + + do { + SleeperThread::msleep(10); + clientsLock.lockForRead(); + if (clients.isEmpty()) + done = true; + clientsLock.unlock(); + } while (!done); + prepareDestroy(); }