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 // Tasking class header file 21 // 22 // Class Description: 23 // 24 // This file creates a class for handling the wrapping of functions 25 // into task objects and submitting to thread pool 26 // 27 // --------------------------------------------------------------- 28 // Author: Jonathan Madsen (Feb 13th 2018) 29 // --------------------------------------------------------------- 30 31 #pragma once 32 33 #include "PTL/Macros.hh" 34 #include "PTL/Task.hh" 35 #include "PTL/TaskGroup.hh" 36 #include "PTL/ThreadPool.hh" 37 38 #include <iostream> 39 #include <memory> 40 #include <stdexcept> 41 #include <thread> 42 #include <utility> 43 44 namespace PTL 45 { 46 //======================================================================================// 47 48 class TaskManager 49 { 50 public: 51 using this_type = TaskManager; 52 using size_type = ThreadPool::size_type; 53 54 public: 55 // Constructor and Destructors 56 explicit TaskManager(ThreadPool*, bool _manage_pool = true); 57 virtual ~TaskManager() noexcept(false); 58 59 TaskManager(const TaskManager&) = delete; 60 TaskManager(TaskManager&&) = default; 61 TaskManager& operator=(const TaskManager&) = delete; 62 TaskManager& operator=(TaskManager&&) = default; 63 64 public: 65 /// get the singleton pointer 66 static TaskManager* GetInstance(); 67 static TaskManager* GetInstanceIfExists(); 68 static unsigned ncores() { return std::thread::hardware_concurrency(); } 69 70 public: 71 //------------------------------------------------------------------------// 72 // return the thread pool 73 inline ThreadPool* thread_pool() const { return m_pool; } 74 75 //------------------------------------------------------------------------// 76 // return the number of threads in the thread pool 77 inline size_type size() const { return (m_pool) ? m_pool->size() : 0; } 78 79 //------------------------------------------------------------------------// 80 // kill all the threads 81 inline void finalize() 82 { 83 if(m_is_finalized) 84 return; 85 m_is_finalized = true; 86 if(m_pool) 87 m_pool->destroy_threadpool(); 88 } 89 //------------------------------------------------------------------------// 90 91 public: 92 //------------------------------------------------------------------------// 93 // direct insertion of a task 94 //------------------------------------------------------------------------// 95 template <typename... Args> 96 void exec(Task<Args...>* _task) 97 { 98 if(!m_pool) 99 throw std::runtime_error("Nullptr to thread-pool"); 100 m_pool->add_task(_task); 101 } 102 103 //------------------------------------------------------------------------// 104 // direct insertion of a packaged_task 105 //------------------------------------------------------------------------// 106 template <typename RetT, typename FuncT, typename... Args> 107 std::shared_ptr<PackagedTask<RetT, Args...>> async(FuncT&& func, Args&&... args) 108 { 109 using task_type = PackagedTask<RetT, Args...>; 110 111 if(!m_pool) 112 throw std::runtime_error("Nullptr to thread-pool"); 113 114 auto _ptask = std::make_shared<task_type>(std::forward<FuncT>(func), 115 std::forward<Args>(args)...); 116 m_pool->add_task(_ptask); 117 return _ptask; 118 } 119 //------------------------------------------------------------------------// 120 template <typename RetT, typename FuncT> 121 std::shared_ptr<PackagedTask<RetT>> async(FuncT&& func) 122 { 123 using task_type = PackagedTask<RetT>; 124 125 if(!m_pool) 126 throw std::runtime_error("Nullptr to thread-pool"); 127 128 auto _ptask = std::make_shared<task_type>(std::forward<FuncT>(func)); 129 m_pool->add_task(_ptask); 130 return _ptask; 131 } 132 //------------------------------------------------------------------------// 133 template <typename FuncT, typename... Args> 134 auto async(FuncT&& func, Args... args) 135 -> std::shared_ptr<PackagedTask<decay_t<decltype(func(args...))>, Args...>> 136 { 137 using RetT = decay_t<decltype(func(args...))>; 138 using task_type = PackagedTask<RetT, Args...>; 139 140 if(!m_pool) 141 throw std::runtime_error("Nullptr to thread-pool"); 142 143 auto _ptask = std::make_shared<task_type>(std::forward<FuncT>(func), 144 std::forward<Args>(args)...); 145 m_pool->add_task(_ptask); 146 return _ptask; 147 } 148 //------------------------------------------------------------------------// 149 150 public: 151 //------------------------------------------------------------------------// 152 // public wrap functions 153 //------------------------------------------------------------------------// 154 template <typename RetT, typename ArgT, typename FuncT, typename... Args> 155 std::shared_ptr<Task<RetT, ArgT, Args...>> wrap(TaskGroup<RetT, ArgT>& tg, 156 FuncT&& func, Args&&... args) 157 { 158 return tg.wrap(std::forward<FuncT>(func), std::forward<Args>(args)...); 159 } 160 //------------------------------------------------------------------------// 161 template <typename RetT, typename ArgT, typename FuncT> 162 std::shared_ptr<Task<RetT, ArgT>> wrap(TaskGroup<RetT, ArgT>& tg, FuncT&& func) 163 { 164 return tg.wrap(std::forward<FuncT>(func)); 165 } 166 167 public: 168 //------------------------------------------------------------------------// 169 // public exec functions 170 //------------------------------------------------------------------------// 171 template <typename RetT, typename ArgT, typename FuncT, typename... Args> 172 void exec(TaskGroup<RetT, ArgT>& tg, FuncT&& func, Args&&... args) 173 { 174 tg.exec(std::forward<FuncT>(func), std::forward<Args>(args)...); 175 } 176 //------------------------------------------------------------------------// 177 template <typename RetT, typename ArgT, typename FuncT> 178 void exec(TaskGroup<RetT, ArgT>& tg, FuncT&& func) 179 { 180 tg.exec(std::forward<FuncT>(func)); 181 } 182 //------------------------------------------------------------------------// 183 template <typename RetT, typename ArgT, typename FuncT, typename... Args> 184 void rexec(TaskGroup<RetT, ArgT>& tg, FuncT&& func, Args&&... args) 185 { 186 tg.exec(std::forward<FuncT>(func), std::forward<Args>(args)...); 187 } 188 //------------------------------------------------------------------------// 189 template <typename RetT, typename ArgT, typename FuncT> 190 void rexec(TaskGroup<RetT, ArgT>& tg, FuncT&& func) 191 { 192 tg.exec(std::forward<FuncT>(func)); 193 } 194 //------------------------------------------------------------------------// 195 // public exec functions (void specializations) 196 //------------------------------------------------------------------------// 197 template <typename FuncT, typename... Args> 198 void rexec(TaskGroup<void, void>& tg, FuncT&& func, Args&&... args) 199 { 200 tg.exec(std::forward<FuncT>(func), std::forward<Args>(args)...); 201 } 202 //------------------------------------------------------------------------// 203 template <typename FuncT> 204 void rexec(TaskGroup<void, void>& tg, FuncT&& func) 205 { 206 tg.exec(std::forward<FuncT>(func)); 207 } 208 //------------------------------------------------------------------------// 209 210 protected: 211 // Protected variables 212 ThreadPool* m_pool = nullptr; 213 bool m_is_finalized = false; 214 215 private: 216 static TaskManager*& fgInstance(); 217 }; 218 219 } // namespace PTL 220 //======================================================================================// 221 222 #include "TaskRunManager.hh" 223 224 //--------------------------------------------------------------------------------------// 225 226 inline PTL::TaskManager*& 227 PTL::TaskManager::fgInstance() 228 { 229 static thread_local TaskManager* _instance = nullptr; 230 return _instance; 231 } 232 233 //--------------------------------------------------------------------------------------// 234 235 inline PTL::TaskManager* 236 PTL::TaskManager::GetInstance() 237 { 238 if(!fgInstance()) 239 { 240 auto nthreads = std::thread::hardware_concurrency(); 241 std::cout << "Allocating mad::TaskManager with " << nthreads << " thread(s)..." 242 << std::endl; 243 new TaskManager(TaskRunManager::GetMasterRunManager()->GetThreadPool()); 244 } 245 return fgInstance(); 246 } 247 248 //--------------------------------------------------------------------------------------// 249 250 inline PTL::TaskManager* 251 PTL::TaskManager::GetInstanceIfExists() 252 { 253 return fgInstance(); 254 } 255 256 //--------------------------------------------------------------------------------------// 257 258 inline PTL::TaskManager::TaskManager(ThreadPool* _pool, bool _manage_pool) 259 : m_pool(_pool) 260 , m_is_finalized(!_manage_pool) 261 { 262 if(!fgInstance()) 263 fgInstance() = this; 264 } 265 266 //--------------------------------------------------------------------------------------// 267 268 inline PTL::TaskManager::~TaskManager() noexcept(false) 269 { 270 finalize(); 271 if(fgInstance() == this) 272 fgInstance() = nullptr; 273 } 274 275 //======================================================================================// 276