ompMacros.hpp
1 #ifndef DM_OMP_MACROS_HPP_INCLUDED
2 #define DM_OMP_MACROS_HPP_INCLUDED
3 
4 #pragma once
5 
6 //openMP
7 #include <omp.h>
8 
9 //boost
10 #include <boost/throw_exception.hpp>
11 #include <boost/exception/exception.hpp>
12 #include <boost/exception_ptr.hpp>
13 #include <boost/preprocessor/seq/for_each.hpp>
14 
15 #include "config.hpp"
16 
17 // Exception handling is not straight forward in multi-thread applications.
18 // Use the following macros to transport the first thrown exception from within an OpenMP loop to the main thread.
19 //
20 // example:
21 //
22 // #define EXCEPTION_SEQUENCE (exception_class1) (exception_class2) [...]
23 //
24 // DM_OMP_OUTSIDE_LOOP_PREFIX
25 //
26 // #pragma omp parallel for
27 // for(int i=0; i<1000; i++)
28 // {
29 // DM_OMP_INSIDE_LOOP_PREFIX
30 //
31 // //loop code
32 // /* optionally, replace do_nothing with your own function */
33 // DM_OMP_INSIDE_LOOP_SUFFIX( EXCEPTION_SEQUENCE, DM::OpenMP::do_nothing )
34 // }
35 //
36 // DM_OMP_OUTSIDE_LOOP_SUFFIX(EXCEPTION_SEQUENCE)
37 //
38 
39 
40 #define DM_OMP_OUTSIDE_LOOP_PREFIX \
41  ::boost::exception_ptr omp_error; \
42  ::omp_lock_t omp_lock; \
43  ::omp_init_lock(&omp_lock); \
44 
45 
46 #define DM_OMP_HAS_EXCEPTION_OCCURED() \
47  DM::OpenMP::has_exception_occured(omp_lock,omp_error) \
48 
49 #define DM_OMP_INSIDE_LOOP_PREFIX \
50 try \
51 { \
52  ::omp_set_lock(&omp_lock); \
53  bool occured = omp_error; \
54  ::omp_unset_lock(&omp_lock); \
55  if( occured ) \
56  continue; \
57  try \
58  { \
59 
60 
61 #define DM_OMP_CATCH_BLOCK(r, FUNCTION, EXCEPTION) \
62  catch(const EXCEPTION &exc) \
63  { \
64  FUNCTION(exc); \
65  throw ::boost::enable_current_exception(::boost::enable_error_info(exc)); \
66  } \
67 
68 
69 #define DM_OMP_INSIDE_LOOP_SUFFIX(EXCEPTION_SEQUENCE, FUNCTION) \
70  } \
71  BOOST_PP_SEQ_FOR_EACH( DM_OMP_CATCH_BLOCK, FUNCTION, EXCEPTION_SEQUENCE ) \
72  catch (...) \
73  { \
74  FUNCTION(); \
75  ::boost::throw_exception( ::std::exception() ); \
76  } \
77 } \
78 catch( ... ) \
79 { \
80  ::omp_set_lock(&omp_lock); \
81  if(!omp_error) \
82  omp_error = ::boost::current_exception(); \
83  ::omp_unset_lock(&omp_lock); \
84 } \
85 
86 
87 #define DM_OMP_OUTSIDE_LOOP_SUFFIX(EXCEPTION_SEQUENCE) \
88  ::omp_destroy_lock(&omp_lock); \
89  if( omp_error ) \
90  ::boost::rethrow_exception(omp_error); \
91 
92 DM_NAMESPACE_BEGIN
93 
94 namespace OpenMP
95 {
96  template<typename ExceptionT>
97  inline void do_nothing(ExceptionT &e) {}
98  inline void do_nothing() {}
99 
100  inline bool has_exception_occured(::omp_lock_t &omp_lock, ::boost::exception_ptr &omp_error) {
101  ::omp_set_lock(&omp_lock);
102  bool occured = omp_error;
103  ::omp_unset_lock(&omp_lock);
104  return occured;
105  }
106 
107 }
108 
109 DM_NAMESPACE_END
110 
111 #endif //DM_OMP_MACROS_HPP_INCLUDED