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