mirror of
https://github.com/overte-org/overte.git
synced 2025-06-23 17:41:03 +02:00
106 lines
3.1 KiB
C++
106 lines
3.1 KiB
C++
//
|
|
// LogStream.h
|
|
// interface
|
|
//
|
|
// Created by Tobias Schwinger on 4/17/13.
|
|
// Copyright (c) 2013 High Fidelity, Inc. All rights reserved.
|
|
//
|
|
|
|
#ifndef __interface__LogStream__
|
|
#define __interface__LogStream__
|
|
|
|
#include <sstream>
|
|
|
|
#include "Log.h"
|
|
|
|
//
|
|
// Makes the logging facility accessible as a C++ stream.
|
|
//
|
|
// Example:
|
|
//
|
|
// // somewhere central - ideally one per thread (else pass 'true' as
|
|
// // second constructor argument and compromise some efficiency)
|
|
// LogStream lOut(printLog);
|
|
//
|
|
// // elsewhere:
|
|
// lOut << "Hello there!" << std::endl;
|
|
//
|
|
class LogStream {
|
|
std::ostringstream _objOutStream;
|
|
Log& _refLog;
|
|
bool _flgThreadSafe;
|
|
public:
|
|
inline LogStream(Log& log, bool threadSafe = false);
|
|
|
|
class StreamRef; friend class StreamRef;
|
|
|
|
template< typename T > friend inline LogStream::StreamRef const operator<<(LogStream&, T const&);
|
|
|
|
private:
|
|
// don't
|
|
LogStream(LogStream const&); // = delete;
|
|
LogStream& operator=(LogStream const&); // = delete;
|
|
|
|
inline void ostreamBegin();
|
|
inline void ostreamEnd();
|
|
};
|
|
|
|
inline LogStream::LogStream(Log& log, bool threadSafe) :
|
|
_objOutStream(std::ios_base::out), _refLog(log), _flgThreadSafe(threadSafe) { }
|
|
|
|
inline void LogStream::ostreamBegin() {
|
|
|
|
if (_flgThreadSafe) {
|
|
// the user wants to share this LogStream among threads,
|
|
// so lock the global log here, already
|
|
pthread_mutex_lock(& _refLog._mtx);
|
|
}
|
|
_objOutStream.str("");
|
|
}
|
|
|
|
inline void LogStream::ostreamEnd() {
|
|
|
|
if (! _flgThreadSafe) {
|
|
// haven't locked, so far (we have memory for each thread)
|
|
pthread_mutex_lock(& _refLog._mtx);
|
|
}
|
|
_refLog.addMessage(_objOutStream.str().c_str());
|
|
pthread_mutex_unlock(& _refLog._mtx);
|
|
}
|
|
|
|
|
|
//
|
|
// The Log::StreamRef class makes operator<< work. It...
|
|
//
|
|
class LogStream::StreamRef {
|
|
mutable LogStream* _ptrLogStream;
|
|
typedef std::ostream& (*manipulator)(std::ostream&);
|
|
|
|
friend class LogStream;
|
|
|
|
template< typename T > friend inline LogStream::StreamRef const operator<<(LogStream&, T const&);
|
|
StreamRef(LogStream* log) : _ptrLogStream(log) { }
|
|
public:
|
|
// ...forwards << operator calls to stringstream...
|
|
template< typename T > StreamRef const operator<<(T const& x) const { _ptrLogStream->_objOutStream << x; return *this; }
|
|
// ...has to dance around to make manipulators (such as std::hex, std::endl) work...
|
|
StreamRef const operator<<(manipulator x) const { _ptrLogStream->_objOutStream << x; return *this; }
|
|
// ...informs the logger that a stream has ended when it has the responsibility...
|
|
~StreamRef() { if (_ptrLogStream != 0l) { _ptrLogStream->ostreamEnd(); } }
|
|
// ...which is passed on upon copy.
|
|
StreamRef(StreamRef const& other) : _ptrLogStream(other._ptrLogStream) { other._ptrLogStream = 0l; }
|
|
|
|
private:
|
|
// don't
|
|
StreamRef& operator=(StreamRef const&); // = delete;
|
|
};
|
|
|
|
template< typename T > inline LogStream::StreamRef const operator<<(LogStream& s, T const& x) {
|
|
|
|
s.ostreamBegin();
|
|
s._objOutStream << x;
|
|
return LogStream::StreamRef(& s); // calls streamEnd at the end of the stream expression
|
|
}
|
|
|
|
|
|
#endif
|