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
16namespace 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 */
23inline 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 */
36template<typename T>
37inline 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 */
45template<>
46inline 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 */
53class 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