Dune Core Modules (2.4.1)

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
16namespace 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
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>
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#if HAVE_NOEXCEPT_SPECIFIER
242 noexcept(false)
243#endif
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)
252 "There are streams still tied to this stream!");
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
345 void pop() throw(DebugStreamError) {
346 if (_actstack.empty())
347 DUNE_THROW(DebugStreamError, "No previous activation setting!");
348
349 _active = _actstack.top();
350 _actstack.pop();
351 };
352
359 bool active() const {
360 return activator<thislevel, dlevel>::value && _active;
361 };
362
367 void attach(std::ostream& stream) {
368 if (_tied)
369 DUNE_THROW(DebugStreamError, "Cannot attach to a tied stream!");
370
371 StreamWrap* newcurr = new StreamWrap(stream);
372 newcurr->next = current;
373 current = newcurr;
374 };
375
377 void detach() throw(DebugStreamError) {
378 if (current->next == 0)
379 DUNE_THROW(DebugStreamError, "Cannot detach initial stream!");
380 if (_tied)
381 DUNE_THROW(DebugStreamError, "Cannot detach a tied stream!");
382
383 StreamWrap* old = current;
384 current = current->next;
385 delete old;
386 };
387
388 // \brief Tie a stream to this one.
389 void tie(DebugStreamState& to) throw(DebugStreamError) {
390 if (to._tied)
391 DUNE_THROW(DebugStreamError, "Cannot tie to an already tied stream!");
392 if (_tied)
393 DUNE_THROW(DebugStreamError, "Stream already tied: untie first!");
394
395 _tied = true;
396 tiedstate = &to;
397
398 // tell master class
399 tiedstate->_tied_streams++;
400 };
401
403 void untie() throw(DebugStreamError) {
404 if(! _tied)
405 DUNE_THROW(DebugStreamError, "Cannot untie, stream is not tied!");
406
407 tiedstate->_tied_streams--;
408 _tied = false;
409 tiedstate = 0;
410 };
411
412 private:
414 DebugStreamState* tiedstate;
415
420 std::stack<bool> _actstack;
421 };
422
424}
425
426
427#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:256
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:403
DebugStream & flush()
pass on flush to underlying output stream
Definition: debugstream.hh:318
void attach(std::ostream &stream)
set output to a different stream.
Definition: debugstream.hh:367
void detach()
detach current output stream and restore to previous stream
Definition: debugstream.hh:377
void pop()
restore previously set activation flag
Definition: debugstream.hh:345
bool active() const
reports if this stream will produce output
Definition: debugstream.hh:359
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: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 & operator<<(const T data)
Generic types are passed on to current output stream.
Definition: debugstream.hh:265
~DebugStream()
Destroy stream.
Definition: debugstream.hh:240
DebugStream(DebugStreamState &master, std::ostream &fallback=std::cerr)
Create a DebugStream and directly tie to another DebugStream.
Definition: debugstream.hh:217
DebugStream & operator<<(const int data)
explicit specialization so that enums can be printed
Definition: debugstream.hh:287
DebugStream & operator<<(std::ostream &(*f)(std::ostream &))
pass on manipulators to underlying output stream
Definition: debugstream.hh:303
#define DUNE_THROW(E, m)
Definition: exceptions.hh:243
Dune namespace.
Definition: alignment.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.111.3 (Nov 21, 23:30, 2024)