genode/repos/base/include/base/log.h

188 lines
3.8 KiB
C
Raw Normal View History

/*
* \brief LOG output functions
* \author Norman Feske
* \date 2016-05-03
*/
/*
* Copyright (C) 2016-2017 Genode Labs GmbH
*
* This file is part of the Genode OS framework, which is distributed
* under the terms of the GNU Affero General Public License version 3.
*/
#ifndef _INCLUDE__BASE__LOG_H_
#define _INCLUDE__BASE__LOG_H_
#include <base/output.h>
2020-02-19 16:26:40 +01:00
#include <base/mutex.h>
#include <trace/timestamp.h>
namespace Genode {
class Log;
class Raw;
class Trace_output;
}
/**
* Interface for writing output to the component's LOG session
*
* The LOG session is not used directly by the 'log', 'warning', and
* 'error' functions. They access the LOG indirectly via this interface
* instead, which ensures the proper synchronization of the output in the
* presence of multiple threads and to apply distinguishable colors to the
* different types of messages.
*/
class Genode::Log
{
public:
/**
* Type of message
*/
enum Type { LOG, WARNING, ERROR };
private:
2020-02-19 16:26:40 +01:00
Mutex _mutex { };
Follow practices suggested by "Effective C++" The patch adjust the code of the base, base-<kernel>, and os repository. To adapt existing components to fix violations of the best practices suggested by "Effective C++" as reported by the -Weffc++ compiler argument. The changes follow the patterns outlined below: * A class with virtual functions can no longer publicly inherit base classed without a vtable. The inherited object may either be moved to a member variable, or inherited privately. The latter would be used for classes that inherit 'List::Element' or 'Avl_node'. In order to enable the 'List' and 'Avl_tree' to access the meta data, the 'List' must become a friend. * Instead of adding a virtual destructor to abstract base classes, we inherit the new 'Interface' class, which contains a virtual destructor. This way, single-line abstract base classes can stay as compact as they are now. The 'Interface' utility resides in base/include/util/interface.h. * With the new warnings enabled, all member variables must be explicitly initialized. Basic types may be initialized with '='. All other types are initialized with braces '{ ... }' or as class initializers. If basic types and non-basic types appear in a row, it is nice to only use the brace syntax (also for basic types) and align the braces. * If a class contains pointers as members, it must now also provide a copy constructor and assignment operator. In the most cases, one would make them private, effectively disallowing the objects to be copied. Unfortunately, this warning cannot be fixed be inheriting our existing 'Noncopyable' class (the compiler fails to detect that the inheriting class cannot be copied and still gives the error). For now, we have to manually add declarations for both the copy constructor and assignment operator as private class members. Those declarations should be prepended with a comment like this: /* * Noncopyable */ Thread(Thread const &); Thread &operator = (Thread const &); In the future, we should revisit these places and try to replace the pointers with references. In the presence of at least one reference member, the compiler would no longer implicitly generate a copy constructor. So we could remove the manual declaration. Issue #465
2017-12-21 15:42:15 +01:00
Output &_output;
Follow practices suggested by "Effective C++" The patch adjust the code of the base, base-<kernel>, and os repository. To adapt existing components to fix violations of the best practices suggested by "Effective C++" as reported by the -Weffc++ compiler argument. The changes follow the patterns outlined below: * A class with virtual functions can no longer publicly inherit base classed without a vtable. The inherited object may either be moved to a member variable, or inherited privately. The latter would be used for classes that inherit 'List::Element' or 'Avl_node'. In order to enable the 'List' and 'Avl_tree' to access the meta data, the 'List' must become a friend. * Instead of adding a virtual destructor to abstract base classes, we inherit the new 'Interface' class, which contains a virtual destructor. This way, single-line abstract base classes can stay as compact as they are now. The 'Interface' utility resides in base/include/util/interface.h. * With the new warnings enabled, all member variables must be explicitly initialized. Basic types may be initialized with '='. All other types are initialized with braces '{ ... }' or as class initializers. If basic types and non-basic types appear in a row, it is nice to only use the brace syntax (also for basic types) and align the braces. * If a class contains pointers as members, it must now also provide a copy constructor and assignment operator. In the most cases, one would make them private, effectively disallowing the objects to be copied. Unfortunately, this warning cannot be fixed be inheriting our existing 'Noncopyable' class (the compiler fails to detect that the inheriting class cannot be copied and still gives the error). For now, we have to manually add declarations for both the copy constructor and assignment operator as private class members. Those declarations should be prepended with a comment like this: /* * Noncopyable */ Thread(Thread const &); Thread &operator = (Thread const &); In the future, we should revisit these places and try to replace the pointers with references. In the presence of at least one reference member, the compiler would no longer implicitly generate a copy constructor. So we could remove the manual declaration. Issue #465
2017-12-21 15:42:15 +01:00
void _acquire(Type);
void _release();
public:
Log(Output &output) : _output(output) { }
template <typename... ARGS>
void output(Type type, ARGS &&... args)
{
/*
* This function is being inlined. Hence, we try to keep it as
2020-02-19 16:26:40 +01:00
* small as possible. For this reason, the mutex operations are
* performed by the '_acquire' and '_release' functions instead of
2020-02-19 16:26:40 +01:00
* using a mutex guard.
*/
_acquire(type);
Output::out_args(_output, args...);
_release();
}
/**
* Return component-global singleton instance of the 'Log'
*/
static Log &log();
};
/**
* Raw-output back end
*
* \noapi
*/
class Genode::Raw
{
private:
static void _acquire();
static void _release();
static Output &_output();
public:
template <typename... ARGS>
static void output(ARGS &&... args)
{
_acquire();
Output::out_args(_output(), args...);
_release();
}
};
class Genode::Trace_output
{
private:
2020-02-19 16:26:40 +01:00
Mutex _mutex { };
Output &_output;
void _acquire();
void _release();
public:
Trace_output(Output &output) : _output(output) { }
template <typename... ARGS>
void output(ARGS &&... args)
{
_acquire();
Output::out_args(_output, args...);
_release();
}
/**
* Return component-global singleton instance of the 'Trace_output'
*/
static Trace_output &trace_output();
};
namespace Genode {
/**
* Write 'args' as a regular message to the log
*/
template <typename... ARGS>
void log(ARGS &&... args) { Log::log().output(Log::LOG, args...); }
/**
* Write 'args' as a warning message to the log
*
* The message is automatically prefixed with "Warning: ". Please refer to
* the description of the 'error' function regarding the convention of
* formatting error/warning messages.
*/
template <typename... ARGS>
void warning(ARGS &&... args) { Log::log().output(Log::WARNING, args...); }
/**
* Write 'args' as an error message to the log
*
* The message is automatically prefixed with "Error: ". Hence, the
* message argument does not need to additionally state that it is an error
* message. By convention, the actual message should be brief, starting
* with a lower-case character.
*/
template <typename... ARGS>
void error(ARGS &&... args) { Log::log().output(Log::ERROR, args...); }
/**
* Write 'args' directly via the kernel (i.e., kernel debugger)
*
* This function is intended for temporarily debugging purposes only.
*/
template <typename... ARGS>
void raw(ARGS &&... args) { Raw::output(args...); }
/**
* Write 'args' to the trace buffer if tracing is enabled
*
* The message is prefixed with a timestamp value
*/
template <typename... ARGS>
void trace(ARGS && ... args) {
Trace_output::trace_output().output(Trace::timestamp(), ": ", args...); }
}
#endif /* _INCLUDE__BASE__LOG_H_ */