Dune Core Modules (2.6.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 
242  {
243  // untie
244  if (_tied)
245  tiedstate->_tied_streams--;
246  else {
247  // check if somebody still ties to us...
248  if (_tied_streams != 0)
249  {
250  std::cerr << "DebugStream destructor is called while other streams are still tied to it. Terminating!" << std::endl;
251  std::terminate();
252  }
253  }
254 
255  // remove ostream-stack
256  while (current != 0) {
257  StreamWrap *s = current;
258  current = current->next;
259  delete s;
260  }
261  }
262 
264  template <class T>
265  DebugStream& operator<<(const T data) {
266  // remove the following code if stream wasn't compiled active
267  if (activator<thislevel, dlevel>::value) {
268  if (! _tied) {
269  if (_active)
270  current->out << data;
271  } else {
272  if (_active && tiedstate->_active)
273  tiedstate->current->out << data;
274  }
275  }
276 
277  return *this;
278  }
279 
287  DebugStream& operator<<(const int data) {
288  // remove the following code if stream wasn't compiled active
289  if (activator<thislevel, dlevel>::value) {
290  if (! _tied) {
291  if (_active)
292  current->out << data;
293  } else {
294  if (_active && tiedstate->_active)
295  tiedstate->current->out << data;
296  }
297  }
298 
299  return *this;
300  }
301 
303  DebugStream& operator<<(std::ostream& (*f)(std::ostream&)) {
304  if (activator<thislevel, dlevel>::value) {
305  if (! _tied) {
306  if (_active)
307  f(current->out);
308  } else {
309  if (_active && tiedstate->_active)
310  f(tiedstate->current->out);
311  }
312  }
313 
314  return *this;
315  }
316 
319  if (activator<thislevel, dlevel>::value) {
320  if (! _tied) {
321  if (_active)
322  current->out.flush();
323  } else {
324  if (_active && tiedstate->_active)
325  tiedstate->current->out.flush();
326  }
327  }
328 
329  return *this;
330  }
331 
333  void push(bool b) {
334  // are we at all active?
335  if (activator<thislevel,alevel>::value) {
336  _actstack.push(_active);
337  _active = b;
338  } else {
339  // stay off
340  _actstack.push(false);
341  }
342  }
343 
347  void pop() {
348  if (_actstack.empty())
349  DUNE_THROW(DebugStreamError, "No previous activation setting!");
350 
351  _active = _actstack.top();
352  _actstack.pop();
353  }
354 
361  bool active() const {
362  return activator<thislevel, dlevel>::value && _active;
363  }
364 
369  void attach(std::ostream& stream) {
370  if (_tied)
371  DUNE_THROW(DebugStreamError, "Cannot attach to a tied stream!");
372 
373  StreamWrap* newcurr = new StreamWrap(stream);
374  newcurr->next = current;
375  current = newcurr;
376  }
377 
381  void detach() {
382  if (current->next == 0)
383  DUNE_THROW(DebugStreamError, "Cannot detach initial stream!");
384  if (_tied)
385  DUNE_THROW(DebugStreamError, "Cannot detach a tied stream!");
386 
387  StreamWrap* old = current;
388  current = current->next;
389  delete old;
390  }
391 
395  void tie(DebugStreamState& to) {
396  if (to._tied)
397  DUNE_THROW(DebugStreamError, "Cannot tie to an already tied stream!");
398  if (_tied)
399  DUNE_THROW(DebugStreamError, "Stream already tied: untie first!");
400 
401  _tied = true;
402  tiedstate = &to;
403 
404  // tell master class
405  tiedstate->_tied_streams++;
406  }
407 
411  void untie() {
412  if(! _tied)
413  DUNE_THROW(DebugStreamError, "Cannot untie, stream is not tied!");
414 
415  tiedstate->_tied_streams--;
416  _tied = false;
417  tiedstate = 0;
418  }
419 
420  private:
422  DebugStreamState* tiedstate;
423 
428  std::stack<bool> _actstack;
429  };
430 
432 }
433 
434 
435 #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
void untie()
Untie stream.
Definition: debugstream.hh:411
DebugStream & operator<<(const T data)
Generic types are passed on to current output stream.
Definition: debugstream.hh:265
DebugStream & operator<<(const int data)
explicit specialization so that enums can be printed
Definition: debugstream.hh:287
void attach(std::ostream &stream)
set output to a different stream.
Definition: debugstream.hh:369
void detach()
detach current output stream and restore to previous stream
Definition: debugstream.hh:381
DebugStream & operator<<(std::ostream &(*f)(std::ostream &))
pass on manipulators to underlying output stream
Definition: debugstream.hh:303
DebugStream & flush()
pass on flush to underlying output stream
Definition: debugstream.hh:318
void pop()
restore previously set activation flag
Definition: debugstream.hh:347
bool active() const
reports if this stream will produce output
Definition: debugstream.hh:361
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 tie(DebugStreamState &to)
Tie a stream to this one.
Definition: debugstream.hh:395
void push(bool b)
set activation flag and store old value
Definition: debugstream.hh:333
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()
Destroy stream.
Definition: debugstream.hh:241
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: alignedallocator.hh:10
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 (Apr 27, 22:29, 2024)