From afdcb9cefe22358617d20de1478976baea286e6e Mon Sep 17 00:00:00 2001 From: Xinyu Hou Date: Mon, 13 Jul 2015 11:00:10 +0100 Subject: [PATCH] Made buffer thread wait until there is a GUI client #4721 Conflicts: src/lib/ipc/IpcLogOutputter.cpp --- src/lib/ipc/IpcLogOutputter.cpp | 16 ++++++++-------- src/lib/ipc/IpcLogOutputter.h | 4 +++- src/lib/synergy/DaemonApp.cpp | 2 +- src/test/unittests/ipc/IpcLogOutputterTests.cpp | 17 ++++++++--------- 4 files changed, 20 insertions(+), 19 deletions(-) diff --git a/src/lib/ipc/IpcLogOutputter.cpp b/src/lib/ipc/IpcLogOutputter.cpp index 276e0a94..b61c5386 100644 --- a/src/lib/ipc/IpcLogOutputter.cpp +++ b/src/lib/ipc/IpcLogOutputter.cpp @@ -37,7 +37,7 @@ enum EIpcLogOutputter { kBufferRateTimeLimit = 1 // seconds }; -IpcLogOutputter::IpcLogOutputter(IpcServer& ipcServer, bool useThread) : +IpcLogOutputter::IpcLogOutputter(IpcServer& ipcServer, EIpcClientType clientType, bool useThread) : m_ipcServer(ipcServer), m_bufferMutex(ARCH->newMutex()), m_sending(false), @@ -50,7 +50,8 @@ IpcLogOutputter::IpcLogOutputter(IpcServer& ipcServer, bool useThread) : m_bufferRateWriteLimit(kBufferRateWriteLimit), m_bufferRateTimeLimit(kBufferRateTimeLimit), m_bufferWriteCount(0), - m_bufferRateStart(ARCH->time()) + m_bufferRateStart(ARCH->time()), + m_clientType(clientType) { if (useThread) { m_bufferThread = new Thread(new TMethodJob( @@ -102,7 +103,9 @@ IpcLogOutputter::write(ELevel, const char* text) } appendBuffer(text); - notifyBuffer(); + if (m_ipcServer.hasClients(m_clientType)) { + notifyBuffer(); + } return true; } @@ -141,7 +144,7 @@ IpcLogOutputter::bufferThread(void*) try { while (m_running) { - if (m_buffer.empty()) { + if (m_buffer.empty() || !m_ipcServer.hasClients(m_clientType)) { ArchMutexLock lock(m_notifyMutex); ARCH->waitCondVar(m_notifyCond, m_notifyMutex, -1); } @@ -184,10 +187,7 @@ IpcLogOutputter::getChunk(size_t count) void IpcLogOutputter::sendBuffer() { - if (m_buffer.empty() || !m_ipcServer.hasClients(kIpcClientGui)) { - if (!m_buffer.empty()) { - m_buffer.clear(); - } + if (m_buffer.empty() || !m_ipcServer.hasClients(m_clientType)) { return; } diff --git a/src/lib/ipc/IpcLogOutputter.h b/src/lib/ipc/IpcLogOutputter.h index a6a476a6..f5e771a5 100644 --- a/src/lib/ipc/IpcLogOutputter.h +++ b/src/lib/ipc/IpcLogOutputter.h @@ -21,6 +21,7 @@ #include "arch/Arch.h" #include "arch/IArchMultithread.h" #include "base/ILogOutputter.h" +#include "ipc/Ipc.h" #include @@ -39,7 +40,7 @@ public: If \p useThread is \c false, then the buffer needs to be sent manually using the \c sendBuffer() function. */ - IpcLogOutputter(IpcServer& ipcServer, bool useThread); + IpcLogOutputter(IpcServer& ipcServer, EIpcClientType clientType, bool useThread); virtual ~IpcLogOutputter(); // ILogOutputter overrides @@ -113,4 +114,5 @@ private: UInt16 m_bufferWriteCount; double m_bufferRateStart; bool m_useThread; + EIpcClientType m_clientType; }; diff --git a/src/lib/synergy/DaemonApp.cpp b/src/lib/synergy/DaemonApp.cpp index 15ff14df..bb1ef91f 100644 --- a/src/lib/synergy/DaemonApp.cpp +++ b/src/lib/synergy/DaemonApp.cpp @@ -211,7 +211,7 @@ DaemonApp::mainLoop(bool logToFile) m_ipcServer = new IpcServer(m_events, &multiplexer); // send logging to gui via ipc, log system adopts outputter. - m_ipcLogOutputter = new IpcLogOutputter(*m_ipcServer, true); + m_ipcLogOutputter = new IpcLogOutputter(*m_ipcServer, kIpcClientGui, true); CLOG->insert(m_ipcLogOutputter); #if SYSAPI_WIN32 diff --git a/src/test/unittests/ipc/IpcLogOutputterTests.cpp b/src/test/unittests/ipc/IpcLogOutputterTests.cpp index 444b506a..72c75b49 100644 --- a/src/test/unittests/ipc/IpcLogOutputterTests.cpp +++ b/src/test/unittests/ipc/IpcLogOutputterTests.cpp @@ -52,11 +52,11 @@ TEST(IpcLogOutputterTests, write_threadingEnabled_bufferIsSent) ON_CALL(mockServer, hasClients(_)).WillByDefault(Return(true)); - EXPECT_CALL(mockServer, hasClients(_)).Times(2); + EXPECT_CALL(mockServer, hasClients(_)).Times(5); EXPECT_CALL(mockServer, send(IpcLogLineMessageEq("mock 1\n"), _)).Times(1); EXPECT_CALL(mockServer, send(IpcLogLineMessageEq("mock 2\n"), _)).Times(1); - IpcLogOutputter outputter(mockServer, true); + IpcLogOutputter outputter(mockServer, kIpcClientUnknown, true); outputter.write(kNOTE, "mock 1"); mockServer.waitForSend(); outputter.write(kNOTE, "mock 2"); @@ -68,11 +68,10 @@ TEST(IpcLogOutputterTests, write_overBufferMaxSize_firstLineTruncated) MockIpcServer mockServer; ON_CALL(mockServer, hasClients(_)).WillByDefault(Return(true)); - - EXPECT_CALL(mockServer, hasClients(_)).Times(1); + EXPECT_CALL(mockServer, hasClients(_)).Times(4); EXPECT_CALL(mockServer, send(IpcLogLineMessageEq("mock 2\nmock 3\n"), _)).Times(1); - IpcLogOutputter outputter(mockServer, false); + IpcLogOutputter outputter(mockServer, kIpcClientUnknown, false); outputter.bufferMaxSize(2); // log more lines than the buffer can contain @@ -88,10 +87,10 @@ TEST(IpcLogOutputterTests, write_underBufferMaxSize_allLinesAreSent) ON_CALL(mockServer, hasClients(_)).WillByDefault(Return(true)); - EXPECT_CALL(mockServer, hasClients(_)).Times(1); + EXPECT_CALL(mockServer, hasClients(_)).Times(3); EXPECT_CALL(mockServer, send(IpcLogLineMessageEq("mock 1\nmock 2\n"), _)).Times(1); - IpcLogOutputter outputter(mockServer, false); + IpcLogOutputter outputter(mockServer, kIpcClientUnknown, false); outputter.bufferMaxSize(2); // log more lines than the buffer can contain @@ -143,11 +142,11 @@ TEST(IpcLogOutputterTests, write_underBufferRateLimit_allLinesAreSent) ON_CALL(mockServer, hasClients(_)).WillByDefault(Return(true)); - EXPECT_CALL(mockServer, hasClients(_)).Times(2); + EXPECT_CALL(mockServer, hasClients(_)).Times(6); EXPECT_CALL(mockServer, send(IpcLogLineMessageEq("mock 1\nmock 2\n"), _)).Times(1); EXPECT_CALL(mockServer, send(IpcLogLineMessageEq("mock 3\nmock 4\n"), _)).Times(1); - IpcLogOutputter outputter(mockServer, false); + IpcLogOutputter outputter(mockServer, kIpcClientUnknown, false); outputter.bufferRateLimit(4, 1); // 1s (should be plenty of time) // log 1 more line than the buffer can accept in time limit.