Took 30 minutes
This commit is contained in:
Lukas Brübach 2026-04-05 21:46:58 +02:00
parent a9b4be3014
commit 04665e4dd8
3 changed files with 94 additions and 43 deletions

View file

@ -348,5 +348,5 @@ int main(int argc, char *argv[])
CountryPixmapGenerator::clear();
UserLevelPixmapGenerator::clear();
return 0;
return ret;
}

View file

@ -1 +1,90 @@
#include "single_instance_manager.h"
SingleInstanceManager::SingleInstanceManager(QObject *parent) : QObject(parent)
{
}
bool SingleInstanceManager::tryRun(const QStringList &initialFiles)
{
serverName = "CockatriceSingleInstance";
QLocalSocket socket;
socket.connectToServer(serverName);
if (socket.waitForConnected(200)) {
// Serialize into buffer first
QByteArray payload;
QDataStream out(&payload, QIODevice::WriteOnly);
out << initialFiles;
// Prefix with size
QByteArray message;
QDataStream msgStream(&message, QIODevice::WriteOnly);
msgStream << quint32(payload.size());
message.append(payload);
socket.write(message);
socket.flush();
socket.waitForBytesWritten(1000);
return false; // Another instance is running
}
// No other instance → start server
server = new QLocalServer(this);
connect(server, &QLocalServer::newConnection, this, &SingleInstanceManager::handleNewConnection);
if (!server->listen(serverName)) {
QLocalServer::removeServer(serverName);
server->listen(serverName);
}
return true;
}
void SingleInstanceManager::handleNewConnection()
{
QLocalSocket *socket = server->nextPendingConnection();
// Per-connection state
auto buffer = new QByteArray();
auto expectedSize = new quint32(0);
connect(socket, &QLocalSocket::readyRead, this, [this, socket, buffer, expectedSize]() {
buffer->append(socket->readAll());
QDataStream stream(buffer, QIODevice::ReadOnly);
while (true) {
// Step 1: read size
if (*expectedSize == 0) {
if (buffer->size() < static_cast<int>(sizeof(quint32)))
return;
stream >> *expectedSize;
}
// Step 2: wait for full payload
if (buffer->size() < static_cast<int>(sizeof(quint32) + *expectedSize))
return;
// Step 3: extract payload
QByteArray payload = buffer->mid(sizeof(quint32), *expectedSize);
QDataStream payloadStream(&payload, QIODevice::ReadOnly);
QStringList files;
payloadStream >> files;
emit filesReceived(files);
// Reset buffer (single message use-case)
buffer->clear();
*expectedSize = 0;
socket->disconnectFromServer();
return;
}
});
connect(socket, &QLocalSocket::disconnected, socket, &QLocalSocket::deleteLater);
}

View file

@ -10,57 +10,19 @@ class SingleInstanceManager : public QObject
{
Q_OBJECT
public:
explicit SingleInstanceManager(QObject *parent = nullptr) : QObject(parent)
{
}
explicit SingleInstanceManager(QObject *parent = nullptr);
bool tryRun(const QStringList &initialFiles)
{
serverName = "CockatriceSingleInstance";
QLocalSocket socket;
socket.connectToServer(serverName);
if (socket.waitForConnected(100)) {
// Another instance is running, send files/URLs to it
QDataStream out(&socket);
out << initialFiles;
socket.flush();
socket.waitForBytesWritten(1000);
return false; // Do not continue in this process
}
// No other instance, create server
server = new QLocalServer(this);
connect(server, &QLocalServer::newConnection, this, &SingleInstanceManager::receiveFiles);
if (!server->listen(serverName)) {
QLocalServer::removeServer(serverName);
server->listen(serverName);
}
return true;
}
bool tryRun(const QStringList &initialFiles);
signals:
void filesReceived(const QStringList &files);
private slots:
void receiveFiles()
{
QLocalSocket *clientConnection = server->nextPendingConnection();
connect(clientConnection, &QLocalSocket::disconnected, clientConnection, &QLocalSocket::deleteLater);
clientConnection->waitForReadyRead(1000);
QDataStream in(clientConnection);
QStringList files;
in >> files;
emit filesReceived(files);
clientConnection->disconnectFromServer();
}
void handleNewConnection();
private:
QString serverName;
QLocalServer *server = nullptr;
};
#endif // COCKATRICE_SINGLE_INSTANCE_MANAGER_H
#endif // COCKATRICE_SINGLE_INSTANCE_MANAGER_H