VALog.h 5.25 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
/*
 *  --------------------------------------------------------------------------------------------
 *
 *    VVV        VVV A           Virtual Acoustics (VA) | http://www.virtualacoustics.org
 *     VVV      VVV AAA          Licensed under the Apache License, Version 2.0
 *      VVV    VVV   AAA
 *       VVV  VVV     AAA        Copyright 2015-2017
 *        VVVVVV       AAA       Institute of Technical Acoustics (ITA)
 *         VVVV         AAA      RWTH Aachen University
 *
 *  --------------------------------------------------------------------------------------------
 */

#ifndef IW_VACORE_LOG
#define IW_VACORE_LOG
Jonas Stienen's avatar
Jonas Stienen committed
16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31

#include <VACoreDefinitions.h>

#include <VACore.h>
#include <VAException.h>

#include <ITAClock.h>
#include <ITAAtomicPrimitives.h>

#include <tbb/concurrent_queue.h>

#include <VistaInterProcComm/Concurrency/VistaMutex.h>
#include <VistaInterProcComm/Concurrency/VistaThreadEvent.h>
#include <VistaInterProcComm/Concurrency/VistaThreadLoop.h>

#include <iostream>
32
#include <iomanip>
Jonas Stienen's avatar
Jonas Stienen committed
33 34
#include <list>
#include <stdarg.h>
35
#include <stdio.h>
Jonas Stienen's avatar
Jonas Stienen committed
36 37 38 39

extern VACORE_API std::ostream* VA_STDOUT;
extern VACORE_API std::ostream* VA_STDERR;

Jonas Stienen's avatar
Jonas Stienen committed
40 41
void VACORE_API VALog_setOutputStream( std::ostream* os );
void VACORE_API VALog_setErrorStream( std::ostream* os );
Jonas Stienen's avatar
Jonas Stienen committed
42 43 44 45 46
int VACORE_API VALog_GetLogLevel();
void VACORE_API VALog_SetLogLevel( int );

VistaMutex& VALog_getOutputStreamMutex();

47 48 49 50 51 52
#define VA_PRINT( expr )			{ if (VA_STDOUT && (VALog_GetLogLevel() >= IVACore::VA_LOG_LEVEL_QUIET ) )		{ VistaMutexLock oLock(VALog_getOutputStreamMutex() ); (*VA_STDOUT) << "[ VAPrint   ] " << expr << std::endl; } }
#define VA_ERROR( module, expr )	{ if (VA_STDOUT && (VALog_GetLogLevel() >= IVACore::VA_LOG_LEVEL_QUIET ) )		{ VistaMutexLock oLock(VALog_getOutputStreamMutex() ); (*VA_STDERR) << "[ VAError   ][ " << std::right << std::setw( 20 ) << module << " ] " << expr << std::endl; } }
#define VA_WARN( module, expr )		{ if (VA_STDOUT && (VALog_GetLogLevel() >= IVACore::VA_LOG_LEVEL_ERROR ) )		{ VistaMutexLock oLock(VALog_getOutputStreamMutex() ); (*VA_STDOUT) << "[ VAWarning ][ " << std::right << std::setw( 20 ) << module << " ] " << expr << std::endl; } }
#define VA_INFO( module, expr )		{ if (VA_STDOUT && (VALog_GetLogLevel() >= IVACore::VA_LOG_LEVEL_INFO ) )		{ VistaMutexLock oLock(VALog_getOutputStreamMutex() ); (*VA_STDOUT) << "[ VAInfo    ][ " << std::right << std::setw( 20 ) << module << " ] " << expr << std::endl; } }
#define VA_VERBOSE( module,expr )	{ if (VA_STDOUT && (VALog_GetLogLevel() >= IVACore::VA_LOG_LEVEL_VERBOSE ) )	{ VistaMutexLock oLock(VALog_getOutputStreamMutex() ); (*VA_STDOUT) << "[ VAVerbose ][ " << std::right << std::setw( 20 ) << module << " ] " << expr << std::endl; } }
#define VA_TRACE( module, expr )	{ if (VA_STDOUT && (VALog_GetLogLevel() >= IVACore::VA_LOG_LEVEL_TRACE ) )		{ VistaMutexLock oLock(VALog_getOutputStreamMutex() ); (*VA_STDOUT) << "[ VATrace   ][ " << std::right << std::setw( 20 ) << module << " ] " << expr << std::endl; } }
Jonas Stienen's avatar
Jonas Stienen committed
53 54 55 56 57 58 59 60

class CVALogItem
{
public:
	double dTimestamp;
	std::string sLogger;
	std::string sMsg;

Jonas Stienen's avatar
Jonas Stienen committed
61 62 63 64 65 66 67 68 69 70 71
	inline CVALogItem()
		: dTimestamp( 0 )
	{
	};

	inline CVALogItem( double dTheTimestamp, const std::string sTheLogger, const std::string sTheMsg )
		: dTimestamp( dTheTimestamp )
		, sLogger( sTheLogger )
		, sMsg( sTheMsg )
	{
	};
Jonas Stienen's avatar
Jonas Stienen committed
72 73

	//! Grer-Operator zur Verwendung der sort() Funktion
Jonas Stienen's avatar
Jonas Stienen committed
74
	bool operator> ( CVALogItem const& rhs );
Jonas Stienen's avatar
Jonas Stienen committed
75 76

	//! Kleiner-Operation
Jonas Stienen's avatar
Jonas Stienen committed
77
	bool operator< ( CVALogItem const& rhs );
Jonas Stienen's avatar
Jonas Stienen committed
78 79 80 81 82 83

};

class CVARealtimeLogStream;

//! Realtime Logger entkoppelt die Ausgabe von Logger-Streams auf einem niederpriorisierten Thread
Jonas Stienen's avatar
Jonas Stienen committed
84 85
class CVARealtimeLogger : public VistaThreadLoop
{
Jonas Stienen's avatar
Jonas Stienen committed
86 87 88 89 90 91 92
public:
	CVARealtimeLogger();
	~CVARealtimeLogger();

	static CVARealtimeLogger* GetInstance();

	//! Streams registrieren
Jonas Stienen's avatar
Jonas Stienen committed
93
	void Register( CVARealtimeLogStream* pStream );
Jonas Stienen's avatar
Jonas Stienen committed
94 95

	//! Streams deregistrieren
Jonas Stienen's avatar
Jonas Stienen committed
96
	void Unregister( CVARealtimeLogStream* pStream );
Jonas Stienen's avatar
Jonas Stienen committed
97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122

	//! Thread anschubsen (nach Aktion)
	void Trigger();

	//! Ausgabe
	bool LoopBody();

	void PreLoop() {};
	void PostLoop() {};

private:
	VistaThreadEvent m_evTrigger;
	ITAAtomicInt m_iTriggerCnt;
	ITAAtomicBool m_bStop;
	std::list<CVARealtimeLogStream*> m_lpStreams;
	VistaMutex m_mxRegistration;
};

//! Implementierung des Echtzeit-Logger-Streams
/**
  * Nutzt den RealtimeLogger, um Stream-Informationen mittels
  * niederpriorisiertem Thread auf die Konsole oder Visual Studio Ausgabe
  * auszugeben.
  */
class CVARealtimeLogStream {
public:
Jonas Stienen's avatar
Jonas Stienen committed
123 124
	CVARealtimeLogStream( ITAClock* pClock = ITAClock::getDefaultClock() )
		: m_pClock( pClock ) {
Jonas Stienen's avatar
Jonas Stienen committed
125
		// Bei Ausgabe-Thread registrieren (Singleton)
Jonas Stienen's avatar
Jonas Stienen committed
126
		CVARealtimeLogger::GetInstance()->Register( this );
Jonas Stienen's avatar
Jonas Stienen committed
127 128 129 130
	}

	virtual ~CVARealtimeLogStream() {
		// Bei Thread deregistieren
Jonas Stienen's avatar
Jonas Stienen committed
131
		CVARealtimeLogger::GetInstance()->Unregister( this );
Jonas Stienen's avatar
Jonas Stienen committed
132 133 134 135 136 137
	}

	std::string GetName() const {
		return m_sName;
	}

Jonas Stienen's avatar
Jonas Stienen committed
138
	void SetName( const std::string& sName ) {
Jonas Stienen's avatar
Jonas Stienen committed
139 140 141 142
		m_sName = sName;
	}

	// Ausgabe
Jonas Stienen's avatar
Jonas Stienen committed
143 144
	void Printf( const char * format, ... ) {
		char buf[ 16384 ];
Jonas Stienen's avatar
Jonas Stienen committed
145
		va_list args;
Jonas Stienen's avatar
Jonas Stienen committed
146
		va_start( args, format );
147
		vsprintf( buf, format, args );
Jonas Stienen's avatar
Jonas Stienen committed
148
		va_end( args );
Jonas Stienen's avatar
Jonas Stienen committed
149

Jonas Stienen's avatar
Jonas Stienen committed
150
		m_qLog.push( CVALogItem( m_pClock->getTime(), m_sName, buf ) );
Jonas Stienen's avatar
Jonas Stienen committed
151 152 153 154 155 156 157 158 159 160
		// TODO: Thread zur Ausgabe anwerfen ggf.
	}

private:
	ITAClock* m_pClock;
	std::string m_sName;
	tbb::strict_ppl::concurrent_queue<CVALogItem> m_qLog;

	friend class CVARealtimeLogger;
};
161
#endif // IW_VACORE_LOG