/usr/include/dune/common/debugstream.hh is in libdune-common-dev 2.5.1-1.
This file is owned by root:root, with mode 0o644.
The actual contents of the file can be viewed below.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 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 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 | // -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*-
// vi: set et ts=4 sw=2 sts=2:
#ifndef DUNE_DEBUGSTREAM_HH
#define DUNE_DEBUGSTREAM_HH
/** \file
* \brief Defines several output streams for messages of different importance
*/
#include <iostream>
#include <stack>
#include <dune/common/exceptions.hh>
namespace Dune {
/*! \defgroup DebugOut Debug output
\ingroup Common
The debug output is implemented by instances of DebugStream which
provides the following features:
- output-syntax in the standard ostream-notation
- output can be totally deactivated depending on template parameters
- streams with active output can be deactivated during runtime
- redirecting to std::ostream or other DebugStream s during runtime
- stack oriented state
The Dune-components should use the streams explained in \ref StdStreams
for output so that applications may redirect the output globally.
Changes in runtime are provided by three sets of methods:
- push()/pop() sets new activation flag or restore old setting
- attach()/detach() redirects output to a different std::ostream or restore old stream
- tie()/untie() redirects output through another DebugStream. If the state of the master stream changes (activation or output-stream) it is changed in the tied stream as well
The first methods implement a full stack whereas tie() is a bit
different: though a tied stream may be (de)activated via
push()/pop() you cannot attach() or detach() an output. You'll need
to change the master stream instead.
\section DebugAppl Applications
Applications using the Dune-library should create an independent set
of DebugStreams so that the debug levels can be changed separately.
Example:
\code
static const Dune::DebugLevel APPL_MINLEVEL = 3;
Dune::DebugStream<1, APPL_MINLEVEL> myverbose;
Dune::DebugStream<2, APPL_MINLEVEL> myinfo;
Dune::DebugStream<3, APPL_MINLEVEL> mywarn;
\endcode
This code creates three streams of which only the last one really
creates output. The output-routines of the other streams vanish in
optimized executables.
You can use the common_bits-Template to switch to a policy using bitflags:
\code
enum { APPL_CORE = 1, APPL_IO = 2, APPL_GRAPHICS = 4};
static const Dune::DebugLevel APPL_DEBUG_MASK = APPL_CORE | APPL_GRAPHICS;
static const Dune::DebugLevel APPL_ACTIVE_MASK = 0xff;
Dune::DebugStream<APPL_CORE, APPL_DEBUG_MASK, APPL_ACTIVE_MASK, Dune::common_bits> coreout;
Dune::DebugStream<APPL_IO, APPL_DEBUG_MASK, APPL_ACTIVE_MASK, Dune::common_bits> ioout;
Dune::DebugStream<APPL_GRAPHICS, APPL_DEBUG_MASK, APPL_ACTIVE_MASK, Dune::common_bits> graphout;
\endcode
Applications that wish to redirect the \ref StdStreams through their
private streams may use the tie()-mechanism:
\code
// initialize streams like above
Dune::dwarn.tie(coreout);
// ... Dune-output to dwarn will be directed through coreout ...
Dune::dwarn.untie();
\endcode
Keep in mind to untie() a stream before the tied stream is destructed.
An alternative is to attach() an output stream defined by the application:
\code
std::ofstream mylog("application.log");
Dune::dwarn.attach(mylog);
\endcode
*/
/**
\addtogroup DebugOut
\{
*/
/*! \file
This file implements the class DebugStream to support output in a
variety of debug levels. Additionally, template parameters control
if the output operation is really performed so that unused debug
levels can be deactivated
*/
/*! \brief Type for debug levels.
Only positive values allowed
*/
typedef unsigned int DebugLevel;
/*!
\brief Greater or equal template test.
value is false if current is below the threshold, true otherwise
This is the default struct to control the activation policy of
DebugStream and deactivates output below the threshold
*/
template <DebugLevel current, DebugLevel threshold>
struct greater_or_equal {
static const bool value = (current >= threshold);
};
/*! \brief activate if current and mask have common bits switched on.
This template implements an alternative strategy to activate or
deactivate a DebugStream. Keep in mind to number your streams as
powers of two if using this template
*/
template <DebugLevel current, DebugLevel mask>
struct common_bits {
enum {value = ((current & mask)!=0) };
};
//! \brief standard exception for the debugstream
class DebugStreamError : public IOError {};
class StreamWrap {
public:
StreamWrap(std::ostream& _out) : out(_out) { }
std::ostream& out;
StreamWrap *next;
};
//! \brief Intermediate class to implement tie-operation of DebugStream
class DebugStreamState {
// !!! should be protected somehow but that won't be easy
public:
//! \brief current output stream and link to possibly pushed old output streams
StreamWrap* current;
//! \brief flag to switch output during runtime
bool _active;
//! \brief are we tied to another DebugStream?
bool _tied;
//! \brief how many streams are tied to this state
unsigned int _tied_streams;
};
/*!
\brief Generic class to implement debug output streams
The main function of a DebugStream is to provide output in a
standard ostream fashion that is fully deactivated if the level of
the stream does not meet the current requirements. More information in \ref DebugOut
\param thislevel this level
\param dlevel level needed for any output to happen
\param alevel level needed to switch activation flag on
\param activator template describing the activation policy
\todo Fix visibility of internal data
*/
template <DebugLevel thislevel = 1,
DebugLevel dlevel = 1,
DebugLevel alevel = 1,
template<DebugLevel, DebugLevel> class activator = greater_or_equal>
class DebugStream : public DebugStreamState {
public:
/*! \brief Create a DebugStream and set initial output stream
during runtime another stream can be attach()ed, however the
initial stream may not be detach()ed.
*/
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;
}
/*! \brief Create a DebugStream and directly tie to another DebugStream
The fallback is used if a DebugStream constructed via this method
is untie()ed later. Otherwise the stream would be broken afterwards.
*/
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++;
}
/*! \brief Destroy stream.
if other streams still tie() to this stream an exception will be
thrown. Otherwise the child streams would certainly break on the
next output
*/
~DebugStream() noexcept(false)
{
// untie
if (_tied)
tiedstate->_tied_streams--;
else {
// check if somebody still ties to us...
if (_tied_streams != 0)
DUNE_THROW(DebugStreamError,
"There are streams still tied to this stream!");
}
// remove ostream-stack
while (current != 0) {
StreamWrap *s = current;
current = current->next;
delete s;
}
}
//! \brief Generic types are passed on to current output stream
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;
}
/*! \brief explicit specialization so that enums can be printed
Operators for built-in types follow special
rules (ยง11.2.3) so that enums won't fit into the generic
method above. With an existing operator<< for int however
the enum will be automatically casted.
*/
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;
}
//! \brief pass on manipulators to underlying output stream
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;
}
//! \brief pass on flush to underlying output stream
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;
}
//! \brief set activation flag and store old value
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);
}
}
//! \brief restore previously set activation flag
void pop() throw(DebugStreamError) {
if (_actstack.empty())
DUNE_THROW(DebugStreamError, "No previous activation setting!");
_active = _actstack.top();
_actstack.pop();
}
/*! \brief reports if this stream will produce output
a DebugStream that is deactivated because of its level will always
return false, otherwise the state of the internal activation is
returned
*/
bool active() const {
return activator<thislevel, dlevel>::value && _active;
}
/*! \brief set output to a different stream.
Old stream data is stored
*/
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;
}
//! \brief detach current output stream and restore to previous stream
void detach() throw(DebugStreamError) {
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;
}
// \brief Tie a stream to this one.
void tie(DebugStreamState& to) throw(DebugStreamError) {
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++;
}
//! \brief Untie stream
void untie() throw(DebugStreamError) {
if(! _tied)
DUNE_THROW(DebugStreamError, "Cannot untie, stream is not tied!");
tiedstate->_tied_streams--;
_tied = false;
tiedstate = 0;
}
private:
//! \brief pointer to data of stream we're tied to
DebugStreamState* tiedstate;
/*! \brief Activation state history.
store old activation settings so that the outside code doesn't
need to remember */
std::stack<bool> _actstack;
};
/** /} */
}
#endif
|