fmatvec  0.0.0
atom.h
1#ifndef _FMATVEC_ATOM_H
2#define _FMATVEC_ATOM_H
3
4#include <ostream>
5#include <iostream>
6#include <functional>
7#include <memory>
8#include <array>
9#include <sstream>
10#include <chrono>
11#include "stream.h"
12
13namespace fmatvec {
14FMATVEC_MSVC_DISABLEW4251_BEGIN
15
16class AdoptCurrentMessageStreamsUntilScopeExit;
17
20FMATVEC_EXPORT extern DisableEscaping disableEscaping;
21FMATVEC_EXPORT extern EnableEscaping enableEscaping;
22
23// Write synchronized to str_.
24// The synchronization is done globally (not seperately for each str_)
25// The content is buffered and written to str_ at destruction time of this object.
26// The two special output manipulators disableEscaping and enableEscaping can be used (always as a pair)
27// to enforce a none escaping mode of str_ if str_ supports this.
28// If so, disableEscaping is translated to str_<<flush<<skipws and
29// enableEscaping to std_<<flush<<noskipws.
30// What str_ actually does on skipws/noskipws is defined by the used class for str_.
31class FMATVEC_EXPORT osyncstream
32#ifndef SWIG // swig can not parse this however it is not needed for swig
33 : public std::ostream
34#endif
35{
36 public:
37 osyncstream(std::ostream &str_);
38 osyncstream(osyncstream &) = delete;
39 osyncstream(osyncstream &&) noexcept;
40 osyncstream& operator=(osyncstream &) = delete;
41 osyncstream& operator=(osyncstream &&) = delete;
42 ~osyncstream() override;
45 osyncstream& operator<<(bool value) { std::ostream::operator<<(value ); return *this; }
46 osyncstream& operator<<(long value) { std::ostream::operator<<(value ); return *this; }
47 osyncstream& operator<<(unsigned long value) { std::ostream::operator<<(value ); return *this; }
48 osyncstream& operator<<(long long value) { std::ostream::operator<<(value ); return *this; }
49 osyncstream& operator<<(unsigned long long value) { std::ostream::operator<<(value ); return *this; }
50 osyncstream& operator<<(double value) { std::ostream::operator<<(value ); return *this; }
51 osyncstream& operator<<(long double value) { std::ostream::operator<<(value ); return *this; }
52 osyncstream& operator<<(const void* value) { std::ostream::operator<<(value ); return *this; }
53 osyncstream& operator<<(std::nullptr_t) { std::ostream::operator<<(nullptr); return *this; }
54 osyncstream& operator<<(short value) { std::ostream::operator<<(value ); return *this; }
55 osyncstream& operator<<(int value) { std::ostream::operator<<(value ); return *this; }
56 osyncstream& operator<<(unsigned short value) { std::ostream::operator<<(value ); return *this; }
57 osyncstream& operator<<(unsigned int value) { std::ostream::operator<<(value ); return *this; }
58 osyncstream& operator<<(float value) { std::ostream::operator<<(value ); return *this; }
59 osyncstream& operator<<(std::streambuf* sb) { std::ostream::operator<<(sb ); return *this; }
60 osyncstream& operator<<(std::ios_base& (*func)(std::ios_base&)) { std::ostream::operator<<(func ); return *this; }
61 osyncstream& operator<<(std::ostream& (*func)(std::ostream&)) { std::ostream::operator<<(func ); return *this; }
62
63 // Use this function with care!!! It's mainly not indented to be used.
64 std::ostream &getOStream() const { return str; }
65 private:
66 std::stringbuf buf;
67 std::ostream &str;
68 bool moved { false };
69};
70
71inline osyncstream& operator<<(osyncstream& os, char ch) { operator<<(static_cast<std::ostream&>(os), ch); return os; }
72inline osyncstream& operator<<(osyncstream& os, signed char ch) { operator<<(static_cast<std::ostream&>(os), ch); return os; }
73inline osyncstream& operator<<(osyncstream& os, unsigned char ch) { operator<<(static_cast<std::ostream&>(os), ch); return os; }
74inline osyncstream& operator<<(osyncstream& os, const char* s) { operator<<(static_cast<std::ostream&>(os), s ); return os; }
75inline osyncstream& operator<<(osyncstream& os, const signed char* s) { operator<<(static_cast<std::ostream&>(os), s ); return os; }
76inline osyncstream& operator<<(osyncstream& os, const unsigned char* s) { operator<<(static_cast<std::ostream&>(os), s ); return os; }
77inline osyncstream& operator<<(osyncstream& os, const std::string &s) { operator<<(static_cast<std::ostream&>(os), s ); return os; }
78
86class FMATVEC_EXPORT Atom {
88 public:
89
91 // When adding new message type a stream and a initial active flag must be provided in atom.cc (see NEW TYPES HERE)
92 enum MsgType {
93 Info, // Informational messages
94 Warn, // Warning messages
95 Debug, // Debugging messages
96 Error, // Error messages
97 Deprecated, // Error messages
98 Status, // Status messages (only the last message is relevant)
99 SIZE // Must be the last enum in this list
100 };
101 #define FMATVEC_ATOM_MSGTYPE_SIZE 6
102#ifndef SWIG // swig can not parse this however it is not needed for swig
103 static_assert(SIZE==FMATVEC_ATOM_MSGTYPE_SIZE, "The proprocessor define FMATVEC_ATOM_MSGTYPE_SIZE must be equal Atom::SIZE.");
104#endif
105
106 protected:
108 Atom();
110 Atom(const Atom &src);
111 public:
113 virtual ~Atom();
114#ifndef SWIG // no assignment operator for swig
116 Atom& operator=(const Atom &);
117#endif
118
124 static void setCurrentMessageStream(MsgType type,
125 const std::shared_ptr<bool> &a=std::make_shared<bool>(true),
126 const std::shared_ptr<std::ostream> &s=std::make_shared<std::ostream>(std::cout.rdbuf()));
127
129 void setMessageStreamActive(MsgType type, bool activeFlag);
130
132 void getMessageStream(MsgType type,
135
139 void adoptMessageStreams(const Atom *src=nullptr);
140
144 osyncstream msg(MsgType type) const {
145 return *_msg[type];
146 }
150 bool msgAct(MsgType type) const {
151 return *_msgAct[type];
152 }
153
157 return *_msgStatic[type];
158 }
161 static bool msgActStatic(MsgType type) {
162 return *_msgActStatic[type];
163 }
164
165 private:
166
167 // A stream which prints to null.
168 static std::shared_ptr<std::ostream> _nullStream;
169
170 // Static pointer arrays of streams and active flags which were used for newly created objects.
171 // These can be changed using setCurrentMessageStream(...)
172 static std::array<std::shared_ptr<bool >, SIZE> _msgActStatic;
173 static std::array<std::shared_ptr<std::ostream>, SIZE> _msgSavedStatic;
174 static std::array<std::shared_ptr<std::ostream>, SIZE> _msgStatic;
175
176 // Pointer arrays to streams and active flags this object uses.
177 // (these have a life-time at least as long as the object itself, ensured by reference counting)
178 std::array<std::shared_ptr<bool >, SIZE> _msgAct;
179 std::array<std::shared_ptr<std::ostream>, SIZE> _msgSaved;
180 std::array<std::shared_ptr<std::ostream>, SIZE> _msg;
181};
182
183#ifndef SWIG
191class FMATVEC_EXPORT PrePostfixedStream : public std::ostream {
192 public:
194 PrePostfixedStream(const std::string &prefix_, const std::string &postfix_,
195 const std::function<void(const std::string &)> &outputFunc,
196 const std::function<void(std::string&)> &escapingFunc=nullptr);
198 PrePostfixedStream(const std::string &prefix_, const std::string &postfix_, std::ostream &outstr_,
199 const std::function<void(std::string&)> &escapingFunc=nullptr);
200 private:
201 class StringBuf : public std::streambuf {
202 public:
203 StringBuf(const PrePostfixedStream &stream_, std::string prefix_, std::string postfix_,
204 const std::function<void(const std::string &)> &outputFunc_,
205 const std::function<void(std::string&)> &escapingFunc_);
206 protected:
207 int overflow(int c) override;
208 std::streamsize xsputn(const char_type* s, std::streamsize count) override;
209 int sync() override;
210 private:
211 void flushBuffer();
212 std::string buffer;
213 std::function<void(const std::string &)> outputFunc;
214 const PrePostfixedStream &stream;
215 const std::string prefix;
216 const std::string postfix;
217 const std::function<void(std::string&)> escapingFunc;
218 };
219 StringBuf buffer;
220};
221#endif
222
226 public:
235 private:
236 std::array<std::pair<std::shared_ptr<bool>, std::shared_ptr<std::ostream>>, Atom::SIZE> savedStreams;
237};
238
239// BEGIN: measure time (just used for performance debugging)
241 public:
242 DebugMeasureAccumulatedTime(std::chrono::duration<double> &sum_, size_t &count_) : sum(sum_), count(count_) {
243 start = std::chrono::steady_clock::now();
244 }
246 auto end = std::chrono::steady_clock::now();
247 auto delta = std::chrono::duration<double>(end - start);
248 sum += delta;
249 count++;
250 }
251 private:
252 std::chrono::time_point<std::chrono::steady_clock> start;
253 std::chrono::duration<double> &sum;
254 size_t &count;
255};
257 public:
258 DebugMeasureAccumulatedTimeOnExit(const std::string &id_, std::chrono::duration<double> &sum_, size_t &count_) : id(id_), sum(sum_), count(count_) {
259 }
261 std::cout<<"fmatvec_measure_id,"<<id<<",totalsec,"<<sum.count()<<",count,"<<count<<",avgsec,"<<sum.count()/count<<std::endl;
262 }
263 private:
264 std::string id;
265 std::chrono::duration<double> &sum;
266 size_t &count;
267};
268// measure the accumulated time and number of calls of a block
269#define FMATVEC_MEASURE_BLOCK(id) \
270 static std::chrono::duration<double> fmatvec_measure_sum_##id {}; \
271 static size_t fmatvec_measure_count_##id {}; \
272 static fmatvec::DebugMeasureAccumulatedTimeOnExit fmatvec_measure_onexit_##id(#id, fmatvec_measure_sum_##id, fmatvec_measure_count_##id); \
273 fmatvec::DebugMeasureAccumulatedTime fmatvec_measure_dummy_##id(fmatvec_measure_sum_##id, fmatvec_measure_count_##id);
274// measure the accumulated time and number of calls of all blocks which contain FMATVEC_MEASURE_RUN(id)
275#define FMATVEC_MEASURE_BLOCKINIT(id) \
276 static std::chrono::duration<double> fmatvec_measure_sum_##id {}; \
277 static size_t fmatvec_measure_count_##id {}; \
278 static fmatvec::DebugMeasureAccumulatedTimeOnExit fmatvec_measure_onexit_##id(#id, fmatvec_measure_sum_##id, fmatvec_measure_count_##id);
279// see, the define above
280#define FMATVEC_MEASURE_BLOCKEXE(id) \
281 fmatvec::DebugMeasureAccumulatedTime fmatvec_measure_dummy_##id(fmatvec_measure_sum_##id, fmatvec_measure_count_##id);
282// start time measure for id
283#define FMATVEC_MEASURE_START(id) \
284 auto fmatvec_measure_start_##id = std::chrono::steady_clock::now();
285// dump elapsed time since the start of id (see the define above)
286#define FMATVEC_MEASURE_DUMP(id) \
287 { \
288 auto end = std::chrono::steady_clock::now(); \
289 auto delta = std::chrono::duration<double>(end - fmatvec_measure_start_##id); \
290 std::cout<<"fmatvec_measure_start_end_id,"<<#id<<",sec,"<<delta.count()<<std::endl; \
291 }
292// BEGIN: measure time (just used for performance debugging)
293
294FMATVEC_MSVC_DISABLEW4251_END
295}
296
297#endif
Definition: atom.h:86
osyncstream msg(MsgType type) const
Definition: atom.h:144
bool msgAct(MsgType type) const
Definition: atom.h:150
virtual ~Atom()
dtor.
MsgType
Messages can be printed to different message types named here.
Definition: atom.h:92
static bool msgActStatic(MsgType type)
Definition: atom.h:161
static osyncstream msgStatic(MsgType type)
Definition: atom.h:156
Definition: atom.h:18
Definition: atom.h:19
Definition: atom.h:191
PrePostfixedStream(const std::string &prefix_, const std::string &postfix_, const std::function< void(const std::string &)> &outputFunc, const std::function< void(std::string &)> &escapingFunc=nullptr)
Call f with every message of the stream, prefixed/postfixed.
PrePostfixedStream(const std::string &prefix_, const std::string &postfix_, std::ostream &outstr_, const std::function< void(std::string &)> &escapingFunc=nullptr)
Convinence function to print to outstr_.
Definition: atom.h:35
Definition: types.h:85
Namespace fmatvec.
Definition: _memory.cc:28
ostream & operator<<(ostream &s, const SymbolicExpression &se)
Write a SymbolicExpression to a stream using serialization.
Definition: ast.cc:190