1 /*
2  * barrier -- mouse and keyboard sharing utility
3  * Copyright (C) 2012-2016 Symless Ltd.
4  * Copyright (C) 2012 Nick Bolton
5  *
6  * This package is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU General Public License
8  * found in the file LICENSE that should have accompanied this file.
9  *
10  * This package is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13  * GNU General Public License for more details.
14  *
15  * You should have received a copy of the GNU General Public License
16  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
17  */
18 
19 #pragma once
20 
21 #include "arch/Arch.h"
22 #include "arch/IArchMultithread.h"
23 #include "base/ILogOutputter.h"
24 #include "base/String.h"
25 #include "ipc/Ipc.h"
26 
27 #include <deque>
28 #include <mutex>
29 
30 class IpcServer;
31 class Event;
32 class IpcClientProxy;
33 
34 //! Write log to GUI over IPC
35 /*!
36 This outputter writes output to the GUI via IPC.
37 */
38 class IpcLogOutputter : public ILogOutputter {
39 public:
40     /*!
41     If \p useThread is \c true, the buffer will be sent using a thread.
42     If \p useThread is \c false, then the buffer needs to be sent manually
43     using the \c sendBuffer() function.
44     */
45     IpcLogOutputter(IpcServer& ipcServer, EIpcClientType clientType, bool useThread);
46     virtual ~IpcLogOutputter();
47 
48     // ILogOutputter overrides
49     virtual void        open(const char* title);
50     virtual void        close();
51     virtual void        show(bool showIfEmpty);
52     virtual bool        write(ELevel level, const char* message);
53 
54     //! @name manipulators
55     //@{
56 
57     //! Notify that the buffer should be sent.
58     void                notifyBuffer();
59 
60     //! Set the buffer size
61     /*!
62     Set the maximum size of the buffer to protect memory
63     from runaway logging.
64     */
65     void                bufferMaxSize(UInt16 bufferMaxSize);
66 
67     //! Set the rate limit
68     /*!
69     Set the maximum number of \p writeRate for every \p timeRate in seconds.
70     */
71     void                bufferRateLimit(UInt16 writeLimit, double timeLimit);
72 
73     //! Send the buffer
74     /*!
75     Sends a chunk of the buffer to the IPC server, normally called
76     when threaded mode is on.
77     */
78     void                sendBuffer();
79 
80     //@}
81 
82     //! @name accessors
83     //@{
84 
85     //! Get the buffer size
86     /*!
87     Returns the maximum size of the buffer.
88     */
89     UInt16                bufferMaxSize() const;
90 
91     //@}
92 
93 private:
94     void                init();
95     void                bufferThread(void*);
96     std::string getChunk(size_t count);
97     void appendBuffer(const std::string& text);
98     bool                isRunning();
99 
100 private:
101     typedef std::deque<std::string> Buffer;
102 
103     IpcServer&            m_ipcServer;
104     Buffer                m_buffer;
105     std::mutex m_bufferMutex;
106     bool                m_sending;
107     Thread*                m_bufferThread;
108     bool                m_running;
109     ArchCond            m_notifyCond;
110     ArchMutex            m_notifyMutex;
111     bool                m_bufferWaiting;
112     IArchMultithread::ThreadID
113                         m_bufferThreadId;
114     UInt16                m_bufferMaxSize;
115     UInt16                m_bufferRateWriteLimit;
116     double                m_bufferRateTimeLimit;
117     UInt16                m_bufferWriteCount;
118     double                m_bufferRateStart;
119     EIpcClientType        m_clientType;
120     std::mutex m_runningMutex;
121 };
122