1 | /*! |
2 | * Copyright (c) 2015 by Contributors |
3 | * \file common.h |
4 | * \brief defines some common utility function. |
5 | */ |
6 | #ifndef DMLC_COMMON_H_ |
7 | #define DMLC_COMMON_H_ |
8 | |
9 | #include <vector> |
10 | #include <string> |
11 | #include <sstream> |
12 | #include <mutex> |
13 | #include <utility> |
14 | #include "./logging.h" |
15 | |
16 | namespace dmlc { |
17 | /*! |
18 | * \brief Split a string by delimiter |
19 | * \param s String to be splitted. |
20 | * \param delim The delimiter. |
21 | * \return a splitted vector of strings. |
22 | */ |
23 | inline std::vector<std::string> Split(const std::string& s, char delim) { |
24 | std::string item; |
25 | std::istringstream is(s); |
26 | std::vector<std::string> ret; |
27 | while (std::getline(is, item, delim)) { |
28 | ret.push_back(item); |
29 | } |
30 | return ret; |
31 | } |
32 | |
33 | /*! |
34 | * \brief hash an object and combines the key with previous keys |
35 | */ |
36 | template<typename T> |
37 | inline size_t HashCombine(size_t key, const T& value) { |
38 | std::hash<T> hash_func; |
39 | return key ^ (hash_func(value) + 0x9e3779b9 + (key << 6) + (key >> 2)); |
40 | } |
41 | |
42 | /*! |
43 | * \brief specialize for size_t |
44 | */ |
45 | template<> |
46 | inline size_t HashCombine<size_t>(size_t key, const size_t& value) { |
47 | return key ^ (value + 0x9e3779b9 + (key << 6) + (key >> 2)); |
48 | } |
49 | |
50 | /*! |
51 | * \brief OMP Exception class catches, saves and rethrows exception from OMP blocks |
52 | */ |
53 | class OMPException { |
54 | private: |
55 | // exception_ptr member to store the exception |
56 | std::exception_ptr omp_exception_; |
57 | // mutex to be acquired during catch to set the exception_ptr |
58 | std::mutex mutex_; |
59 | |
60 | public: |
61 | /*! |
62 | * \brief Parallel OMP blocks should be placed within Run to save exception |
63 | */ |
64 | template <typename Function, typename... Parameters> |
65 | void Run(Function f, Parameters... params) { |
66 | try { |
67 | f(params...); |
68 | } catch (dmlc::Error &ex) { |
69 | std::lock_guard<std::mutex> lock(mutex_); |
70 | if (!omp_exception_) { |
71 | omp_exception_ = std::current_exception(); |
72 | } |
73 | } catch (std::exception &ex) { |
74 | std::lock_guard<std::mutex> lock(mutex_); |
75 | if (!omp_exception_) { |
76 | omp_exception_ = std::current_exception(); |
77 | } |
78 | } |
79 | } |
80 | |
81 | /*! |
82 | * \brief should be called from the main thread to rethrow the exception |
83 | */ |
84 | void Rethrow() { |
85 | if (this->omp_exception_) std::rethrow_exception(this->omp_exception_); |
86 | } |
87 | }; |
88 | |
89 | } // namespace dmlc |
90 | |
91 | #endif // DMLC_COMMON_H_ |
92 | |