Loading...
Searching...
No Matches
debugstream.hh
Go to the documentation of this file.
// -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*-
// vi: set et ts=4 sw=2 sts=2:
// SPDX-FileCopyrightInfo: Copyright © DUNE Project contributors, see file LICENSE.md in module root
// SPDX-License-Identifier: LicenseRef-GPL-2.0-only-with-DUNE-exception
#ifndef DUNE_DEBUGSTREAM_HH
#define DUNE_DEBUGSTREAM_HH
#include <iostream>
#include <stack>
#include <dune/common/exceptions.hh>
namespace Dune {
typedef unsigned int DebugLevel;
template <DebugLevel current, DebugLevel threshold>
struct greater_or_equal {
constexpr static bool value = (current >= threshold);
};
template <DebugLevel current, DebugLevel mask>
struct common_bits {
constexpr static bool value = ((current & mask) != 0);
};
class DebugStreamError : public IOError {};
class StreamWrap {
public:
StreamWrap(std::ostream& _out) : out(_out) { }
std::ostream& out;
StreamWrap *next;
};
class DebugStreamState {
// !!! should be protected somehow but that won't be easy
public:
StreamWrap* current;
bool _active;
bool _tied;
unsigned int _tied_streams;
};
template <DebugLevel thislevel = 1,
DebugLevel dlevel = 1,
DebugLevel alevel = 1,
template<DebugLevel, DebugLevel> class activator = greater_or_equal>
class DebugStream : public DebugStreamState {
public:
DebugStream(std::ostream& out = std::cerr) {
// start a new list of streams
current = new StreamWrap(out);
current->next = 0;
// check if we are above the default activation level
_active = activator<thislevel,alevel>::value;
// we're not tied to another DebugStream
_tied = false;
// no child streams yet
_tied_streams = 0;
}
DebugStream (DebugStreamState& master,
std::ostream& fallback = std::cerr)
{
// start a new list of streams
current = new StreamWrap(fallback);
current->next = 0;
// check if we are above the default activation level
_active = activator<thislevel,alevel>::value;
_tied_streams = 0;
// tie to the provided stream
_tied = true;
tiedstate = &master;
tiedstate->_tied_streams++;
}
~DebugStream()
{
// untie
if (_tied)
tiedstate->_tied_streams--;
else {
// check if somebody still ties to us...
if (_tied_streams != 0)
{
std::cerr << "DebugStream destructor is called while other streams are still tied to it. Terminating!" << std::endl;
std::terminate();
}
}
// remove ostream-stack
while (current != 0) {
StreamWrap *s = current;
current = current->next;
delete s;
}
}
template <class T>
DebugStream& operator<<(const T data) {
// remove the following code if stream wasn't compiled active
if (activator<thislevel, dlevel>::value) {
if (! _tied) {
if (_active)
current->out << data;
} else {
if (_active && tiedstate->_active)
tiedstate->current->out << data;
}
}
return *this;
}
DebugStream& operator<<(const int data) {
// remove the following code if stream wasn't compiled active
if (activator<thislevel, dlevel>::value) {
if (! _tied) {
if (_active)
current->out << data;
} else {
if (_active && tiedstate->_active)
tiedstate->current->out << data;
}
}
return *this;
}
DebugStream& operator<<(std::ostream& (*f)(std::ostream&)) {
if (activator<thislevel, dlevel>::value) {
if (! _tied) {
if (_active)
f(current->out);
} else {
if (_active && tiedstate->_active)
f(tiedstate->current->out);
}
}
return *this;
}
DebugStream& flush() {
if (activator<thislevel, dlevel>::value) {
if (! _tied) {
if (_active)
current->out.flush();
} else {
if (_active && tiedstate->_active)
tiedstate->current->out.flush();
}
}
return *this;
}
void push(bool b) {
// are we at all active?
if (activator<thislevel,alevel>::value) {
_actstack.push(_active);
_active = b;
} else {
// stay off
_actstack.push(false);
}
}
void pop() {
if (_actstack.empty())
DUNE_THROW(DebugStreamError, "No previous activation setting!");
_active = _actstack.top();
_actstack.pop();
}
bool active() const {
return activator<thislevel, dlevel>::value && _active;
}
void attach(std::ostream& stream) {
if (_tied)
DUNE_THROW(DebugStreamError, "Cannot attach to a tied stream!");
StreamWrap* newcurr = new StreamWrap(stream);
newcurr->next = current;
current = newcurr;
}
void detach() {
if (current->next == 0)
DUNE_THROW(DebugStreamError, "Cannot detach initial stream!");
if (_tied)
DUNE_THROW(DebugStreamError, "Cannot detach a tied stream!");
StreamWrap* old = current;
current = current->next;
delete old;
}
void tie(DebugStreamState& to) {
if (to._tied)
DUNE_THROW(DebugStreamError, "Cannot tie to an already tied stream!");
if (_tied)
DUNE_THROW(DebugStreamError, "Stream already tied: untie first!");
_tied = true;
tiedstate = &to;
// tell master class
tiedstate->_tied_streams++;
}
void untie() {
if(! _tied)
DUNE_THROW(DebugStreamError, "Cannot untie, stream is not tied!");
tiedstate->_tied_streams--;
_tied = false;
tiedstate = 0;
}
private:
DebugStreamState* tiedstate;
std::stack<bool> _actstack;
};
}
#endif
exceptions.hh
A few common exception classes.
Dune::StreamWrap::StreamWrap
StreamWrap(std::ostream &_out)
Definition debugstream.hh:152
Dune::DebugStream::DebugStream
DebugStream(std::ostream &out=std::cerr)
Create a DebugStream and set initial output stream.
Definition debugstream.hh:199
Dune::DebugStream::untie
void untie()
Untie stream.
Definition debugstream.hh:413
Dune::DebugStream::flush
DebugStream & flush()
pass on flush to underlying output stream
Definition debugstream.hh:320
Dune::DebugStream::attach
void attach(std::ostream &stream)
set output to a different stream.
Definition debugstream.hh:371
Dune::DebugStream::detach
void detach()
detach current output stream and restore to previous stream
Definition debugstream.hh:383
Dune::common_bits::value
static constexpr bool value
Definition debugstream.hh:143
Dune::StreamWrap::out
std::ostream & out
Definition debugstream.hh:153
Dune::DebugStream::pop
void pop()
restore previously set activation flag
Definition debugstream.hh:349
Dune::DebugStream::active
bool active() const
reports if this stream will produce output
Definition debugstream.hh:363
Dune::DebugStreamState::_active
bool _active
flag to switch output during runtime
Definition debugstream.hh:165
Dune::DebugStreamState::_tied_streams
unsigned int _tied_streams
how many streams are tied to this state
Definition debugstream.hh:171
Dune::DebugStream::tie
void tie(DebugStreamState &to)
Tie a stream to this one.
Definition debugstream.hh:397
Dune::DebugStream::push
void push(bool b)
set activation flag and store old value
Definition debugstream.hh:335
Dune::DebugLevel
unsigned int DebugLevel
Type for debug levels.
Definition debugstream.hh:118
Dune::DebugStreamState::_tied
bool _tied
are we tied to another DebugStream?
Definition debugstream.hh:168
Dune::DebugStreamState::current
StreamWrap * current
current output stream and link to possibly pushed old output streams
Definition debugstream.hh:162
Dune::DebugStream::operator<<
DebugStream & operator<<(const T data)
Generic types are passed on to current output stream.
Definition debugstream.hh:267
Dune::greater_or_equal::value
static constexpr bool value
Definition debugstream.hh:131
Dune::DebugStream::~DebugStream
~DebugStream()
Destroy stream.
Definition debugstream.hh:243
Dune::DebugStream::DebugStream
DebugStream(DebugStreamState &master, std::ostream &fallback=std::cerr)
Create a DebugStream and directly tie to another DebugStream.
Definition debugstream.hh:219
Dune::DebugStream::operator<<
DebugStream & operator<<(const int data)
explicit specialization so that enums can be printed
Definition debugstream.hh:289
Dune::DebugStream::operator<<
DebugStream & operator<<(std::ostream &(*f)(std::ostream &))
pass on manipulators to underlying output stream
Definition debugstream.hh:305
Dune::StreamWrap::next
StreamWrap * next
Definition debugstream.hh:154
DUNE_THROW
#define DUNE_THROW(E,...)
Definition exceptions.hh:314
Dune
Dune namespace
Definition alignedallocator.hh:13
Dune::greater_or_equal
Greater or equal template test.
Definition debugstream.hh:130
Dune::common_bits
activate if current and mask have common bits switched on.
Definition debugstream.hh:142
Dune::DebugStreamError
standard exception for the debugstream
Definition debugstream.hh:148
Dune::StreamWrap
Definition debugstream.hh:150
Dune::DebugStreamState
Intermediate class to implement tie-operation of DebugStream.
Definition debugstream.hh:158
Dune::IOError
Default exception class for I/O errors.
Definition exceptions.hh:325