Dune Core Modules (unstable)

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 © 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
18namespace 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
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>
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
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:323
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 & flush()
pass on flush to underlying output stream
Definition: debugstream.hh:320
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
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 & operator<<(const T data)
Generic types are passed on to current output stream.
Definition: debugstream.hh:267
~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
DebugStream & operator<<(const int data)
explicit specialization so that enums can be printed
Definition: debugstream.hh:289
DebugStream & operator<<(std::ostream &(*f)(std::ostream &))
pass on manipulators to underlying output stream
Definition: debugstream.hh:305
#define DUNE_THROW(E,...)
Definition: exceptions.hh:312
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.111.3 (Dec 21, 23:30, 2024)