1 //******************************************************************
3 // Copyright 2015 Samsung Electronics All Rights Reserved.
5 //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
7 // Licensed under the Apache License, Version 2.0 (the "License");
8 // you may not use this file except in compliance with the License.
9 // You may obtain a copy of the License at
11 // http://www.apache.org/licenses/LICENSE-2.0
13 // Unless required by applicable law or agreed to in writing, software
14 // distributed under the License is distributed on an "AS IS" BASIS,
15 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 // See the License for the specific language governing permissions and
17 // limitations under the License.
19 //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
21 #ifndef COMMON_INTERNAL_ASSERTUTILS_H
22 #define COMMON_INTERNAL_ASSERTUTILS_H
30 #include "OCException.h"
32 #include "RCSException.h"
41 // This is a helper class to avoid calling the base layer during terminating the process.
42 // The reason why you should not call the base layer in this situation is that
43 // OC apis are singletons or internally implemented as singleton.
44 // Singleton implemented with a static variable is initialized
45 // in the first call to the function.
46 // It means you can not guarantee the order of initialization of the singletons,
47 // which is the reverse order of destruction.
48 // Some of RE classes are also implemented as singletons.
49 // Now we have a problem if RE tries to call one of OC apis
50 // after OC classes are destroyed first.
51 // To solve this issue, it registers exit handler to catch the termination event.
52 // Keep this information with a bool flag dynamically allocated to
53 // make sure it is not destroyed during the destruction of the static objects.
54 class TerminationChecker
57 static bool& getExited()
59 static bool* flag = new bool{ false };
63 static void atExitHandler()
70 std::atexit(atExitHandler);
74 static bool isInTermination()
76 static TerminationChecker once;
81 struct NotOCStackResult;
83 template <typename FUNC, typename ...PARAMS>
86 typedef decltype(std::declval<FUNC>()(std::declval<PARAMS>()...)) type;
89 template< typename A, typename B, typename ENABLER = void >
90 struct EnableIfTypeIs;
92 template< typename A >
93 struct EnableIfTypeIs< A, OCStackResult,
94 typename std::enable_if< std::is_same< A, OCStackResult >::value >::type >
99 template< typename A >
100 struct EnableIfTypeIs< A, NotOCStackResult,
101 typename std::enable_if< !std::is_same< A, OCStackResult >::value >::type >
106 template< typename T, typename = typename std::enable_if<
107 std::is_class<T>::value && std::is_pointer<T>::value>::type >
108 struct EnableIfClassPointer
113 template< typename T, typename = typename std::enable_if< std::is_class< T >::value > >
120 inline void expectOCStackResult(OCStackResult actual,
121 std::initializer_list<OCStackResult> allowed)
123 for (auto r : allowed)
125 if (actual == r) return;
128 throw RCSPlatformException(actual);
131 inline void expectOCStackResult(OCStackResult actual, OCStackResult expected)
133 if (actual != expected)
135 throw RCSPlatformException(actual);
139 inline void expectOCStackResultOK(OCStackResult actual)
141 expectOCStackResult(actual, OC_STACK_OK);
144 template< typename FUNC, typename ...PARAMS >
145 typename Detail::EnableIfTypeIs< typename Detail::ResultType< FUNC, PARAMS... >::type,
146 OCStackResult >::type
147 invokeOCFuncWithResultExpect(std::initializer_list<OCStackResult> allowed,
148 FUNC&& fn, PARAMS&& ...params)
150 if (Detail::TerminationChecker::isInTermination()) return;
154 expectOCStackResult(fn(std::forward< PARAMS >(params)...), std::move(allowed));
156 catch (const OC::OCException& e)
158 throw RCSPlatformException(e.code());
163 template< typename FUNC, typename ...PARAMS >
164 typename Detail::EnableIfTypeIs< typename Detail::ResultType< FUNC, PARAMS... >::type,
165 OCStackResult >::type
166 invokeOCFunc(FUNC&& fn, PARAMS&& ...params)
168 if (Detail::TerminationChecker::isInTermination()) return;
172 expectOCStackResultOK(fn(std::forward< PARAMS >(params)...));
174 catch (const OC::OCException& e)
176 throw RCSPlatformException(e.code());
180 template< typename FUNC, typename ...PARAMS >
181 typename Detail::EnableIfTypeIs< typename Detail::ResultType< FUNC, PARAMS... >::type,
182 Detail::NotOCStackResult >::type
183 invokeOCFunc(FUNC* fn, PARAMS&& ...params)
185 if (Detail::TerminationChecker::isInTermination()) return;
189 return fn(std::forward< PARAMS >(params)...);
191 catch (const OC::OCException& e)
193 throw RCSPlatformException(e.code());
197 template< typename OBJ, typename = typename Detail::EnableIfClassPointer<OBJ>::type,
198 typename FUNC, typename ...PARAMS >
199 inline auto invokeOC(OBJ&& obj, FUNC&& fn, PARAMS&& ...params) ->
200 typename Detail::EnableIfTypeIs<
201 decltype((obj->*fn)(std::forward< PARAMS >(params)...)), OCStackResult>::
204 if (Detail::TerminationChecker::isInTermination()) return;
208 expectOCStackResultOK(obj->*fn(std::forward< PARAMS >(params)...));
210 catch (const OC::OCException& e)
212 throw RCSPlatformException(e.code());
216 template< typename OBJ, typename = typename Detail::EnableIfClassPointer<OBJ>::type,
217 typename FUNC, typename ...PARAMS >
218 inline auto invokeOC(OBJ&& obj, FUNC&& fn, PARAMS&& ...params) ->
219 typename Detail::EnableIfTypeIs<
220 decltype((obj->*fn)(std::forward< PARAMS >(params)...)),
221 Detail::NotOCStackResult>::
224 if (Detail::TerminationChecker::isInTermination()) return;
228 obj->*fn(std::forward< PARAMS >(params)...);
230 catch (const OC::OCException& e)
232 throw RCSPlatformException(e.code());
236 template< typename OBJ, typename = typename Detail::EnableIfClass<OBJ>::type,
237 typename FUNC, typename ...PARAMS >
238 inline auto invokeOC(const std::shared_ptr< OBJ >& obj, FUNC&& fn, PARAMS&& ...params) ->
239 typename Detail::EnableIfTypeIs<
240 decltype((obj.get()->*fn)(std::forward< PARAMS >(params)...)), OCStackResult>::
243 if (Detail::TerminationChecker::isInTermination()) return;
247 expectOCStackResultOK((obj.get()->*fn)(std::forward< PARAMS >(params)...));
249 catch (const OC::OCException& e)
251 throw RCSPlatformException(e.code());
255 template< typename OBJ, typename = typename Detail::EnableIfClass< OBJ >::type,
256 typename FUNC, typename ...PARAMS >
257 inline auto invokeOC(const std::shared_ptr<OBJ>& obj, FUNC&& fn, PARAMS&& ...params) ->
258 typename Detail::EnableIfTypeIs<
259 decltype((obj.get()->*fn)(std::forward< PARAMS >(params)...)),
260 Detail::NotOCStackResult>::
263 if (Detail::TerminationChecker::isInTermination()) return { };
267 return (obj.get()->*fn)(std::forward< PARAMS >(params)...);
269 catch (const OC::OCException& e)
271 throw RCSPlatformException(e.code());
278 #endif // COMMON_INTERNAL_ASSERTUTILS_H