Skip to content
Snippets Groups Projects
Commit 73a016f0 authored by Joseph Mirabel's avatar Joseph Mirabel Committed by Olivier Stasse
Browse files

Add macros to use real time logs.

parent 3b391ca7
No related branches found
No related tags found
No related merge requests found
......@@ -23,6 +23,8 @@
# include <boost/shared_ptr.hpp>
# include <dynamic-graph/config.hh>
# include <dynamic-graph/debug.h>
namespace dynamicgraph
{
......@@ -50,7 +52,8 @@ namespace dynamicgraph
{
public:
RTLoggerStream (RealTimeLogger* logger, std::ostream& os) : logger_(logger), os_ (os) {}
template <typename T> RTLoggerStream& operator<< (T t) { os_ << t; return *this; }
template <typename T> inline RTLoggerStream& operator<< (T t) { os_ << t; return *this; }
inline RTLoggerStream& operator<< (std::ostream& (*pf)(std::ostream&)) { os_ << pf; return *this; }
~RTLoggerStream();
private:
......@@ -65,6 +68,10 @@ namespace dynamicgraph
class DYNAMIC_GRAPH_DLLAPI RealTimeLogger
{
public:
static RealTimeLogger& instance();
static void destroy();
/// \todo add an argument to preallocate the internal string to a given size.
RealTimeLogger (const std::size_t& bufferSize);
......@@ -72,9 +79,6 @@ namespace dynamicgraph
inline void addOutputStream (const LoggerStreamPtr_t& os) { outputs_.push_back(os); }
/// The function to be called by the thread who exports the outputs
//void spin ();
/// Write next message to output.
/// It does nothing if the buffer is empty.
/// \return true if it wrote something
......@@ -104,7 +108,7 @@ namespace dynamicgraph
return backIdx_ + buffer_.size() - frontIdx_;
}
inline std::size_t getBufferSize () { return buffer_.capacity(); }
inline std::size_t getBufferSize () { return buffer_.size(); }
~RealTimeLogger ();
......@@ -121,7 +125,21 @@ namespace dynamicgraph
/// Index of the slot where to write next value (does not contain valid data).
std::size_t backIdx_;
std::ostream oss_;
struct thread;
static RealTimeLogger* instance_;
static thread* thread_;
};
} // end of namespace dynamicgraph
#ifdef ENABLE_RT_LOG
# define dgADD_OSTREAM_TO_RTLOG(ostr) ::dynamicgraph::RealTimeLogger::instance() \
.addOutputStream(::dynamicgraph::LoggerStreamPtr_t(new ::dynamicgraph::LoggerIOStream(ostr)))
# define dgRTLOG() ::dynamicgraph::RealTimeLogger::instance().front()
#else // ENABLE_RT_LOG
# define dgADD_OSTREAM_TO_RTLOG(ostr) struct __end_with_semicolon
# define dgRTLOG() if (1) ; else __null_stream()
#endif
#endif //! DYNAMIC_GRAPH_LOGGER_REAL_TIME_H
......@@ -19,6 +19,9 @@
#include <dynamic-graph/real-time-logger.h>
#include <boost/thread/thread.hpp>
#include <boost/date_time/posix_time/posix_time.hpp>
namespace dynamicgraph
{
RealTimeLogger::RealTimeLogger (const std::size_t& bufferSize)
......@@ -68,4 +71,47 @@ namespace dynamicgraph
os_ << std::ends;
if (logger_ != NULL) logger_->frontReady();
}
struct RealTimeLogger::thread
{
bool requestShutdown_;
boost::thread t_;
thread (RealTimeLogger* logger)
: requestShutdown_ (false)
, t_ (&thread::spin, this, logger)
{}
void spin (RealTimeLogger* logger)
{
while (!requestShutdown_ || !logger->empty())
{
// If the logger did not write anything, it means the buffer is empty.
// Do a pause
if (!logger->spinOnce())
boost::this_thread::sleep(boost::posix_time::milliseconds(100));
}
}
};
RealTimeLogger* RealTimeLogger::instance_ = NULL;
RealTimeLogger::thread* RealTimeLogger::thread_ = NULL;
RealTimeLogger& RealTimeLogger::instance()
{
if (instance_ == NULL) {
instance_ = new RealTimeLogger (1000);
thread_ = new thread (instance_);
}
return *instance_;
}
void RealTimeLogger::destroy ()
{
if (instance_ == NULL) return;
thread_->requestShutdown_ = true;
thread_->t_.join();
delete instance_;
delete thread_;
}
}
......@@ -18,6 +18,8 @@
*/
#include <iostream>
#define ENABLE_RT_LOG
#include <dynamic-graph/real-time-logger.h>
#define BOOST_TEST_MODULE real_time_logger
......@@ -25,7 +27,6 @@
#include <boost/test/unit_test.hpp>
#include <boost/test/output_test_stream.hpp>
#include <boost/thread.hpp>
#include <boost/thread/thread.hpp>
#include <boost/date_time/posix_time/posix_time.hpp>
......@@ -51,33 +52,20 @@ BOOST_AUTO_TEST_CASE (monothread)
rtl.spinOnce();
}
bool requestShutdown = false;
void spin (RealTimeLogger* logger)
{
while (!requestShutdown || !logger->empty())
{
// If the logger did not write anything, it means the buffer is empty.
// Do a pause
if (!logger->spinOnce())
boost::this_thread::sleep(boost::posix_time::milliseconds(100));
}
}
BOOST_AUTO_TEST_CASE (multithread)
{
RealTimeLogger rtl (10);
rtl.addOutputStream (LoggerStreamPtr_t (new LoggerIOStream(std::cout)));
boost::thread loggerThread (spin, &rtl);
RealTimeLogger& rtl = RealTimeLogger::instance();
dgADD_OSTREAM_TO_RTLOG (std::cout);
for (int i = 0; i < 10; ++i) {
boost::this_thread::sleep(boost::posix_time::milliseconds(20));
for (std::size_t i = 0; i < rtl.getBufferSize()-1; ++i)
rtl.front() << "Call number " << i << '\n';
for (std::size_t i = 0; i < 12; ++i) {
boost::this_thread::sleep(boost::posix_time::milliseconds(20));
rtl.front() << "Call number " << i << std::endl;
BOOST_CHECK (!rtl.full());
}
rtl.front() << "This call should appear in the output" << '\n';
dgRTLOG() << "This call should appear in the output" << '\n';
requestShutdown = true;
loggerThread.join();
RealTimeLogger::destroy();
}
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment