Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-01-30 10:07:23

0001 //
0002 // MIT License
0003 // Copyright (c) 2020 Jonathan R. Madsen
0004 // Permission is hereby granted, free of charge, to any person obtaining a copy
0005 // of this software and associated documentation files (the "Software"), to deal
0006 // in the Software without restriction, including without limitation the rights
0007 // to use, copy, modify, merge, publish, distribute, sublicense, and
0008 // copies of the Software, and to permit persons to whom the Software is
0009 // furnished to do so, subject to the following conditions:
0010 // The above copyright notice and this permission notice shall be included in
0011 // all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED
0012 // "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT
0013 // LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
0014 // PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
0015 // HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
0016 // ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
0017 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
0018 //
0019 //
0020 // ---------------------------------------------------------------
0021 // Tasking class header file
0022 //
0023 // Class Description:
0024 //
0025 // This file defines the task types for TaskManager and ThreadPool
0026 //
0027 // ---------------------------------------------------------------
0028 // Author: Jonathan Madsen (Feb 13th 2018)
0029 // ---------------------------------------------------------------
0030 
0031 #pragma once
0032 
0033 #include "PTL/Globals.hh"
0034 #include "PTL/VTask.hh"
0035 
0036 #include <cstdint>
0037 #include <future>
0038 #include <tuple>
0039 #include <utility>
0040 
0041 namespace PTL
0042 {
0043 //======================================================================================//
0044 
0045 /// \brief The task class is supplied to thread_pool.
0046 template <typename RetT>
0047 class TaskFuture : public VTask
0048 {
0049 public:
0050     using promise_type = std::promise<RetT>;
0051     using future_type  = std::future<RetT>;
0052     using result_type  = RetT;
0053 
0054 public:
0055     // pass a free function pointer
0056     template <typename... Args>
0057     TaskFuture(Args&&... args)
0058     : VTask{ std::forward<Args>(args)... }
0059     {}
0060 
0061     ~TaskFuture() override = default;
0062 
0063     TaskFuture(const TaskFuture&) = delete;
0064     TaskFuture& operator=(const TaskFuture&) = delete;
0065 
0066     TaskFuture(TaskFuture&&) noexcept = default;
0067     TaskFuture& operator=(TaskFuture&&) noexcept = default;
0068 
0069 public:
0070     // execution operator
0071     virtual future_type get_future() = 0;
0072     virtual void        wait()       = 0;
0073     virtual RetT        get()        = 0;
0074 };
0075 
0076 //======================================================================================//
0077 
0078 /// \brief The task class is supplied to thread_pool.
0079 template <typename RetT, typename... Args>
0080 class PackagedTask : public TaskFuture<RetT>
0081 {
0082 public:
0083     using this_type          = PackagedTask<RetT, Args...>;
0084     using promise_type       = std::promise<RetT>;
0085     using future_type        = std::future<RetT>;
0086     using packaged_task_type = std::packaged_task<RetT(Args...)>;
0087     using result_type        = RetT;
0088     using tuple_type         = std::tuple<Args...>;
0089 
0090 public:
0091     // pass a free function pointer
0092     template <typename FuncT>
0093     PackagedTask(FuncT func, Args... args)
0094     : TaskFuture<RetT>{ true, 0 }
0095     , m_ptask{ std::move(func) }
0096     , m_args{ args... }
0097     {}
0098 
0099     template <typename FuncT>
0100     PackagedTask(bool _is_native, intmax_t _depth, FuncT func, Args... args)
0101     : TaskFuture<RetT>{ _is_native, _depth }
0102     , m_ptask{ std::move(func) }
0103     , m_args{ args... }
0104     {}
0105 
0106     ~PackagedTask() override = default;
0107 
0108     PackagedTask(const PackagedTask&) = delete;
0109     PackagedTask& operator=(const PackagedTask&) = delete;
0110 
0111     PackagedTask(PackagedTask&&) noexcept = default;
0112     PackagedTask& operator=(PackagedTask&&) noexcept = default;
0113 
0114 public:
0115     // execution operator
0116     void        operator()() final { mpl::apply(std::move(m_ptask), std::move(m_args)); }
0117     future_type get_future() final { return m_ptask.get_future(); }
0118     void        wait() final { return m_ptask.get_future().wait(); }
0119     RetT        get() final { return m_ptask.get_future().get(); }
0120 
0121 private:
0122     packaged_task_type m_ptask;
0123     tuple_type         m_args;
0124 };
0125 
0126 //======================================================================================//
0127 
0128 /// \brief The task class is supplied to thread_pool.
0129 template <typename RetT, typename... Args>
0130 class Task : public TaskFuture<RetT>
0131 {
0132 public:
0133     using this_type          = Task<RetT, Args...>;
0134     using promise_type       = std::promise<RetT>;
0135     using future_type        = std::future<RetT>;
0136     using packaged_task_type = std::packaged_task<RetT(Args...)>;
0137     using result_type        = RetT;
0138     using tuple_type         = std::tuple<Args...>;
0139 
0140 public:
0141     template <typename FuncT>
0142     Task(FuncT func, Args... args)
0143     : TaskFuture<RetT>{}
0144     , m_ptask{ std::move(func) }
0145     , m_args{ args... }
0146     {}
0147 
0148     template <typename FuncT>
0149     Task(bool _is_native, intmax_t _depth, FuncT func, Args... args)
0150     : TaskFuture<RetT>{ _is_native, _depth }
0151     , m_ptask{ std::move(func) }
0152     , m_args{ args... }
0153     {}
0154 
0155     ~Task() override = default;
0156 
0157     Task(const Task&) = delete;
0158     Task& operator=(const Task&) = delete;
0159 
0160     Task(Task&&) noexcept = default;
0161     Task& operator=(Task&&) noexcept = default;
0162 
0163 public:
0164     // execution operator
0165     void operator()() final
0166     {
0167         if(m_ptask.valid())
0168             mpl::apply(std::move(m_ptask), std::move(m_args));
0169     }
0170     future_type get_future() final { return m_ptask.get_future(); }
0171     void        wait() final { return m_ptask.get_future().wait(); }
0172     RetT        get() final { return m_ptask.get_future().get(); }
0173 
0174 private:
0175     packaged_task_type m_ptask{};
0176     tuple_type         m_args{};
0177 };
0178 
0179 //======================================================================================//
0180 
0181 /// \brief The task class is supplied to thread_pool.
0182 template <typename RetT>
0183 class Task<RetT, void> : public TaskFuture<RetT>
0184 {
0185 public:
0186     using this_type          = Task<RetT>;
0187     using promise_type       = std::promise<RetT>;
0188     using future_type        = std::future<RetT>;
0189     using packaged_task_type = std::packaged_task<RetT()>;
0190     using result_type        = RetT;
0191 
0192 public:
0193     template <typename FuncT>
0194     Task(FuncT func)
0195     : TaskFuture<RetT>()
0196     , m_ptask{ std::move(func) }
0197     {}
0198 
0199     template <typename FuncT>
0200     Task(bool _is_native, intmax_t _depth, FuncT func)
0201     : TaskFuture<RetT>{ _is_native, _depth }
0202     , m_ptask{ std::move(func) }
0203     {}
0204 
0205     virtual ~Task() = default;
0206 
0207     Task(const Task&) = delete;
0208     Task& operator=(const Task&) = delete;
0209 
0210     Task(Task&&) noexcept = default;
0211     Task& operator=(Task&&) noexcept = default;
0212 
0213 public:
0214     // execution operator
0215     virtual void        operator()() final { m_ptask(); }
0216     virtual future_type get_future() final { return m_ptask.get_future(); }
0217     virtual void        wait() final { return m_ptask.get_future().wait(); }
0218     virtual RetT        get() final { return m_ptask.get_future().get(); }
0219 
0220 private:
0221     packaged_task_type m_ptask{};
0222 };
0223 
0224 //======================================================================================//
0225 
0226 /// \brief The task class is supplied to thread_pool.
0227 template <>
0228 class Task<void, void> : public TaskFuture<void>
0229 {
0230 public:
0231     using RetT               = void;
0232     using this_type          = Task<void, void>;
0233     using promise_type       = std::promise<RetT>;
0234     using future_type        = std::future<RetT>;
0235     using packaged_task_type = std::packaged_task<RetT()>;
0236     using result_type        = RetT;
0237 
0238 public:
0239     template <typename FuncT>
0240     explicit Task(FuncT func)
0241     : TaskFuture<RetT>{}
0242     , m_ptask{ std::move(func) }
0243     {}
0244 
0245     template <typename FuncT>
0246     Task(bool _is_native, intmax_t _depth, FuncT func)
0247     : TaskFuture<RetT>{ _is_native, _depth }
0248     , m_ptask{ std::move(func) }
0249     {}
0250 
0251     ~Task() override = default;
0252 
0253     Task(const Task&) = delete;
0254     Task& operator=(const Task&) = delete;
0255 
0256     Task(Task&&)  = default;
0257     Task& operator=(Task&&) = default;
0258 
0259 public:
0260     // execution operator
0261     void        operator()() final { m_ptask(); }
0262     future_type get_future() final { return m_ptask.get_future(); }
0263     void        wait() final { return m_ptask.get_future().wait(); }
0264     RetT        get() final { return m_ptask.get_future().get(); }
0265 
0266 private:
0267     packaged_task_type m_ptask{};
0268 };
0269 
0270 //======================================================================================//
0271 
0272 }  // namespace PTL