mirror of
https://github.com/debauchee/barrier.git
synced 2026-05-11 00:58:14 +08:00
* made gui ipc reader more robust by getting rid of reader thread (but read wait now blocks gui thread)
* separated ipc client proxy mutex into read and write (i think read was deadlocking write) * fixed cpu spinning on ipc log send buffer thread (now uses wait cond like before).
This commit is contained in:
@@ -26,10 +26,12 @@
|
||||
IpcClient::IpcClient()
|
||||
{
|
||||
m_Socket = new QTcpSocket(this);
|
||||
m_Reader = new IpcReader(m_Socket);
|
||||
connect(m_Socket, SIGNAL(connected()), this, SLOT(connected()));
|
||||
connect(m_Socket, SIGNAL(error(QAbstractSocket::SocketError)), this, SLOT(error(QAbstractSocket::SocketError)));
|
||||
|
||||
m_Reader = new IpcReader(m_Socket);
|
||||
connect(m_Reader, SIGNAL(readLogLine(const QString&)), this, SLOT(handleReadLogLine(const QString&)));
|
||||
m_Reader->start();
|
||||
}
|
||||
|
||||
IpcClient::~IpcClient()
|
||||
@@ -43,8 +45,6 @@ void IpcClient::connected()
|
||||
write(kIpcHello, 1, typeBuf);
|
||||
|
||||
infoMessage("connection established");
|
||||
|
||||
m_Reader->start();
|
||||
}
|
||||
|
||||
void IpcClient::connectToHost()
|
||||
|
||||
@@ -20,96 +20,98 @@
|
||||
#include "Ipc.h"
|
||||
#include <iostream>
|
||||
#include <QMutex>
|
||||
#include <QByteArray>
|
||||
|
||||
IpcReader::IpcReader(QTcpSocket* socket) :
|
||||
m_Socket(socket),
|
||||
m_ReadyRead(false)
|
||||
m_Socket(socket)
|
||||
{
|
||||
connect(socket, SIGNAL(readyRead()), this, SLOT(readyRead()));
|
||||
}
|
||||
|
||||
IpcReader::~IpcReader()
|
||||
{
|
||||
}
|
||||
|
||||
void IpcReader::readyRead()
|
||||
void IpcReader::start()
|
||||
{
|
||||
connect(m_Socket, SIGNAL(readyRead()), this, SLOT(read()));
|
||||
}
|
||||
|
||||
void IpcReader::read()
|
||||
{
|
||||
QMutexLocker locker(&m_Mutex);
|
||||
std::cout << "ready read" << std::endl;
|
||||
m_ReadyRead = true;
|
||||
}
|
||||
|
||||
void IpcReader::run()
|
||||
{
|
||||
m_Socket->waitForConnected(-1);
|
||||
while (true) {
|
||||
char codeBuf[1];
|
||||
readStream(codeBuf, 1);
|
||||
int code = bytesToInt(codeBuf, 1);
|
||||
|
||||
char codeBuf[1];
|
||||
readStream(codeBuf, 1);
|
||||
switch (code) {
|
||||
case kIpcLogLine: {
|
||||
std::cout << "reading log line" << std::endl;
|
||||
|
||||
switch (codeBuf[0]) {
|
||||
case kIpcLogLine: {
|
||||
char lenBuf[4];
|
||||
readStream(lenBuf, 4);
|
||||
int len = bytesToInt(lenBuf, 4);
|
||||
char lenBuf[4];
|
||||
readStream(lenBuf, 4);
|
||||
int len = bytesToInt(lenBuf, 4);
|
||||
|
||||
char* data = new char[len];
|
||||
readStream(data, len);
|
||||
char* data = new char[len];
|
||||
readStream(data, len);
|
||||
QString line = QString::fromUtf8(data, len);
|
||||
delete data;
|
||||
|
||||
QString line = QString::fromUtf8(data, len);
|
||||
readLogLine(line);
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
std::cerr << "aborting, message invalid: " << (unsigned int)codeBuf[0] << std::endl;
|
||||
return;
|
||||
readLogLine(line);
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
std::cerr << "aborting, message invalid: " << code << std::endl;
|
||||
return;
|
||||
}
|
||||
|
||||
std::cout << "read done" << std::endl;
|
||||
}
|
||||
|
||||
void IpcReader::readStream(char* buffer, int length)
|
||||
bool IpcReader::readStream(char* buffer, int length)
|
||||
{
|
||||
QDataStream stream(m_Socket);
|
||||
std::cout << "reading stream" << std::endl;
|
||||
|
||||
int read = 0;
|
||||
while (read < length) {
|
||||
int ask = length - read;
|
||||
int got = stream.readRawData(buffer, ask);
|
||||
|
||||
if (got == 0) {
|
||||
std::cout << "end of buffer, waiting" << std::endl;
|
||||
|
||||
// i'd love nothing more than to use a wait condition here, but
|
||||
// qt is such a fucker with mutexes (can't lock/unlock between
|
||||
// threads?! wtf?!). i'd just rather not go there (patches welcome).
|
||||
while (!m_ReadyRead) {
|
||||
QThread::usleep(50);
|
||||
}
|
||||
m_ReadyRead = false;
|
||||
if (m_Socket->bytesAvailable() < ask) {
|
||||
std::cout << "buffer too short, waiting" << std::endl;
|
||||
m_Socket->waitForReadyRead(-1);
|
||||
}
|
||||
else if (got == -1) {
|
||||
|
||||
// i really don't trust qt not to copy beyond the array length.
|
||||
// seems like a convoluted an expensive way to copy from the stream :/
|
||||
char* tempBuffer = new char[ask];
|
||||
int got = m_Socket->read(tempBuffer, ask);
|
||||
memcpy(buffer, tempBuffer, got);
|
||||
delete tempBuffer;
|
||||
|
||||
read += got;
|
||||
|
||||
std::cout << "> ask=" << ask << " got=" << got
|
||||
<< " read=" << read << std::endl;
|
||||
|
||||
if (got == -1) {
|
||||
std::cout << "socket ended, aborting" << std::endl;
|
||||
return;
|
||||
return false;
|
||||
}
|
||||
else {
|
||||
read += got;
|
||||
else if (length - read > 0) {
|
||||
std::cout << "more remains, seek to " << got << std::endl;
|
||||
buffer += got;
|
||||
|
||||
std::cout << "> ask=" << ask << " got=" << got
|
||||
<< " read=" << read << std::endl;
|
||||
|
||||
if (length - read > 0) {
|
||||
std::cout << "more remains" << std::endl;
|
||||
}
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
// TODO: qt must have a built in way of converting bytes to int.
|
||||
int IpcReader::bytesToInt(const char *buffer, int size)
|
||||
{
|
||||
if (size == 2) {
|
||||
if (size == 1) {
|
||||
return (unsigned char)buffer[0];
|
||||
}
|
||||
else if (size == 2) {
|
||||
return
|
||||
(((unsigned char)buffer[0]) << 8) +
|
||||
(unsigned char)buffer[1];
|
||||
@@ -122,7 +124,6 @@ int IpcReader::bytesToInt(const char *buffer, int size)
|
||||
(unsigned char)buffer[3];
|
||||
}
|
||||
else {
|
||||
// TODO: other sizes, if needed.
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -17,31 +17,31 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <QThread>
|
||||
#include <QObject>
|
||||
#include <QMutex>
|
||||
|
||||
class QTcpSocket;
|
||||
|
||||
class IpcReader : public QThread
|
||||
class IpcReader : public QObject
|
||||
{
|
||||
Q_OBJECT;
|
||||
|
||||
public:
|
||||
IpcReader(QTcpSocket* socket);
|
||||
virtual ~IpcReader();
|
||||
void run();
|
||||
void stop();
|
||||
void start();
|
||||
|
||||
signals:
|
||||
void readLogLine(const QString& text);
|
||||
|
||||
private:
|
||||
void readStream(char* buffer, int length);
|
||||
bool readStream(char* buffer, int length);
|
||||
int bytesToInt(const char* buffer, int size);
|
||||
|
||||
private slots:
|
||||
void readyRead();
|
||||
void read();
|
||||
|
||||
private:
|
||||
QTcpSocket* m_Socket;
|
||||
bool m_ReadyRead;
|
||||
QMutex m_Mutex;
|
||||
};
|
||||
|
||||
@@ -54,15 +54,6 @@ static const char* synergyIconFiles[] =
|
||||
":/res/icons/16x16/synergy-connected.png"
|
||||
};
|
||||
|
||||
class QThreadImpl : public QThread
|
||||
{
|
||||
public:
|
||||
static void msleep(unsigned long msecs)
|
||||
{
|
||||
QThread::msleep(msecs);
|
||||
}
|
||||
};
|
||||
|
||||
MainWindow::MainWindow(QSettings& settings, AppConfig& appConfig) :
|
||||
m_Settings(settings),
|
||||
m_AppConfig(appConfig),
|
||||
|
||||
Reference in New Issue
Block a user