Dune Core Modules (2.5.0)

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;
152  StreamWrap *next;
153  };
154 
157  // !!! should be protected somehow but that won't be easy
158  public:
160  StreamWrap* current;
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 
240  ~DebugStream() noexcept(false)
241  {
242  // untie
243  if (_tied)
244  tiedstate->_tied_streams--;
245  else {
246  // check if somebody still ties to us...
247  if (_tied_streams != 0)
249  "There are streams still tied to this stream!");
250  }
251 
252  // remove ostream-stack
253  while (current != 0) {
254  StreamWrap *s = current;
255  current = current->next;
256  delete s;
257  }
258  }
259 
261  template <class T>
262  DebugStream& operator<<(const T data) {
263  // remove the following code if stream wasn't compiled active
264  if (activator<thislevel, dlevel>::value) {
265  if (! _tied) {
266  if (_active)
267  current->out << data;
268  } else {
269  if (_active && tiedstate->_active)
270  tiedstate->current->out << data;
271  }
272  }
273 
274  return *this;
275  }
276 
284  DebugStream& operator<<(const int data) {
285  // remove the following code if stream wasn't compiled active
286  if (activator<thislevel, dlevel>::value) {
287  if (! _tied) {
288  if (_active)
289  current->out << data;
290  } else {
291  if (_active && tiedstate->_active)
292  tiedstate->current->out << data;
293  }
294  }
295 
296  return *this;
297  }
298 
300  DebugStream& operator<<(std::ostream& (*f)(std::ostream&)) {
301  if (activator<thislevel, dlevel>::value) {
302  if (! _tied) {
303  if (_active)
304  f(current->out);
305  } else {
306  if (_active && tiedstate->_active)
307  f(tiedstate->current->out);
308  }
309  }
310 
311  return *this;
312  }
313 
316  if (activator<thislevel, dlevel>::value) {
317  if (! _tied) {
318  if (_active)
319  current->out.flush();
320  } else {
321  if (_active && tiedstate->_active)
322  tiedstate->current->out.flush();
323  }
324  }
325 
326  return *this;
327  }
328 
330  void push(bool b) {
331  // are we at all active?
332  if (activator<thislevel,alevel>::value) {
333  _actstack.push(_active);
334  _active = b;
335  } else {
336  // stay off
337  _actstack.push(false);
338  }
339  }
340 
342  void pop() throw(DebugStreamError) {
343  if (_actstack.empty())
344  DUNE_THROW(DebugStreamError, "No previous activation setting!");
345 
346  _active = _actstack.top();
347  _actstack.pop();
348  }
349 
356  bool active() const {
357  return activator<thislevel, dlevel>::value && _active;
358  }
359 
364  void attach(std::ostream& stream) {
365  if (_tied)
366  DUNE_THROW(DebugStreamError, "Cannot attach to a tied stream!");
367 
368  StreamWrap* newcurr = new StreamWrap(stream);
369  newcurr->next = current;
370  current = newcurr;
371  }
372 
374  void detach() throw(DebugStreamError) {
375  if (current->next == 0)
376  DUNE_THROW(DebugStreamError, "Cannot detach initial stream!");
377  if (_tied)
378  DUNE_THROW(DebugStreamError, "Cannot detach a tied stream!");
379 
380  StreamWrap* old = current;
381  current = current->next;
382  delete old;
383  }
384 
385  // \brief Tie a stream to this one.
386  void tie(DebugStreamState& to) throw(DebugStreamError) {
387  if (to._tied)
388  DUNE_THROW(DebugStreamError, "Cannot tie to an already tied stream!");
389  if (_tied)
390  DUNE_THROW(DebugStreamError, "Stream already tied: untie first!");
391 
392  _tied = true;
393  tiedstate = &to;
394 
395  // tell master class
396  tiedstate->_tied_streams++;
397  }
398 
400  void untie() throw(DebugStreamError) {
401  if(! _tied)
402  DUNE_THROW(DebugStreamError, "Cannot untie, stream is not tied!");
403 
404  tiedstate->_tied_streams--;
405  _tied = false;
406  tiedstate = 0;
407  }
408 
409  private:
411  DebugStreamState* tiedstate;
412 
417  std::stack<bool> _actstack;
418  };
419 
421 }
422 
423 
424 #endif
standard exception for the debugstream
Definition: debugstream.hh:146
Intermediate class to implement tie-operation of DebugStream.
Definition: debugstream.hh:156
Generic class to implement debug output streams.
Definition: debugstream.hh:190
Default exception class for I/O errors.
Definition: exceptions.hh:229
A few common exception classes.
DebugStream(std::ostream &out=std::cerr)
Create a DebugStream and set initial output stream.
Definition: debugstream.hh:197
~DebugStream() noexcept(false)
Destroy stream.
Definition: debugstream.hh:240
void untie()
Untie stream.
Definition: debugstream.hh:400
DebugStream & operator<<(const T data)
Generic types are passed on to current output stream.
Definition: debugstream.hh:262
DebugStream & operator<<(const int data)
explicit specialization so that enums can be printed
Definition: debugstream.hh:284
void attach(std::ostream &stream)
set output to a different stream.
Definition: debugstream.hh:364
void detach()
detach current output stream and restore to previous stream
Definition: debugstream.hh:374
DebugStream & operator<<(std::ostream &(*f)(std::ostream &))
pass on manipulators to underlying output stream
Definition: debugstream.hh:300
DebugStream & flush()
pass on flush to underlying output stream
Definition: debugstream.hh:315
void pop()
restore previously set activation flag
Definition: debugstream.hh:342
bool active() const
reports if this stream will produce output
Definition: debugstream.hh:356
bool _active
flag to switch output during runtime
Definition: debugstream.hh:163
unsigned int _tied_streams
how many streams are tied to this state
Definition: debugstream.hh:169
void push(bool b)
set activation flag and store old value
Definition: debugstream.hh:330
unsigned int DebugLevel
Type for debug levels.
Definition: debugstream.hh:116
bool _tied
are we tied to another DebugStream?
Definition: debugstream.hh:166
StreamWrap * current
current output stream and link to possibly pushed old output streams
Definition: debugstream.hh:160
DebugStream(DebugStreamState &master, std::ostream &fallback=std::cerr)
Create a DebugStream and directly tie to another DebugStream.
Definition: debugstream.hh:217
#define DUNE_THROW(E, m)
Definition: exceptions.hh:216
Dune namespace.
Definition: alignment.hh:11
activate if current and mask have common bits switched on.
Definition: debugstream.hh:140
Greater or equal template test.
Definition: debugstream.hh:128
Creative Commons License   |  Legal Statements / Impressum  |  Hosted by TU Dresden  |  generated with Hugo v0.80.0 (May 9, 22:29, 2024)