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
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
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 & flush()
pass on flush to underlying output stream
Definition: debugstream.hh:315
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
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 & operator<<(const T data)
Generic types are passed on to current output stream.
Definition: debugstream.hh:262
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:284
DebugStream & operator<<(std::ostream &(*f)(std::ostream &))
pass on manipulators to underlying output stream
Definition: debugstream.hh:300
#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.111.3 (Nov 23, 23:29, 2024)