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/VTask.hh" << 33 #include "Globals.hh" 34 #include "PTL/detail/CxxBackports.hh" << 34 #include "VTask.hh" 35 35 36 #include <cstdint> 36 #include <cstdint> 37 #include <future> << 37 #include <functional> 38 #include <tuple> << 38 #include <stdexcept> 39 #include <utility> << 40 39 41 namespace PTL 40 namespace PTL 42 { 41 { >> 42 class ThreadPool; >> 43 43 //============================================ 44 //======================================================================================// 44 45 45 /// \brief The task class is supplied to threa 46 /// \brief The task class is supplied to thread_pool. 46 template <typename RetT> 47 template <typename RetT> 47 class TaskFuture : public VTask 48 class TaskFuture : public VTask 48 { 49 { 49 public: 50 public: 50 using promise_type = std::promise<RetT>; << 51 typedef std::promise<RetT> promise_type; 51 using future_type = std::future<RetT>; << 52 typedef std::future<RetT> future_type; 52 using result_type = RetT; << 53 typedef RetT result_type; 53 54 54 public: 55 public: 55 // pass a free function pointer 56 // pass a free function pointer 56 template <typename... Args> 57 template <typename... Args> 57 TaskFuture(Args&&... args) 58 TaskFuture(Args&&... args) 58 : VTask{ std::forward<Args>(args)... } 59 : VTask{ std::forward<Args>(args)... } 59 {} 60 {} 60 61 61 ~TaskFuture() override = default; << 62 virtual ~TaskFuture() = default; 62 63 63 TaskFuture(const TaskFuture&) = delete; 64 TaskFuture(const TaskFuture&) = delete; 64 TaskFuture& operator=(const TaskFuture&) = 65 TaskFuture& operator=(const TaskFuture&) = delete; 65 66 66 TaskFuture(TaskFuture&&) noexcept = defaul << 67 TaskFuture(TaskFuture&&) = default; 67 TaskFuture& operator=(TaskFuture&&) noexce << 68 TaskFuture& operator=(TaskFuture&&) = default; 68 69 69 public: 70 public: 70 // execution operator 71 // execution operator 71 virtual future_type get_future() = 0; 72 virtual future_type get_future() = 0; 72 virtual void wait() = 0; 73 virtual void wait() = 0; 73 virtual RetT get() = 0; 74 virtual RetT get() = 0; 74 }; 75 }; 75 76 76 //============================================ 77 //======================================================================================// 77 78 78 /// \brief The task class is supplied to threa 79 /// \brief The task class is supplied to thread_pool. 79 template <typename RetT, typename... Args> 80 template <typename RetT, typename... Args> 80 class PackagedTask : public TaskFuture<RetT> 81 class PackagedTask : public TaskFuture<RetT> 81 { 82 { 82 public: 83 public: 83 using this_type = PackagedTask<Re << 84 typedef PackagedTask<RetT, Args...> this_type; 84 using promise_type = std::promise<Re << 85 typedef std::promise<RetT> promise_type; 85 using future_type = std::future<Ret << 86 typedef std::future<RetT> future_type; 86 using packaged_task_type = std::packaged_t << 87 typedef std::packaged_task<RetT(Args...)> packaged_task_type; 87 using result_type = RetT; << 88 typedef RetT result_type; 88 using tuple_type = std::tuple<Args << 89 typedef std::tuple<Args...> tuple_type; 89 90 90 public: 91 public: 91 // pass a free function pointer 92 // pass a free function pointer 92 template <typename FuncT> 93 template <typename FuncT> 93 PackagedTask(FuncT func, Args... args) 94 PackagedTask(FuncT func, Args... args) 94 : TaskFuture<RetT>{ true, 0 } 95 : TaskFuture<RetT>{ true, 0 } 95 , m_ptask{ std::move(func) } 96 , m_ptask{ std::move(func) } 96 , m_args{ args... } 97 , m_args{ args... } 97 {} 98 {} 98 99 99 template <typename FuncT> 100 template <typename FuncT> 100 PackagedTask(bool _is_native, intmax_t _de 101 PackagedTask(bool _is_native, intmax_t _depth, FuncT func, Args... args) 101 : TaskFuture<RetT>{ _is_native, _depth } 102 : TaskFuture<RetT>{ _is_native, _depth } 102 , m_ptask{ std::move(func) } 103 , m_ptask{ std::move(func) } 103 , m_args{ args... } 104 , m_args{ args... } 104 {} 105 {} 105 106 106 ~PackagedTask() override = default; << 107 virtual ~PackagedTask() = default; 107 108 108 PackagedTask(const PackagedTask&) = delete 109 PackagedTask(const PackagedTask&) = delete; 109 PackagedTask& operator=(const PackagedTask 110 PackagedTask& operator=(const PackagedTask&) = delete; 110 111 111 PackagedTask(PackagedTask&&) noexcept = de << 112 PackagedTask(PackagedTask&&) = default; 112 PackagedTask& operator=(PackagedTask&&) no << 113 PackagedTask& operator=(PackagedTask&&) = default; 113 114 114 public: 115 public: 115 // execution operator 116 // execution operator 116 void operator()() final { PTL::appl << 117 virtual void operator()() final { mpl::apply(std::move(m_ptask), std::move(m_args)); } 117 future_type get_future() final { return m_ << 118 virtual future_type get_future() final { return m_ptask.get_future(); } 118 void wait() final { return m_ptask. << 119 virtual void wait() final { return m_ptask.get_future().wait(); } 119 RetT get() final { return m_ptask.g << 120 virtual RetT get() final { return m_ptask.get_future().get(); } 120 121 121 private: 122 private: 122 packaged_task_type m_ptask; 123 packaged_task_type m_ptask; 123 tuple_type m_args; 124 tuple_type m_args; 124 }; 125 }; 125 126 126 //============================================ 127 //======================================================================================// 127 128 128 /// \brief The task class is supplied to threa 129 /// \brief The task class is supplied to thread_pool. 129 template <typename RetT, typename... Args> 130 template <typename RetT, typename... Args> 130 class Task : public TaskFuture<RetT> 131 class Task : public TaskFuture<RetT> 131 { 132 { 132 public: 133 public: 133 using this_type = Task<RetT, Args << 134 typedef Task<RetT, Args...> this_type; 134 using promise_type = std::promise<Re << 135 typedef std::promise<RetT> promise_type; 135 using future_type = std::future<Ret << 136 typedef std::future<RetT> future_type; 136 using packaged_task_type = std::packaged_t << 137 typedef std::packaged_task<RetT(Args...)> packaged_task_type; 137 using result_type = RetT; << 138 typedef RetT result_type; 138 using tuple_type = std::tuple<Args << 139 typedef std::tuple<Args...> tuple_type; 139 140 140 public: 141 public: 141 template <typename FuncT> 142 template <typename FuncT> 142 Task(FuncT func, Args... args) 143 Task(FuncT func, Args... args) 143 : TaskFuture<RetT>{} 144 : TaskFuture<RetT>{} 144 , m_ptask{ std::move(func) } 145 , m_ptask{ std::move(func) } 145 , m_args{ args... } 146 , m_args{ args... } 146 {} 147 {} 147 148 148 template <typename FuncT> 149 template <typename FuncT> 149 Task(bool _is_native, intmax_t _depth, Fun 150 Task(bool _is_native, intmax_t _depth, FuncT func, Args... args) 150 : TaskFuture<RetT>{ _is_native, _depth } 151 : TaskFuture<RetT>{ _is_native, _depth } 151 , m_ptask{ std::move(func) } 152 , m_ptask{ std::move(func) } 152 , m_args{ args... } 153 , m_args{ args... } 153 {} 154 {} 154 155 155 ~Task() override = default; << 156 virtual ~Task() = default; 156 157 157 Task(const Task&) = delete; 158 Task(const Task&) = delete; 158 Task& operator=(const Task&) = delete; 159 Task& operator=(const Task&) = delete; 159 160 160 Task(Task&&) noexcept = default; << 161 Task(Task&&) = default; 161 Task& operator=(Task&&) noexcept = default << 162 Task& operator=(Task&&) = default; 162 163 163 public: 164 public: 164 // execution operator 165 // execution operator 165 void operator()() final << 166 virtual void operator()() final 166 { 167 { 167 if(m_ptask.valid()) 168 if(m_ptask.valid()) 168 PTL::apply(std::move(m_ptask), std << 169 mpl::apply(std::move(m_ptask), std::move(m_args)); 169 } 170 } 170 future_type get_future() final { return m_ << 171 virtual future_type get_future() final { return m_ptask.get_future(); } 171 void wait() final { return m_ptask. << 172 virtual void wait() final { return m_ptask.get_future().wait(); } 172 RetT get() final { return m_ptask.g << 173 virtual RetT get() final { return m_ptask.get_future().get(); } 173 174 174 private: 175 private: 175 packaged_task_type m_ptask{}; 176 packaged_task_type m_ptask{}; 176 tuple_type m_args{}; 177 tuple_type m_args{}; 177 }; 178 }; 178 179 179 //============================================ 180 //======================================================================================// 180 181 181 /// \brief The task class is supplied to threa 182 /// \brief The task class is supplied to thread_pool. 182 template <typename RetT> 183 template <typename RetT> 183 class Task<RetT, void> : public TaskFuture<Ret 184 class Task<RetT, void> : public TaskFuture<RetT> 184 { 185 { 185 public: 186 public: 186 using this_type = Task<RetT>; << 187 typedef Task<RetT> this_type; 187 using promise_type = std::promise<Re << 188 typedef std::promise<RetT> promise_type; 188 using future_type = std::future<Ret << 189 typedef std::future<RetT> future_type; 189 using packaged_task_type = std::packaged_t << 190 typedef std::packaged_task<RetT()> packaged_task_type; 190 using result_type = RetT; << 191 typedef RetT result_type; 191 192 192 public: 193 public: 193 template <typename FuncT> 194 template <typename FuncT> 194 Task(FuncT func) 195 Task(FuncT func) 195 : TaskFuture<RetT>() 196 : TaskFuture<RetT>() 196 , m_ptask{ std::move(func) } 197 , m_ptask{ std::move(func) } 197 {} 198 {} 198 199 199 template <typename FuncT> 200 template <typename FuncT> 200 Task(bool _is_native, intmax_t _depth, Fun 201 Task(bool _is_native, intmax_t _depth, FuncT func) 201 : TaskFuture<RetT>{ _is_native, _depth } 202 : TaskFuture<RetT>{ _is_native, _depth } 202 , m_ptask{ std::move(func) } 203 , m_ptask{ std::move(func) } 203 {} 204 {} 204 205 205 virtual ~Task() = default; 206 virtual ~Task() = default; 206 207 207 Task(const Task&) = delete; 208 Task(const Task&) = delete; 208 Task& operator=(const Task&) = delete; 209 Task& operator=(const Task&) = delete; 209 210 210 Task(Task&&) noexcept = default; << 211 Task(Task&&) = default; 211 Task& operator=(Task&&) noexcept = default << 212 Task& operator=(Task&&) = default; 212 213 213 public: 214 public: 214 // execution operator 215 // execution operator 215 virtual void operator()() final { m 216 virtual void operator()() final { m_ptask(); } 216 virtual future_type get_future() final { r 217 virtual future_type get_future() final { return m_ptask.get_future(); } 217 virtual void wait() final { return 218 virtual void wait() final { return m_ptask.get_future().wait(); } 218 virtual RetT get() final { return m 219 virtual RetT get() final { return m_ptask.get_future().get(); } 219 220 220 private: 221 private: 221 packaged_task_type m_ptask{}; 222 packaged_task_type m_ptask{}; 222 }; 223 }; 223 224 224 //============================================ 225 //======================================================================================// 225 226 226 /// \brief The task class is supplied to threa 227 /// \brief The task class is supplied to thread_pool. 227 template <> 228 template <> 228 class Task<void, void> : public TaskFuture<voi 229 class Task<void, void> : public TaskFuture<void> 229 { 230 { 230 public: 231 public: 231 using RetT = void; << 232 typedef void RetT; 232 using this_type = Task<void, void << 233 typedef Task<void, void> this_type; 233 using promise_type = std::promise<Re << 234 typedef std::promise<RetT> promise_type; 234 using future_type = std::future<Ret << 235 typedef std::future<RetT> future_type; 235 using packaged_task_type = std::packaged_t << 236 typedef std::packaged_task<RetT()> packaged_task_type; 236 using result_type = RetT; << 237 typedef RetT result_type; 237 238 238 public: 239 public: 239 template <typename FuncT> 240 template <typename FuncT> 240 explicit Task(FuncT func) 241 explicit Task(FuncT func) 241 : TaskFuture<RetT>{} 242 : TaskFuture<RetT>{} 242 , m_ptask{ std::move(func) } 243 , m_ptask{ std::move(func) } 243 {} 244 {} 244 245 245 template <typename FuncT> 246 template <typename FuncT> 246 Task(bool _is_native, intmax_t _depth, Fun 247 Task(bool _is_native, intmax_t _depth, FuncT func) 247 : TaskFuture<RetT>{ _is_native, _depth } 248 : TaskFuture<RetT>{ _is_native, _depth } 248 , m_ptask{ std::move(func) } 249 , m_ptask{ std::move(func) } 249 {} 250 {} 250 251 251 ~Task() override = default; << 252 virtual ~Task() = default; 252 253 253 Task(const Task&) = delete; 254 Task(const Task&) = delete; 254 Task& operator=(const Task&) = delete; 255 Task& operator=(const Task&) = delete; 255 256 256 Task(Task&&) = default; 257 Task(Task&&) = default; 257 Task& operator=(Task&&) = default; 258 Task& operator=(Task&&) = default; 258 259 259 public: 260 public: 260 // execution operator 261 // execution operator 261 void operator()() final { m_ptask() << 262 virtual void operator()() final { m_ptask(); } 262 future_type get_future() final { return m_ << 263 virtual future_type get_future() final { return m_ptask.get_future(); } 263 void wait() final { return m_ptask. << 264 virtual void wait() final { return m_ptask.get_future().wait(); } 264 RetT get() final { return m_ptask.g << 265 virtual RetT get() final { return m_ptask.get_future().get(); } 265 266 266 private: 267 private: 267 packaged_task_type m_ptask{}; 268 packaged_task_type m_ptask{}; 268 }; 269 }; 269 270 270 //============================================ 271 //======================================================================================// 271 272 272 } // namespace PTL 273 } // namespace PTL 273 274