File indexing completed on 2025-01-18 09:57:47
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017
0018
0019
0020
0021
0022
0023
0024
0025
0026
0027
0028
0029
0030
0031 #pragma once
0032
0033 #include "PTL/Globals.hh"
0034 #include "PTL/Task.hh"
0035 #include "PTL/TaskGroup.hh"
0036 #include "PTL/ThreadPool.hh"
0037
0038 #include <iostream>
0039 #include <memory>
0040 #include <stdexcept>
0041 #include <thread>
0042 #include <utility>
0043
0044 namespace PTL
0045 {
0046
0047
0048 class TaskManager
0049 {
0050 public:
0051 using this_type = TaskManager;
0052 using size_type = ThreadPool::size_type;
0053
0054 public:
0055
0056 explicit TaskManager(ThreadPool*, bool _manage_pool = true);
0057 virtual ~TaskManager() noexcept(false);
0058
0059 TaskManager(const TaskManager&) = delete;
0060 TaskManager(TaskManager&&) = default;
0061 TaskManager& operator=(const TaskManager&) = delete;
0062 TaskManager& operator=(TaskManager&&) = default;
0063
0064 public:
0065
0066 static TaskManager* GetInstance();
0067 static TaskManager* GetInstanceIfExists();
0068 static unsigned ncores() { return std::thread::hardware_concurrency(); }
0069
0070 public:
0071
0072
0073 inline ThreadPool* thread_pool() const { return m_pool; }
0074
0075
0076
0077 inline size_type size() const { return (m_pool) ? m_pool->size() : 0; }
0078
0079
0080
0081 inline void finalize()
0082 {
0083 if(m_is_finalized)
0084 return;
0085 m_is_finalized = true;
0086 if(m_pool)
0087 m_pool->destroy_threadpool();
0088 }
0089
0090
0091 public:
0092
0093
0094
0095 template <typename... Args>
0096 void exec(Task<Args...>* _task)
0097 {
0098 if(!m_pool)
0099 throw std::runtime_error("Nullptr to thread-pool");
0100 m_pool->add_task(_task);
0101 }
0102
0103
0104
0105
0106 template <typename RetT, typename FuncT, typename... Args>
0107 std::shared_ptr<PackagedTask<RetT, Args...>> async(FuncT&& func, Args&&... args)
0108 {
0109 using task_type = PackagedTask<RetT, Args...>;
0110
0111 if(!m_pool)
0112 throw std::runtime_error("Nullptr to thread-pool");
0113
0114 auto _ptask = std::make_shared<task_type>(std::forward<FuncT>(func),
0115 std::forward<Args>(args)...);
0116 m_pool->add_task(_ptask);
0117 return _ptask;
0118 }
0119
0120 template <typename RetT, typename FuncT>
0121 std::shared_ptr<PackagedTask<RetT>> async(FuncT&& func)
0122 {
0123 using task_type = PackagedTask<RetT>;
0124
0125 if(!m_pool)
0126 throw std::runtime_error("Nullptr to thread-pool");
0127
0128 auto _ptask = std::make_shared<task_type>(std::forward<FuncT>(func));
0129 m_pool->add_task(_ptask);
0130 return _ptask;
0131 }
0132
0133 template <typename FuncT, typename... Args>
0134 auto async(FuncT&& func, Args... args)
0135 -> std::shared_ptr<PackagedTask<decay_t<decltype(func(args...))>, Args...>>
0136 {
0137 using RetT = decay_t<decltype(func(args...))>;
0138 using task_type = PackagedTask<RetT, Args...>;
0139
0140 if(!m_pool)
0141 throw std::runtime_error("Nullptr to thread-pool");
0142
0143 auto _ptask = std::make_shared<task_type>(std::forward<FuncT>(func),
0144 std::forward<Args>(args)...);
0145 m_pool->add_task(_ptask);
0146 return _ptask;
0147 }
0148
0149
0150 public:
0151
0152
0153
0154 template <typename RetT, typename ArgT, typename FuncT, typename... Args>
0155 std::shared_ptr<Task<RetT, ArgT, Args...>> wrap(TaskGroup<RetT, ArgT>& tg,
0156 FuncT&& func, Args&&... args)
0157 {
0158 return tg.wrap(std::forward<FuncT>(func), std::forward<Args>(args)...);
0159 }
0160
0161 template <typename RetT, typename ArgT, typename FuncT>
0162 std::shared_ptr<Task<RetT, ArgT>> wrap(TaskGroup<RetT, ArgT>& tg, FuncT&& func)
0163 {
0164 return tg.wrap(std::forward<FuncT>(func));
0165 }
0166
0167 public:
0168
0169
0170
0171 template <typename RetT, typename ArgT, typename FuncT, typename... Args>
0172 void exec(TaskGroup<RetT, ArgT>& tg, FuncT&& func, Args&&... args)
0173 {
0174 tg.exec(std::forward<FuncT>(func), std::forward<Args>(args)...);
0175 }
0176
0177 template <typename RetT, typename ArgT, typename FuncT>
0178 void exec(TaskGroup<RetT, ArgT>& tg, FuncT&& func)
0179 {
0180 tg.exec(std::forward<FuncT>(func));
0181 }
0182
0183 template <typename RetT, typename ArgT, typename FuncT, typename... Args>
0184 void rexec(TaskGroup<RetT, ArgT>& tg, FuncT&& func, Args&&... args)
0185 {
0186 tg.exec(std::forward<FuncT>(func), std::forward<Args>(args)...);
0187 }
0188
0189 template <typename RetT, typename ArgT, typename FuncT>
0190 void rexec(TaskGroup<RetT, ArgT>& tg, FuncT&& func)
0191 {
0192 tg.exec(std::forward<FuncT>(func));
0193 }
0194
0195
0196
0197 template <typename FuncT, typename... Args>
0198 void rexec(TaskGroup<void, void>& tg, FuncT&& func, Args&&... args)
0199 {
0200 tg.exec(std::forward<FuncT>(func), std::forward<Args>(args)...);
0201 }
0202
0203 template <typename FuncT>
0204 void rexec(TaskGroup<void, void>& tg, FuncT&& func)
0205 {
0206 tg.exec(std::forward<FuncT>(func));
0207 }
0208
0209
0210 protected:
0211
0212 ThreadPool* m_pool = nullptr;
0213 bool m_is_finalized = false;
0214
0215 private:
0216 static TaskManager*& fgInstance();
0217 };
0218
0219 }
0220
0221
0222 #include "TaskRunManager.hh"
0223
0224
0225
0226 inline PTL::TaskManager*&
0227 PTL::TaskManager::fgInstance()
0228 {
0229 static thread_local TaskManager* _instance = nullptr;
0230 return _instance;
0231 }
0232
0233
0234
0235 inline PTL::TaskManager*
0236 PTL::TaskManager::GetInstance()
0237 {
0238 if(!fgInstance())
0239 {
0240 auto nthreads = std::thread::hardware_concurrency();
0241 std::cout << "Allocating mad::TaskManager with " << nthreads << " thread(s)..."
0242 << std::endl;
0243 new TaskManager(TaskRunManager::GetMasterRunManager()->GetThreadPool());
0244 }
0245 return fgInstance();
0246 }
0247
0248
0249
0250 inline PTL::TaskManager*
0251 PTL::TaskManager::GetInstanceIfExists()
0252 {
0253 return fgInstance();
0254 }
0255
0256
0257
0258 inline PTL::TaskManager::TaskManager(ThreadPool* _pool, bool _manage_pool)
0259 : m_pool(_pool)
0260 , m_is_finalized(!_manage_pool)
0261 {
0262 if(!fgInstance())
0263 fgInstance() = this;
0264 }
0265
0266
0267
0268 inline PTL::TaskManager::~TaskManager() noexcept(false)
0269 {
0270 finalize();
0271 if(fgInstance() == this)
0272 fgInstance() = nullptr;
0273 }
0274
0275