/* * synergy -- mouse and keyboard sharing utility * Copyright (C) 2012 Nick Bolton * * This package is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * found in the file COPYING that should have accompanied this file. * * This package is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #include "CIpcLogOutputter.h" #include "CIpcServer.h" #include "CIpcMessage.h" #include "Ipc.h" #include "CEvent.h" #include "CEventQueue.h" #include "TMethodEventJob.h" #include "CIpcClientProxy.h" #include "CArch.h" #include "CThread.h" #include "TMethodJob.h" #include "XArch.h" CIpcLogOutputter::CIpcLogOutputter(CIpcServer& ipcServer) : m_ipcServer(ipcServer), m_bufferMutex(ARCH->newMutex()), m_sending(false), m_running(true) { m_bufferThread = new CThread(new TMethodJob( this, &CIpcLogOutputter::bufferThread)); } CIpcLogOutputter::~CIpcLogOutputter() { m_running = false; m_bufferThread->wait(5); ARCH->closeMutex(m_bufferMutex); delete m_bufferThread; } void CIpcLogOutputter::open(const char* title) { } void CIpcLogOutputter::close() { } void CIpcLogOutputter::show(bool showIfEmpty) { } bool CIpcLogOutputter::write(ELevel level, const char* text) { return write(level, text, false); } bool CIpcLogOutputter::write(ELevel, const char* text, bool force) { // sending the buffer generates log messages, which we must throw // away (otherwise this would cause recursion). this is just a drawback // of logging this way. there is also the risk that this could throw // away log messages not generated by the ipc, but it seems like it // would be difficult to distinguish (other than looking at the stack // trace somehow). perhaps a file stream might be a better option :-/ if (m_sending && !force) { return true; } CArchMutexLock lock(m_bufferMutex); m_buffer.append(text); m_buffer.append("\n"); return true; } void CIpcLogOutputter::bufferThread(void*) { try { while (m_running) { while (m_running && m_buffer.size() == 0) { ARCH->sleep(.1); } if (!m_running) { break; } if (m_ipcServer.hasClients(kIpcClientGui)) { sendBuffer(); } } } catch (XArch& e) { LOG((CLOG_ERR "ipc log buffer thread error, %s", e.what().c_str())); } LOG((CLOG_DEBUG "ipc log buffer thread finished")); } CString* CIpcLogOutputter::emptyBuffer() { CArchMutexLock lock(m_bufferMutex); CString* copy = new CString(m_buffer); m_buffer.clear(); return copy; } void CIpcLogOutputter::sendBuffer() { CIpcMessage message; message.m_type = kIpcLogLine; message.m_data = emptyBuffer(); m_sending = true; m_ipcServer.send(message, kIpcClientGui); m_sending = false; }