Geant4 Cross Reference |
1 // 1 // 2 // MIT License 2 // MIT License 3 // Copyright (c) 2020 Jonathan R. Madsen 3 // Copyright (c) 2020 Jonathan R. Madsen 4 // Permission is hereby granted, free of charg 4 // Permission is hereby granted, free of charge, to any person obtaining a copy 5 // of this software and associated documentati 5 // of this software and associated documentation files (the "Software"), to deal 6 // in the Software without restriction, includ 6 // in the Software without restriction, including without limitation the rights 7 // to use, copy, modify, merge, publish, distr 7 // to use, copy, modify, merge, publish, distribute, sublicense, and 8 // copies of the Software, and to permit perso 8 // copies of the Software, and to permit persons to whom the Software is 9 // furnished to do so, subject to the followin 9 // furnished to do so, subject to the following conditions: 10 // The above copyright notice and this permiss 10 // The above copyright notice and this permission notice shall be included in 11 // all copies or substantial portions of the S 11 // all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED 12 // "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPR 12 // "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT 13 // LIMITED TO THE WARRANTIES OF MERCHANTABILIT 13 // LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR 14 // PURPOSE AND NONINFRINGEMENT. IN NO EVENT SH 14 // PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT 15 // HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR 15 // HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN 16 // ACTION OF CONTRACT, TORT OR OTHERWISE, ARIS 16 // ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 17 // WITH THE SOFTWARE OR THE USE OR OTHER DEALI 17 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 18 // 18 // 19 // 19 // 20 // ------------------------------------------- 20 // --------------------------------------------------------------- 21 // Tasking class header file 21 // Tasking class header file 22 // 22 // 23 // Class Description: 23 // Class Description: 24 // 24 // 25 // This file defines the task types for TaskMa 25 // This file defines the task types for TaskManager and ThreadPool 26 // 26 // 27 // ------------------------------------------- 27 // --------------------------------------------------------------- 28 // Author: Jonathan Madsen (Feb 13th 2018) 28 // Author: Jonathan Madsen (Feb 13th 2018) 29 // ------------------------------------------- 29 // --------------------------------------------------------------- 30 30 31 #pragma once 31 #pragma once 32 32 >> 33 #include "PTL/Globals.hh" 33 #include "PTL/VTask.hh" 34 #include "PTL/VTask.hh" 34 #include "PTL/detail/CxxBackports.hh" << 35 35 36 #include <cstdint> 36 #include <cstdint> 37 #include <future> 37 #include <future> 38 #include <tuple> 38 #include <tuple> 39 #include <utility> 39 #include <utility> 40 40 41 namespace PTL 41 namespace PTL 42 { 42 { 43 //============================================ 43 //======================================================================================// 44 44 45 /// \brief The task class is supplied to threa 45 /// \brief The task class is supplied to thread_pool. 46 template <typename RetT> 46 template <typename RetT> 47 class TaskFuture : public VTask 47 class TaskFuture : public VTask 48 { 48 { 49 public: 49 public: 50 using promise_type = std::promise<RetT>; 50 using promise_type = std::promise<RetT>; 51 using future_type = std::future<RetT>; 51 using future_type = std::future<RetT>; 52 using result_type = RetT; 52 using result_type = RetT; 53 53 54 public: 54 public: 55 // pass a free function pointer 55 // pass a free function pointer 56 template <typename... Args> 56 template <typename... Args> 57 TaskFuture(Args&&... args) 57 TaskFuture(Args&&... args) 58 : VTask{ std::forward<Args>(args)... } 58 : VTask{ std::forward<Args>(args)... } 59 {} 59 {} 60 60 61 ~TaskFuture() override = default; 61 ~TaskFuture() override = default; 62 62 63 TaskFuture(const TaskFuture&) = delete; 63 TaskFuture(const TaskFuture&) = delete; 64 TaskFuture& operator=(const TaskFuture&) = 64 TaskFuture& operator=(const TaskFuture&) = delete; 65 65 66 TaskFuture(TaskFuture&&) noexcept = defaul 66 TaskFuture(TaskFuture&&) noexcept = default; 67 TaskFuture& operator=(TaskFuture&&) noexce 67 TaskFuture& operator=(TaskFuture&&) noexcept = default; 68 68 69 public: 69 public: 70 // execution operator 70 // execution operator 71 virtual future_type get_future() = 0; 71 virtual future_type get_future() = 0; 72 virtual void wait() = 0; 72 virtual void wait() = 0; 73 virtual RetT get() = 0; 73 virtual RetT get() = 0; 74 }; 74 }; 75 75 76 //============================================ 76 //======================================================================================// 77 77 78 /// \brief The task class is supplied to threa 78 /// \brief The task class is supplied to thread_pool. 79 template <typename RetT, typename... Args> 79 template <typename RetT, typename... Args> 80 class PackagedTask : public TaskFuture<RetT> 80 class PackagedTask : public TaskFuture<RetT> 81 { 81 { 82 public: 82 public: 83 using this_type = PackagedTask<Re 83 using this_type = PackagedTask<RetT, Args...>; 84 using promise_type = std::promise<Re 84 using promise_type = std::promise<RetT>; 85 using future_type = std::future<Ret 85 using future_type = std::future<RetT>; 86 using packaged_task_type = std::packaged_t 86 using packaged_task_type = std::packaged_task<RetT(Args...)>; 87 using result_type = RetT; 87 using result_type = RetT; 88 using tuple_type = std::tuple<Args 88 using tuple_type = std::tuple<Args...>; 89 89 90 public: 90 public: 91 // pass a free function pointer 91 // pass a free function pointer 92 template <typename FuncT> 92 template <typename FuncT> 93 PackagedTask(FuncT func, Args... args) 93 PackagedTask(FuncT func, Args... args) 94 : TaskFuture<RetT>{ true, 0 } 94 : TaskFuture<RetT>{ true, 0 } 95 , m_ptask{ std::move(func) } 95 , m_ptask{ std::move(func) } 96 , m_args{ args... } 96 , m_args{ args... } 97 {} 97 {} 98 98 99 template <typename FuncT> 99 template <typename FuncT> 100 PackagedTask(bool _is_native, intmax_t _de 100 PackagedTask(bool _is_native, intmax_t _depth, FuncT func, Args... args) 101 : TaskFuture<RetT>{ _is_native, _depth } 101 : TaskFuture<RetT>{ _is_native, _depth } 102 , m_ptask{ std::move(func) } 102 , m_ptask{ std::move(func) } 103 , m_args{ args... } 103 , m_args{ args... } 104 {} 104 {} 105 105 106 ~PackagedTask() override = default; 106 ~PackagedTask() override = default; 107 107 108 PackagedTask(const PackagedTask&) = delete 108 PackagedTask(const PackagedTask&) = delete; 109 PackagedTask& operator=(const PackagedTask 109 PackagedTask& operator=(const PackagedTask&) = delete; 110 110 111 PackagedTask(PackagedTask&&) noexcept = de 111 PackagedTask(PackagedTask&&) noexcept = default; 112 PackagedTask& operator=(PackagedTask&&) no 112 PackagedTask& operator=(PackagedTask&&) noexcept = default; 113 113 114 public: 114 public: 115 // execution operator 115 // execution operator 116 void operator()() final { PTL::appl << 116 void operator()() final { mpl::apply(std::move(m_ptask), std::move(m_args)); } 117 future_type get_future() final { return m_ 117 future_type get_future() final { return m_ptask.get_future(); } 118 void wait() final { return m_ptask. 118 void wait() final { return m_ptask.get_future().wait(); } 119 RetT get() final { return m_ptask.g 119 RetT get() final { return m_ptask.get_future().get(); } 120 120 121 private: 121 private: 122 packaged_task_type m_ptask; 122 packaged_task_type m_ptask; 123 tuple_type m_args; 123 tuple_type m_args; 124 }; 124 }; 125 125 126 //============================================ 126 //======================================================================================// 127 127 128 /// \brief The task class is supplied to threa 128 /// \brief The task class is supplied to thread_pool. 129 template <typename RetT, typename... Args> 129 template <typename RetT, typename... Args> 130 class Task : public TaskFuture<RetT> 130 class Task : public TaskFuture<RetT> 131 { 131 { 132 public: 132 public: 133 using this_type = Task<RetT, Args 133 using this_type = Task<RetT, Args...>; 134 using promise_type = std::promise<Re 134 using promise_type = std::promise<RetT>; 135 using future_type = std::future<Ret 135 using future_type = std::future<RetT>; 136 using packaged_task_type = std::packaged_t 136 using packaged_task_type = std::packaged_task<RetT(Args...)>; 137 using result_type = RetT; 137 using result_type = RetT; 138 using tuple_type = std::tuple<Args 138 using tuple_type = std::tuple<Args...>; 139 139 140 public: 140 public: 141 template <typename FuncT> 141 template <typename FuncT> 142 Task(FuncT func, Args... args) 142 Task(FuncT func, Args... args) 143 : TaskFuture<RetT>{} 143 : TaskFuture<RetT>{} 144 , m_ptask{ std::move(func) } 144 , m_ptask{ std::move(func) } 145 , m_args{ args... } 145 , m_args{ args... } 146 {} 146 {} 147 147 148 template <typename FuncT> 148 template <typename FuncT> 149 Task(bool _is_native, intmax_t _depth, Fun 149 Task(bool _is_native, intmax_t _depth, FuncT func, Args... args) 150 : TaskFuture<RetT>{ _is_native, _depth } 150 : TaskFuture<RetT>{ _is_native, _depth } 151 , m_ptask{ std::move(func) } 151 , m_ptask{ std::move(func) } 152 , m_args{ args... } 152 , m_args{ args... } 153 {} 153 {} 154 154 155 ~Task() override = default; 155 ~Task() override = default; 156 156 157 Task(const Task&) = delete; 157 Task(const Task&) = delete; 158 Task& operator=(const Task&) = delete; 158 Task& operator=(const Task&) = delete; 159 159 160 Task(Task&&) noexcept = default; 160 Task(Task&&) noexcept = default; 161 Task& operator=(Task&&) noexcept = default 161 Task& operator=(Task&&) noexcept = default; 162 162 163 public: 163 public: 164 // execution operator 164 // execution operator 165 void operator()() final 165 void operator()() final 166 { 166 { 167 if(m_ptask.valid()) 167 if(m_ptask.valid()) 168 PTL::apply(std::move(m_ptask), std << 168 mpl::apply(std::move(m_ptask), std::move(m_args)); 169 } 169 } 170 future_type get_future() final { return m_ 170 future_type get_future() final { return m_ptask.get_future(); } 171 void wait() final { return m_ptask. 171 void wait() final { return m_ptask.get_future().wait(); } 172 RetT get() final { return m_ptask.g 172 RetT get() final { return m_ptask.get_future().get(); } 173 173 174 private: 174 private: 175 packaged_task_type m_ptask{}; 175 packaged_task_type m_ptask{}; 176 tuple_type m_args{}; 176 tuple_type m_args{}; 177 }; 177 }; 178 178 179 //============================================ 179 //======================================================================================// 180 180 181 /// \brief The task class is supplied to threa 181 /// \brief The task class is supplied to thread_pool. 182 template <typename RetT> 182 template <typename RetT> 183 class Task<RetT, void> : public TaskFuture<Ret 183 class Task<RetT, void> : public TaskFuture<RetT> 184 { 184 { 185 public: 185 public: 186 using this_type = Task<RetT>; 186 using this_type = Task<RetT>; 187 using promise_type = std::promise<Re 187 using promise_type = std::promise<RetT>; 188 using future_type = std::future<Ret 188 using future_type = std::future<RetT>; 189 using packaged_task_type = std::packaged_t 189 using packaged_task_type = std::packaged_task<RetT()>; 190 using result_type = RetT; 190 using result_type = RetT; 191 191 192 public: 192 public: 193 template <typename FuncT> 193 template <typename FuncT> 194 Task(FuncT func) 194 Task(FuncT func) 195 : TaskFuture<RetT>() 195 : TaskFuture<RetT>() 196 , m_ptask{ std::move(func) } 196 , m_ptask{ std::move(func) } 197 {} 197 {} 198 198 199 template <typename FuncT> 199 template <typename FuncT> 200 Task(bool _is_native, intmax_t _depth, Fun 200 Task(bool _is_native, intmax_t _depth, FuncT func) 201 : TaskFuture<RetT>{ _is_native, _depth } 201 : TaskFuture<RetT>{ _is_native, _depth } 202 , m_ptask{ std::move(func) } 202 , m_ptask{ std::move(func) } 203 {} 203 {} 204 204 205 virtual ~Task() = default; 205 virtual ~Task() = default; 206 206 207 Task(const Task&) = delete; 207 Task(const Task&) = delete; 208 Task& operator=(const Task&) = delete; 208 Task& operator=(const Task&) = delete; 209 209 210 Task(Task&&) noexcept = default; 210 Task(Task&&) noexcept = default; 211 Task& operator=(Task&&) noexcept = default 211 Task& operator=(Task&&) noexcept = default; 212 212 213 public: 213 public: 214 // execution operator 214 // execution operator 215 virtual void operator()() final { m 215 virtual void operator()() final { m_ptask(); } 216 virtual future_type get_future() final { r 216 virtual future_type get_future() final { return m_ptask.get_future(); } 217 virtual void wait() final { return 217 virtual void wait() final { return m_ptask.get_future().wait(); } 218 virtual RetT get() final { return m 218 virtual RetT get() final { return m_ptask.get_future().get(); } 219 219 220 private: 220 private: 221 packaged_task_type m_ptask{}; 221 packaged_task_type m_ptask{}; 222 }; 222 }; 223 223 224 //============================================ 224 //======================================================================================// 225 225 226 /// \brief The task class is supplied to threa 226 /// \brief The task class is supplied to thread_pool. 227 template <> 227 template <> 228 class Task<void, void> : public TaskFuture<voi 228 class Task<void, void> : public TaskFuture<void> 229 { 229 { 230 public: 230 public: 231 using RetT = void; 231 using RetT = void; 232 using this_type = Task<void, void 232 using this_type = Task<void, void>; 233 using promise_type = std::promise<Re 233 using promise_type = std::promise<RetT>; 234 using future_type = std::future<Ret 234 using future_type = std::future<RetT>; 235 using packaged_task_type = std::packaged_t 235 using packaged_task_type = std::packaged_task<RetT()>; 236 using result_type = RetT; 236 using result_type = RetT; 237 237 238 public: 238 public: 239 template <typename FuncT> 239 template <typename FuncT> 240 explicit Task(FuncT func) 240 explicit Task(FuncT func) 241 : TaskFuture<RetT>{} 241 : TaskFuture<RetT>{} 242 , m_ptask{ std::move(func) } 242 , m_ptask{ std::move(func) } 243 {} 243 {} 244 244 245 template <typename FuncT> 245 template <typename FuncT> 246 Task(bool _is_native, intmax_t _depth, Fun 246 Task(bool _is_native, intmax_t _depth, FuncT func) 247 : TaskFuture<RetT>{ _is_native, _depth } 247 : TaskFuture<RetT>{ _is_native, _depth } 248 , m_ptask{ std::move(func) } 248 , m_ptask{ std::move(func) } 249 {} 249 {} 250 250 251 ~Task() override = default; 251 ~Task() override = default; 252 252 253 Task(const Task&) = delete; 253 Task(const Task&) = delete; 254 Task& operator=(const Task&) = delete; 254 Task& operator=(const Task&) = delete; 255 255 256 Task(Task&&) = default; 256 Task(Task&&) = default; 257 Task& operator=(Task&&) = default; 257 Task& operator=(Task&&) = default; 258 258 259 public: 259 public: 260 // execution operator 260 // execution operator 261 void operator()() final { m_ptask() 261 void operator()() final { m_ptask(); } 262 future_type get_future() final { return m_ 262 future_type get_future() final { return m_ptask.get_future(); } 263 void wait() final { return m_ptask. 263 void wait() final { return m_ptask.get_future().wait(); } 264 RetT get() final { return m_ptask.g 264 RetT get() final { return m_ptask.get_future().get(); } 265 265 266 private: 266 private: 267 packaged_task_type m_ptask{}; 267 packaged_task_type m_ptask{}; 268 }; 268 }; 269 269 270 //============================================ 270 //======================================================================================// 271 271 272 } // namespace PTL 272 } // namespace PTL 273 273