PVData C++ 8.0.7
Loading...
Searching...
No Matches
epicsException.h
1/*
2 * Copyright information and license terms for this software can be
3 * found in the file LICENSE that is included with the distribution
4 */
5/*
6 * epicsException.h
7 *
8 * Created on: Oct 20, 2010
9 * Author: Matej Sekoranja
10 */
11
12/*
13 * Throwing exceptions w/ file+line# and, when possibly, a stack trace
14 *
15 * THROW_EXCEPTION1( std::bad_alloc );
16 *
17 * THROW_EXCEPTION2( std::logic_error, "my message" );
18 *
19 * THROW_EXCEPTION( mySpecialException("my message", 42, "hello", ...) );
20 *
21 * Catching exceptions
22 *
23 * catch(std::logic_error& e) {
24 * fprintf(stderr, "%s happened\n", e.what());
25 * PRINT_EXCEPTION2(e, stderr);
26 * cout<<SHOW_EXCEPTION(e);
27 * }
28 *
29 * If the exception was not thrown with the above THROW_EXCEPTION*
30 * the nothing will be printed.
31 */
32
33#ifndef EPICSEXCEPTION_H_
34#define EPICSEXCEPTION_H_
35
36#include <stdexcept>
37#include <string>
38#include <cstdio>
39
40#include <shareLib.h>
41
42// Users may redefine this for a large size if desired
43#ifndef EXCEPT_DEPTH
44# define EXCEPT_DEPTH 20
45#endif
46
47#if defined(__GLIBC__) || (defined(__APPLE__) && defined(__MACH__)) /* and possibly some BSDs */
48# include <execinfo.h>
49# include <cxxabi.h>
50# define EXCEPT_USE_BACKTRACE
51#elif defined(_WIN32) && !defined(_MINGW) && !defined(SKIP_DBGHELP)
52# define _WINSOCKAPI_
53# include <windows.h>
54# include <dbghelp.h>
55# define EXCEPT_USE_CAPTURE
56#else
57# define EXCEPT_USE_NONE
58#endif
59
60#if defined(_WIN32) && !defined(_MINGW)
61#pragma warning( push )
62#pragma warning(disable: 4275) // non dll-interface class used as base for dll-interface class (std::logic_error)
63#pragma warning(disable: 4251) // class std::string needs to have dll-interface to be used by clients
64#endif
65
66namespace epics { namespace pvData {
67
68
69/* Stores file and line number given, and when possible the call stack
70 * at the point where it was constructed
71 */
72class epicsShareClass ExceptionMixin {
73 const char *m_file;
74 int m_line;
75#ifndef EXCEPT_USE_NONE
76 void *m_stack[EXCEPT_DEPTH];
77 int m_depth; // always <= EXCEPT_DEPTH
78#endif
79public:
80 // allow the ctor to be inlined if possible
81 ExceptionMixin(const char* file, int line)
82 :m_file(file)
83 ,m_line(line)
84#if defined(EXCEPT_USE_BACKTRACE)
85 {
86 m_depth=backtrace(m_stack,EXCEPT_DEPTH);
87 }
88#elif defined(EXCEPT_USE_CAPTURE)
89 {
90 m_depth=CaptureStackBackTrace(0,EXCEPT_DEPTH,m_stack,0);
91 }
92#else
93 {}
94#endif
95
96 void print(FILE *fp=stderr) const;
97
98 std::string show() const;
99};
100
101#ifndef THROW_EXCEPTION_COMPAT
102
103namespace detail {
104 /* Combines user exception type with Mixin
105 *
106 * Takes advantage of the requirement that all exception classes
107 * must be copy constructable. Of course this also requires
108 * that an extra copy be constructed...
109 */
110 template<typename E>
111 class ExceptionMixed : public E, public ExceptionMixin {
112 public:
113 // construct from copy of E
114 ExceptionMixed(const E& self,const char* file, int line)
115 :E(self), ExceptionMixin(file,line)
116 {}
117 // construct for E w/o arguments
118 ExceptionMixed(const char* file, int line)
119 :E(), ExceptionMixin(file,line)
120 {}
121 // construct for E one argument
122 template<typename A1>
123 ExceptionMixed(A1 arg1,const char* file, int line)
124 :E(arg1), ExceptionMixin(file,line)
125 {}
126 // construct for E two arguments
127 template<typename A1, typename A2>
128 ExceptionMixed(A1 arg1, A2 arg2,const char* file, int line)
129 :E(arg1,arg2), ExceptionMixin(file,line)
130 {}
131 };
132
133 // function template to deduce E from argument
134 template<typename E>
135 static inline
137 makeException(const E& self,const char* file, int line)
138 {
139 return ExceptionMixed<E>(self,file,line);
140 }
141
142 template<typename E>
143 static inline
144 std::string
145 showException(const E& ex)
146 {
147 const ExceptionMixin *mx=dynamic_cast<const ExceptionMixin*>(&ex);
148 if(!mx) return std::string();
149 return mx->show();
150 }
151}
152
153// Throw an exception of a mixed sub-class of the type of E
154// The instance E is copied and discarded
155#define THROW_EXCEPTION(E) \
156do { \
157 throw ::epics::pvData::detail::makeException(E, __FILE__, __LINE__); \
158} while(0)
159
160// Throw an exception of a mixed sub-class of E, passing MSG as an argument
161#define THROW_EXCEPTION1(TYPE) \
162do { \
163 throw ::epics::pvData::detail::ExceptionMixed<TYPE>(__FILE__, __LINE__); \
164 }while(0)
165
166// Throw an exception of a mixed sub-class of E, passing MSG as an argument
167#define THROW_EXCEPTION2(TYPE,MSG) \
168do { \
169 throw ::epics::pvData::detail::ExceptionMixed<TYPE>(MSG, __FILE__, __LINE__); \
170}while(0)
171
172#define PRINT_EXCEPTION2(EI, FP) \
173do { \
174 ::epics::pvData::ExceptionMixin *_em_p=dynamic_cast< ::epics::pvData::ExceptionMixin*>(&EI); \
175 if (_em_p) {_em_p->print(FP);} \
176}while(0)
177
178#define PRINT_EXCEPTION(EI) PRINT_EXCEPTION2(EI,stderr)
179
180#if !defined(__GNUC__) || __GNUC__ < 4
181# define SHOW_EXCEPTION(EI) ::epics::pvData::detail::showException(EI)
182#else
183# define SHOW_EXCEPTION(EI) \
184 ({ ::epics::pvData::ExceptionMixin *_mx=dynamic_cast< ::epics::pvData::ExceptionMixin*>(&(EI)); \
185 _mx ? _mx->show() : std::string(); \
186 })
187#endif
188
189#else // THROW_EXCEPTION_COMPAT
190/* For older compilers which have a problem with the above */
191
192#define PRINT_EXCEPTION(EI) do{}while(0)
193#define PRINT_EXCEPTION2(EI,FP) do{}while(0)
194#define SHOW_EXCEPTION(EI) std::string()
195
196#define THROW_EXCEPTION(E) do{throw (E);}while(0)
197#define THROW_EXCEPTION1(E) do{throw (E)();}while(0)
198#define THROW_EXCEPTION2(E,A) do{throw (E)(A);}while(0)
199
200#endif // THROW_EXCEPTION_COMPAT
205class epicsShareClass BaseException : public std::logic_error {
206public:
210 explicit BaseException(const std::string& msg) : std::logic_error(msg) {}
211
215 virtual ~BaseException() throw(){};
216
221 virtual const char* what() const throw();
222
223private:
224 mutable std::string base_msg;
225};
226
227#if defined(_WIN32) && !defined(_MINGW)
228#pragma warning( pop )
229#endif
230
231#define THROW_BASE_EXCEPTION(msg) THROW_EXCEPTION2(::epics::pvData::BaseException, msg)
232
233 }
234}
235
236
237#endif /* EPICSEXCEPTION_H_ */
virtual const char * what() const
BaseException(const std::string &msg)
epics
Definition convert.h:21