Dune Core Modules (2.9.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 // SPDX-FileCopyrightInfo: Copyright (C) DUNE Project contributors, see file LICENSE.md in module root
4 // SPDX-License-Identifier: LicenseRef-GPL-2.0-only-with-DUNE-exception
5 
6 #ifndef DUNE_DEBUGSTREAM_HH
7 #define DUNE_DEBUGSTREAM_HH
8 
13 #include <iostream>
14 #include <stack>
15 
17 
18 namespace Dune {
19 
118  typedef unsigned int DebugLevel;
119 
129  template <DebugLevel current, DebugLevel threshold>
131  constexpr static bool value = (current >= threshold);
132  };
133 
134 
141  template <DebugLevel current, DebugLevel mask>
142  struct common_bits {
143  constexpr static bool value = ((current & mask) != 0);
144  };
145 
146 
148  class DebugStreamError : public IOError {};
149 
150  class StreamWrap {
151  public:
152  StreamWrap(std::ostream& _out) : out(_out) { }
153  std::ostream& out;
154  StreamWrap *next;
155  };
156 
159  // !!! should be protected somehow but that won't be easy
160  public:
162  StreamWrap* current;
163 
165  bool _active;
166 
168  bool _tied;
169 
171  unsigned int _tied_streams;
172  };
173 
188  template <DebugLevel thislevel = 1,
189  DebugLevel dlevel = 1,
190  DebugLevel alevel = 1,
191  template<DebugLevel, DebugLevel> class activator = greater_or_equal>
192  class DebugStream : public DebugStreamState {
193  public:
199  DebugStream(std::ostream& out = std::cerr) {
200  // start a new list of streams
201  current = new StreamWrap(out);
202  current->next = 0;
203 
204  // check if we are above the default activation level
205  _active = activator<thislevel,alevel>::value;
206 
207  // we're not tied to another DebugStream
208  _tied = false;
209 
210  // no child streams yet
211  _tied_streams = 0;
212  }
213 
220  std::ostream& fallback = std::cerr)
221  {
222  // start a new list of streams
223  current = new StreamWrap(fallback);
224  current->next = 0;
225 
226  // check if we are above the default activation level
227  _active = activator<thislevel,alevel>::value;
228  _tied_streams = 0;
229 
230  // tie to the provided stream
231  _tied = true;
232  tiedstate = &master;
233  tiedstate->_tied_streams++;
234  }
235 
244  {
245  // untie
246  if (_tied)
247  tiedstate->_tied_streams--;
248  else {
249  // check if somebody still ties to us...
250  if (_tied_streams != 0)
251  {
252  std::cerr << "DebugStream destructor is called while other streams are still tied to it. Terminating!" << std::endl;
253  std::terminate();
254  }
255  }
256 
257  // remove ostream-stack
258  while (current != 0) {
259  StreamWrap *s = current;
260  current = current->next;
261  delete s;
262  }
263  }
264 
266  template <class T>
267  DebugStream& operator<<(const T data) {
268  // remove the following code if stream wasn't compiled active
269  if (activator<thislevel, dlevel>::value) {
270  if (! _tied) {
271  if (_active)
272  current->out << data;
273  } else {
274  if (_active && tiedstate->_active)
275  tiedstate->current->out << data;
276  }
277  }
278 
279  return *this;
280  }
281 
289  DebugStream& operator<<(const int data) {
290  // remove the following code if stream wasn't compiled active
291  if (activator<thislevel, dlevel>::value) {
292  if (! _tied) {
293  if (_active)
294  current->out << data;
295  } else {
296  if (_active && tiedstate->_active)
297  tiedstate->current->out << data;
298  }
299  }
300 
301  return *this;
302  }
303 
305  DebugStream& operator<<(std::ostream& (*f)(std::ostream&)) {
306  if (activator<thislevel, dlevel>::value) {
307  if (! _tied) {
308  if (_active)
309  f(current->out);
310  } else {
311  if (_active && tiedstate->_active)
312  f(tiedstate->current->out);
313  }
314  }
315 
316  return *this;
317  }
318 
321  if (activator<thislevel, dlevel>::value) {
322  if (! _tied) {
323  if (_active)
324  current->out.flush();
325  } else {
326  if (_active && tiedstate->_active)
327  tiedstate->current->out.flush();
328  }
329  }
330 
331  return *this;
332  }
333 
335  void push(bool b) {
336  // are we at all active?
337  if (activator<thislevel,alevel>::value) {
338  _actstack.push(_active);
339  _active = b;
340  } else {
341  // stay off
342  _actstack.push(false);
343  }
344  }
345 
349  void pop() {
350  if (_actstack.empty())
351  DUNE_THROW(DebugStreamError, "No previous activation setting!");
352 
353  _active = _actstack.top();
354  _actstack.pop();
355  }
356 
363  bool active() const {
364  return activator<thislevel, dlevel>::value && _active;
365  }
366 
371  void attach(std::ostream& stream) {
372  if (_tied)
373  DUNE_THROW(DebugStreamError, "Cannot attach to a tied stream!");
374 
375  StreamWrap* newcurr = new StreamWrap(stream);
376  newcurr->next = current;
377  current = newcurr;
378  }
379 
383  void detach() {
384  if (current->next == 0)
385  DUNE_THROW(DebugStreamError, "Cannot detach initial stream!");
386  if (_tied)
387  DUNE_THROW(DebugStreamError, "Cannot detach a tied stream!");
388 
389  StreamWrap* old = current;
390  current = current->next;
391  delete old;
392  }
393 
397  void tie(DebugStreamState& to) {
398  if (to._tied)
399  DUNE_THROW(DebugStreamError, "Cannot tie to an already tied stream!");
400  if (_tied)
401  DUNE_THROW(DebugStreamError, "Stream already tied: untie first!");
402 
403  _tied = true;
404  tiedstate = &to;
405 
406  // tell master class
407  tiedstate->_tied_streams++;
408  }
409 
413  void untie() {
414  if(! _tied)
415  DUNE_THROW(DebugStreamError, "Cannot untie, stream is not tied!");
416 
417  tiedstate->_tied_streams--;
418  _tied = false;
419  tiedstate = 0;
420  }
421 
422  private:
424  DebugStreamState* tiedstate;
425 
430  std::stack<bool> _actstack;
431  };
432 
434 }
435 
436 
437 #endif
standard exception for the debugstream
Definition: debugstream.hh:148
Intermediate class to implement tie-operation of DebugStream.
Definition: debugstream.hh:158
Generic class to implement debug output streams.
Definition: debugstream.hh:192
Default exception class for I/O errors.
Definition: exceptions.hh:231
A few common exception classes.
DebugStream(std::ostream &out=std::cerr)
Create a DebugStream and set initial output stream.
Definition: debugstream.hh:199
void untie()
Untie stream.
Definition: debugstream.hh:413
DebugStream & operator<<(const T data)
Generic types are passed on to current output stream.
Definition: debugstream.hh:267
DebugStream & operator<<(const int data)
explicit specialization so that enums can be printed
Definition: debugstream.hh:289
void attach(std::ostream &stream)
set output to a different stream.
Definition: debugstream.hh:371
void detach()
detach current output stream and restore to previous stream
Definition: debugstream.hh:383
DebugStream & operator<<(std::ostream &(*f)(std::ostream &))
pass on manipulators to underlying output stream
Definition: debugstream.hh:305
DebugStream & flush()
pass on flush to underlying output stream
Definition: debugstream.hh:320
void pop()
restore previously set activation flag
Definition: debugstream.hh:349
bool active() const
reports if this stream will produce output
Definition: debugstream.hh:363
bool _active
flag to switch output during runtime
Definition: debugstream.hh:165
unsigned int _tied_streams
how many streams are tied to this state
Definition: debugstream.hh:171
void tie(DebugStreamState &to)
Tie a stream to this one.
Definition: debugstream.hh:397
void push(bool b)
set activation flag and store old value
Definition: debugstream.hh:335
unsigned int DebugLevel
Type for debug levels.
Definition: debugstream.hh:118
bool _tied
are we tied to another DebugStream?
Definition: debugstream.hh:168
StreamWrap * current
current output stream and link to possibly pushed old output streams
Definition: debugstream.hh:162
~DebugStream()
Destroy stream.
Definition: debugstream.hh:243
DebugStream(DebugStreamState &master, std::ostream &fallback=std::cerr)
Create a DebugStream and directly tie to another DebugStream.
Definition: debugstream.hh:219
#define DUNE_THROW(E, m)
Definition: exceptions.hh:218
Mask< V > mask(ADLTag< 0, std::is_same< V, Mask< V > >::value >, const V &v)
implements Simd::mask()
Definition: defaults.hh:153
Dune namespace.
Definition: alignedallocator.hh:13
activate if current and mask have common bits switched on.
Definition: debugstream.hh:142
Greater or equal template test.
Definition: debugstream.hh:130
Creative Commons License   |  Legal Statements / Impressum  |  Hosted by TU Dresden  |  generated with Hugo v0.80.0 (Apr 26, 22:29, 2024)