RCFProto

- Main Page
- Classes
- Files

- File List

All Classes Functions Typedefs
Throw.hpp
1
2 //******************************************************************************
3 // RCF - Remote Call Framework
4 //
5 // Copyright (c) 2005 - 2013, Delta V Software. All rights reserved.
6 // http://www.deltavsoft.com
7 //
8 // RCF is distributed under dual licenses - closed source or GPL.
9 // Consult your particular license for conditions of use.
10 //
11 // If you have not purchased a commercial license, you are using RCF
12 // under GPL terms.
13 //
14 // Version: 2.0
15 // Contact: support <at> deltavsoft.com
16 //
17 //******************************************************************************
18
19 #ifndef INCLUDE_UTIL_THROW_HPP
20 #define INCLUDE_UTIL_THROW_HPP
21
22 #include <exception>
23 #include <memory>
24
25 #include <boost/current_function.hpp>
26
27 #include "VariableArgMacro.hpp"
28
29 namespace util {
30
31 namespace detail {
32
33 inline bool uncaught_exception()
34 {
35 return std::uncaught_exception();
36 }
37
38 class I_InvokeThrow
39 {
40 public:
41 virtual ~I_InvokeThrow() {}
42 virtual void invoke(const std::string &context, const std::string & args, int logName, int logLevel, const char * file, int line, const char * func) = 0;
43 };
44
45 template<typename E>
46 class InvokeThrow : public I_InvokeThrow
47 {
48 public:
49 InvokeThrow(const E &e) : mE(e)
50 {}
51
52 void invoke(const std::string &context, const std::string & args, int logName, int logLevel, const char * file, int line, const char * func)
53 {
54 const_cast<E &>(mE).setContext(context);
55
56 if (RCF::LogManager::instance().isEnabled(logName, logLevel))
57 {
58 RCF::LogEntry entry(logName, logLevel, file, line, func);
59
60 entry
61 << "Exception thrown. "
62 << mE;
63
64 if (!args.empty())
65 {
66 entry
67 << " Values: "
68 << args;
69 }
70 }
71
72 throw mE;
73 }
74
75 private:
76 const E &mE;
77 };
78
79 template<>
80 class InvokeThrow<std::runtime_error> : public I_InvokeThrow
81 {
82 public:
83 InvokeThrow(const std::runtime_error &e) : mE(e)
84 {}
85
86 void invoke(const std::string &context, const std::string & args, int logName, int logLevel, const char * file, int line, const char * func)
87 {
88 if (RCF::LogManager::instance().isEnabled(logName, logLevel))
89 {
90 RCF::LogEntry entry(logName, logLevel, file, line, func);
91
92 entry
93 << "Exception thrown. "
94 << mE;
95
96 if (!args.empty())
97 {
98 entry
99 << " Values: "
100 << args;
101 }
102 }
103
104 throw std::runtime_error( std::string(mE.what()) + ": " + context);
105 }
106
107 private:
108 const std::runtime_error &mE;
109 };
110
111 template<typename T>
112 const char *getTypeName(const T &t)
113 {
114 return typeid(t).name();
115 }
116
117 }
118
119 class ThrowFunctor : public VariableArgMacroFunctor
120 {
121 public:
122 ThrowFunctor() : mThrown(false), mLogName(0), mLogLevel(0)
123 {}
124
125 template<typename E>
126 ThrowFunctor(const E &e, int logName, int logLevel) :
127 VariableArgMacroFunctor(),
128 mInvokeThrow(new detail::InvokeThrow<E>(e)),
129 mThrown(false),
130 mLogName(logName),
131 mLogLevel(logLevel)
132 {}
133
134 ~ThrowFunctor()
135 {
136 // dtor gets called repeatedly by borland, believe it or not
137 if (!mThrown)
138 {
139 mThrown = true;
140
141 std::string args(mArgs->str(), static_cast<std::size_t>(mArgs->tellp()));
142
143 std::string context = mHeader->str();
144 context += args;
145
146 if (!util::detail::uncaught_exception())
147 {
148 mInvokeThrow->invoke(context, args, mLogName, mLogLevel, mFile, mLine, mFunc);
149 }
150 }
151 }
152
153 private:
154 std::auto_ptr<detail::I_InvokeThrow> mInvokeThrow;
155 bool mThrown;
156
157 int mLogName;
158 int mLogLevel;
159 };
160
161
162 #ifdef _MSC_VER
163 #pragma warning( push )
164 #pragma warning( disable : 4355 ) // warning C4355: 'this' : used in base member initializer list
165 #endif
166
167 #if defined(__GNUC__) && (__GNUC__ < 3 || (__GNUC__ == 3 && __GNUC_MINOR__ < 4))
168 #define UTIL_THROW_GCC_33_HACK (const util::VariableArgMacro<util::ThrowFunctor> &)
169 #else
170 #define UTIL_THROW_GCC_33_HACK
171 #endif
172
173 DECLARE_VARIABLE_ARG_MACRO( UTIL_THROW, ThrowFunctor );
174 #define UTIL_THROW(e, logName, logLevel) \
175 while (true) \
176 UTIL_THROW_GCC_33_HACK \
177 util::VariableArgMacro<util::ThrowFunctor>(e, logName, logLevel) \
178 .init( \
179 "", \
180 "", \
181 __FILE__, \
182 __LINE__, \
183 BOOST_CURRENT_FUNCTION) \
184 .cast( (util::VariableArgMacro<util::ThrowFunctor> *) NULL) \
185 .UTIL_THROW_A
186
187
188
189 #define UTIL_THROW_A(x) UTIL_THROW_OP(x, B)
190 #define UTIL_THROW_B(x) UTIL_THROW_OP(x, A)
191 #define UTIL_THROW_OP(x, next) UTIL_THROW_A.notify_((x), #x).UTIL_THROW_ ## next
192
193 #ifdef _MSC_VER
194 #pragma warning( pop )
195 #endif
196
197 #define UTIL_VERIFY(cond, e, logName, logLevel) if (cond); else UTIL_THROW(e, logName, logLevel)
198
199 } // namespace util
200
201 #endif // ! INCLUDE_UTIL_THROW_HPP