Turi Create  4.0
execute_task_in_native_thread.hpp
1 /* Copyright © 2017 Apple Inc. All rights reserved.
2  *
3  * Use of this source code is governed by a BSD-3-clause license that can
4  * be found in the LICENSE.txt file or at https://opensource.org/licenses/BSD-3-Clause
5  */
6 #ifndef TURI_PARALLEL_EXECUTE_TASK_IN_NATIVE_THREAD_HPP
7 #define TURI_PARALLEL_EXECUTE_TASK_IN_NATIVE_THREAD_HPP
8 #include <functional>
9 
10 namespace turi {
11 
12 /**
13  * Takes a function and executes it in a native stack space.
14  * Used to get by some libjvm oddities when using coroutines.
15  *
16  * Returns an exception if an exception was thrown while executing the inner task.
17  * \ingroup threading
18  */
19 std::exception_ptr execute_task_in_native_thread(const std::function<void(void)>& fn);
20 
21 namespace native_exec_task_impl {
22 template <typename T>
23 struct value_type {
24  T ret;
25 
26  T get_result() {
27  return ret;
28  }
29 
30  template <typename F, typename A1>
31  void run_as_native(F f, A1 a1) {
32  auto except = execute_task_in_native_thread([&](void)->void {
33  ret = f(a1);
34  });
35  if (except) std::rethrow_exception(except);
36  }
37 
38  template <typename F, typename A1, typename A2>
39  void run_as_native(F f, A1 a1, A2 a2) {
40  auto except = execute_task_in_native_thread([&](void)->void {
41  ret = f(a1, a2);
42  });
43  if (except) std::rethrow_exception(except);
44  }
45 
46  template <typename F, typename A1, typename A2, typename A3>
47  void run_as_native(F f, A1 a1, A2 a2, A3 a3) {
48  auto except = execute_task_in_native_thread([&](void)->void {
49  ret = f(a1, a2, a3);
50  });
51  if (except) std::rethrow_exception(except);
52  }
53 
54  template <typename F, typename A1, typename A2, typename A3, typename A4>
55  void run_as_native(F f, A1 a1, A2 a2, A3 a3, A4 a4) {
56  auto except = execute_task_in_native_thread([&](void)->void {
57  ret = f(a1, a2, a3, a4);
58  });
59  if (except) std::rethrow_exception(except);
60  }
61 
62  template <typename F, typename A1, typename A2, typename A3, typename A4, typename A5>
63  void run_as_native(F f, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5) {
64  auto except = execute_task_in_native_thread([&](void)->void {
65  ret = f(a1, a2, a3, a4, a5);
66  });
67  if (except) std::rethrow_exception(except);
68  }
69 
70  template <typename F, typename A1, typename A2, typename A3, typename A4, typename A5, typename A6>
71  void run_as_native(F f, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6) {
72  auto except = execute_task_in_native_thread([&](void)->void {
73  ret = f(a1, a2, a3, a4, a5, a6);
74  });
75  if (except) std::rethrow_exception(except);
76  }
77 
78  template <typename F, typename A1, typename A2, typename A3, typename A4, typename A5, typename A6, typename A7>
79  void run_as_native(F f, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6, A7 a7) {
80  auto except = execute_task_in_native_thread([&](void)->void {
81  ret = f(a1, a2, a3, a4, a5, a6, a7);
82  });
83  if (except) std::rethrow_exception(except);
84  }
85 };
86 
87 template <>
88 struct value_type<void> {
89 
90  void get_result() { }
91 
92  template <typename F, typename A1>
93  void run_as_native(F f, A1 a1) {
94  auto except = execute_task_in_native_thread([&](void)->void {
95  f(a1);
96  });
97  if (except) std::rethrow_exception(except);
98  }
99 
100  template <typename F, typename A1, typename A2>
101  void run_as_native(F f, A1 a1, A2 a2) {
102  auto except = execute_task_in_native_thread([&](void)->void {
103  f(a1, a2);
104  });
105  if (except) std::rethrow_exception(except);
106  }
107 
108  template <typename F, typename A1, typename A2, typename A3>
109  void run_as_native(F f, A1 a1, A2 a2, A3 a3) {
110  auto except = execute_task_in_native_thread([&](void)->void {
111  f(a1, a2, a3);
112  });
113  if (except) std::rethrow_exception(except);
114  }
115 
116  template <typename F, typename A1, typename A2, typename A3, typename A4>
117  void run_as_native(F f, A1 a1, A2 a2, A3 a3, A4 a4) {
118  auto except = execute_task_in_native_thread([&](void)->void {
119  f(a1, a2, a3, a4);
120  });
121  if (except) std::rethrow_exception(except);
122  }
123 
124  template <typename F, typename A1, typename A2, typename A3, typename A4, typename A5>
125  void run_as_native(F f, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5) {
126  auto except = execute_task_in_native_thread([&](void)->void {
127  f(a1, a2, a3, a4, a5);
128  });
129  if (except) std::rethrow_exception(except);
130  }
131 
132  template <typename F, typename A1, typename A2, typename A3, typename A4, typename A5, typename A6>
133  void run_as_native(F f, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6) {
134  auto except = execute_task_in_native_thread([&](void)->void {
135  f(a1, a2, a3, a4, a5, a6);
136  });
137  if (except) std::rethrow_exception(except);
138  }
139 
140  template <typename F, typename A1, typename A2, typename A3, typename A4, typename A5, typename A6, typename A7>
141  void run_as_native(F f, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6, A7 a7) {
142  auto except = execute_task_in_native_thread([&](void)->void {
143  f(a1, a2, a3, a4, a5, a6, a7);
144  });
145  if (except) std::rethrow_exception(except);
146  }
147 };
148 } // namespace native_exec_task_impl
149 /**
150  * Takes a function call and runs it in a native stack space.
151  * Used to get by some libjvm oddities when using coroutines.
152  *
153  * Returns an exception if an exception was thrown while executing the inner task.
154  */
155 template <typename F, typename ... Args>
156 typename std::result_of<F(Args...)>::type run_as_native(F f, Args... args) {
157  native_exec_task_impl::value_type<typename std::result_of<F(Args...)>::type> result;
158 
159  result.template run_as_native<F, Args...>(f, args...);
160 
161  return result.get_result();
162 }
163 
164 } // turicreate
165 #endif
std::exception_ptr execute_task_in_native_thread(const std::function< void(void)> &fn)
std::result_of< F(Args...)>::type run_as_native(F f, Args... args)