dune-common  2.4
debugstream.hh
Go to the documentation of this file.
1 // -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*-
2 // vi: set et ts=4 sw=2 sts=2:
3 
4 #ifndef DUNE_DEBUGSTREAM_HH
5 #define DUNE_DEBUGSTREAM_HH
6 
11 #include <iostream>
12 #include <stack>
13 
15 
16 namespace Dune {
17 
116  typedef unsigned int DebugLevel;
117 
127  template <DebugLevel current, DebugLevel threshold>
129  static const bool value = (current >= threshold);
130  };
131 
132 
139  template <DebugLevel current, DebugLevel mask>
140  struct common_bits {
141  enum {value = ((current & mask)!=0) };
142  };
143 
144 
146  class DebugStreamError : public IOError {};
147 
148  class StreamWrap {
149  public:
150  StreamWrap(std::ostream& _out) : out(_out) { };
151  std::ostream& out;
153  };
154 
157  // !!! should be protected somehow but that won't be easy
158  public:
161 
163  bool _active;
164 
166  bool _tied;
167 
169  unsigned int _tied_streams;
170  };
171 
186  template <DebugLevel thislevel = 1,
187  DebugLevel dlevel = 1,
188  DebugLevel alevel = 1,
189  template<DebugLevel, DebugLevel> class activator = greater_or_equal>
190  class DebugStream : public DebugStreamState {
191  public:
197  DebugStream(std::ostream& out = std::cerr) {
198  // start a new list of streams
199  current = new StreamWrap(out);
200  current->next = 0;
201 
202  // check if we are above the default activation level
203  _active = activator<thislevel,alevel>::value;
204 
205  // we're not tied to another DebugStream
206  _tied = false;
207 
208  // no child streams yet
209  _tied_streams = 0;
210  };
211 
218  std::ostream& fallback = std::cerr)
219  {
220  // start a new list of streams
221  current = new StreamWrap(fallback);
222  current->next = 0;
223 
224  // check if we are above the default activation level
225  _active = activator<thislevel,alevel>::value;
226  _tied_streams = 0;
227 
228  // tie to the provided stream
229  _tied = true;
230  tiedstate = &master;
231  tiedstate->_tied_streams++;
232  };
233 
241  // untie
242  if (_tied)
243  tiedstate->_tied_streams--;
244  else {
245  // check if somebody still ties to us...
246  if (_tied_streams != 0)
248  "There are streams still tied to this stream!");
249  };
250 
251  // remove ostream-stack
252  while (current != 0) {
253  StreamWrap *s = current;
254  current = current->next;
255  delete s;
256  };
257  };
258 
260  template <class T>
261  DebugStream& operator<<(const T data) {
262  // remove the following code if stream wasn't compiled active
263  if (activator<thislevel, dlevel>::value) {
264  if (! _tied) {
265  if (_active)
266  current->out << data;
267  } else {
268  if (_active && tiedstate->_active)
269  tiedstate->current->out << data;
270  };
271  };
272 
273  return *this;
274  }
275 
283  DebugStream& operator<<(const int data) {
284  // remove the following code if stream wasn't compiled active
285  if (activator<thislevel, dlevel>::value) {
286  if (! _tied) {
287  if (_active)
288  current->out << data;
289  } else {
290  if (_active && tiedstate->_active)
291  tiedstate->current->out << data;
292  };
293  };
294 
295  return *this;
296  }
297 
299  DebugStream& operator<<(std::ostream& (*f)(std::ostream&)) {
300  if (activator<thislevel, dlevel>::value) {
301  if (! _tied) {
302  if (_active)
303  f(current->out);
304  } else {
305  if (_active && tiedstate->_active)
306  f(tiedstate->current->out);
307  };
308  }
309 
310  return *this;
311  };
312 
315  if (activator<thislevel, dlevel>::value) {
316  if (! _tied) {
317  if (_active)
318  current->out.flush();
319  } else {
320  if (_active && tiedstate->_active)
321  tiedstate->current->out.flush();
322  };
323  }
324 
325  return *this;
326  };
327 
329  void push(bool b) {
330  // are we at all active?
331  if (activator<thislevel,alevel>::value) {
332  _actstack.push(_active);
333  _active = b;
334  } else {
335  // stay off
336  _actstack.push(false);
337  };
338  };
339 
341  void pop() throw(DebugStreamError) {
342  if (_actstack.empty())
343  DUNE_THROW(DebugStreamError, "No previous activation setting!");
344 
345  _active = _actstack.top();
346  _actstack.pop();
347  };
348 
355  bool active() const {
356  return activator<thislevel, dlevel>::value && _active;
357  };
358 
363  void attach(std::ostream& stream) {
364  if (_tied)
365  DUNE_THROW(DebugStreamError, "Cannot attach to a tied stream!");
366 
367  StreamWrap* newcurr = new StreamWrap(stream);
368  newcurr->next = current;
369  current = newcurr;
370  };
371 
373  void detach() throw(DebugStreamError) {
374  if (current->next == 0)
375  DUNE_THROW(DebugStreamError, "Cannot detach initial stream!");
376  if (_tied)
377  DUNE_THROW(DebugStreamError, "Cannot detach a tied stream!");
378 
379  StreamWrap* old = current;
380  current = current->next;
381  delete old;
382  };
383 
384  // \brief Tie a stream to this one.
386  if (to._tied)
387  DUNE_THROW(DebugStreamError, "Cannot tie to an already tied stream!");
388  if (_tied)
389  DUNE_THROW(DebugStreamError, "Stream already tied: untie first!");
390 
391  _tied = true;
392  tiedstate = &to;
393 
394  // tell master class
395  tiedstate->_tied_streams++;
396  };
397 
399  void untie() throw(DebugStreamError) {
400  if(! _tied)
401  DUNE_THROW(DebugStreamError, "Cannot untie, stream is not tied!");
402 
403  tiedstate->_tied_streams--;
404  _tied = false;
405  tiedstate = 0;
406  };
407 
408  private:
410  DebugStreamState* tiedstate;
411 
416  std::stack<bool> _actstack;
417  };
418 
420 }
421 
422 
423 #endif
std::ostream & out
Definition: debugstream.hh:150
DebugStream & operator<<(std::ostream &(*f)(std::ostream &))
pass on manipulators to underlying output stream
Definition: debugstream.hh:299
Definition: debugstream.hh:148
bool _active
flag to switch output during runtime
Definition: debugstream.hh:163
static const bool value
Definition: debugstream.hh:129
Intermediate class to implement tie-operation of DebugStream.
Definition: debugstream.hh:156
A few common exception classes.
Default exception class for I/O errors.
Definition: exceptions.hh:256
DebugStream(DebugStreamState &master, std::ostream &fallback=std::cerr)
Create a DebugStream and directly tie to another DebugStream.
Definition: debugstream.hh:217
StreamWrap(std::ostream &_out)
Definition: debugstream.hh:150
bool _tied
are we tied to another DebugStream?
Definition: debugstream.hh:166
void push(bool b)
set activation flag and store old value
Definition: debugstream.hh:329
void tie(DebugStreamState &to)
Definition: debugstream.hh:385
unsigned int DebugLevel
Type for debug levels.
Definition: debugstream.hh:116
standard exception for the debugstream
Definition: debugstream.hh:146
Dune namespace.
Definition: alignment.hh:9
~DebugStream()
Destroy stream.
Definition: debugstream.hh:240
DebugStream & operator<<(const T data)
Generic types are passed on to current output stream.
Definition: debugstream.hh:261
StreamWrap * current
current output stream and link to possibly pushed old output streams
Definition: debugstream.hh:160
Greater or equal template test.
Definition: debugstream.hh:128
void pop()
restore previously set activation flag
Definition: debugstream.hh:341
DebugStream(std::ostream &out=std::cerr)
Create a DebugStream and set initial output stream.
Definition: debugstream.hh:197
DebugStream & flush()
pass on flush to underlying output stream
Definition: debugstream.hh:314
void attach(std::ostream &stream)
set output to a different stream.
Definition: debugstream.hh:363
#define DUNE_THROW(E, m)
Definition: exceptions.hh:243
Definition: debugstream.hh:141
activate if current and mask have common bits switched on.
Definition: debugstream.hh:140
Generic class to implement debug output streams.
Definition: debugstream.hh:190
bool active() const
reports if this stream will produce output
Definition: debugstream.hh:355
StreamWrap * next
Definition: debugstream.hh:152
DebugStream & operator<<(const int data)
explicit specialization so that enums can be printed
Definition: debugstream.hh:283
void detach()
detach current output stream and restore to previous stream
Definition: debugstream.hh:373
unsigned int _tied_streams
how many streams are tied to this state
Definition: debugstream.hh:169
void untie()
Untie stream.
Definition: debugstream.hh:399