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
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
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
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 & 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:369
void detach()
detach current output stream and restore to previous stream
Definition: debugstream.hh:381
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 & operator<<(const T data)
Generic types are passed on to current output stream.
Definition: debugstream.hh:265
~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
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: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.111.3 (Dec 26, 23:30, 2024)