From 465075d825235e9ad3ee6261cc97e60b4a83b8bb Mon Sep 17 00:00:00 2001 From: orignal Date: Tue, 10 Dec 2013 08:00:13 -0500 Subject: [PATCH] Log and queue added --- Log.cpp | 3 ++ Log.h | 45 +++++++++++++++++++++++++ Queue.h | 101 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 149 insertions(+) create mode 100644 Log.cpp create mode 100644 Log.h create mode 100644 Queue.h diff --git a/Log.cpp b/Log.cpp new file mode 100644 index 00000000..b5e49612 --- /dev/null +++ b/Log.cpp @@ -0,0 +1,3 @@ +#include "Log.h" + +i2p::util::MsgQueue g_Log; \ No newline at end of file diff --git a/Log.h b/Log.h new file mode 100644 index 00000000..e538b7be --- /dev/null +++ b/Log.h @@ -0,0 +1,45 @@ +#ifndef LOG_H__ +#define LOG_H__ + +#include +#include +#include "Queue.h" + +struct LogMsg +{ + std::stringstream s; + std::ostream& output; + + LogMsg (std::ostream& o = std::cout): output (o) {}; + + void Process () + { + output << s.str (); + } +}; + +extern i2p::util::MsgQueue g_Log; + +template +void LogPrint (std::stringstream& s, TValue arg) +{ + s << arg; +} + +template +void LogPrint (std::stringstream& s, TValue arg, TArgs... args) +{ + LogPrint (s, arg); + LogPrint (s, args...); +} + +template +void LogPrint (TArgs... args) +{ + LogMsg * msg = new LogMsg (); + LogPrint (msg->s, args...); + msg->s << std::endl; + g_Log.Put (msg); +} + +#endif diff --git a/Queue.h b/Queue.h new file mode 100644 index 00000000..31e8e0a4 --- /dev/null +++ b/Queue.h @@ -0,0 +1,101 @@ +#ifndef QUEUE_H__ +#define QUEUE_H__ + +#include +#include +#include +#include + +namespace i2p +{ +namespace util +{ + template + class Queue + { + public: + + void Put (Element * e) + { + std::unique_lock l(m_QueueMutex); + m_Queue.push (e); + m_NonEmpty.notify_one (); + } + + Element * GetNext () + { + std::unique_lock l(m_QueueMutex); + Element * el = GetNonThreadSafe (); + if (!el) + { + m_NonEmpty.wait (l); + el = GetNonThreadSafe (); + } + return el; + } + + Element * GetNextWithTimeout (int usec) + { + std::unique_lock l(m_QueueMutex); + Element * el = GetNonThreadSafe (); + if (!el) + { + m_NonEmpty.wait_for (l, std::chrono::milliseconds (usec)); + el = GetNonThreadSafe (); + } + return el; + } + + void WakeUp () { m_NonEmpty.notify_one (); }; + + Element * Get () + { + std::unique_lock l(m_QueueMutex); + return GetNonThreadSafe (); + } + + private: + + Element * GetNonThreadSafe () + { + if (!m_Queue.empty ()) + { + Element * el = m_Queue.front (); + m_Queue.pop (); + return el; + } + return nullptr; + } + + private: + + std::queue m_Queue; + std::mutex m_QueueMutex; + std::condition_variable m_NonEmpty; + }; + + template + class MsgQueue: public Queue + { + public: + + MsgQueue (): m_Thread (std::bind (&MsgQueue::Run, this)) {}; + + private: + void Run () + { + Msg * msg = nullptr; + while ((msg = Queue::GetNext ()) != nullptr) + { + msg->Process (); + delete msg; + } + } + + private: + std::thread m_Thread; + }; +} +} + +#endif