Line data Source code
1 : // 2 : // Copyright 2024 OpenModelViewer Authors 3 : // 4 : // Licensed under the Apache License, Version 2.0 (the "License"); 5 : // you may not use this file except in compliance with the License. 6 : // You may obtain a copy of the License at 7 : // 8 : // http://www.apache.org/licenses/LICENSE-2.0 9 : // 10 : // Unless required by applicable law or agreed to in writing, software 11 : // distributed under the License is distributed on an "AS IS" BASIS, 12 : // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 : // See the License for the specific language governing permissions and 14 : // limitations under the License. 15 : // 16 : 17 : #pragma once 18 : 19 : #include "openmodelviewer/core/async/itask.hpp" 20 : #include "openmodelviewer/core/async/task_data.hpp" 21 : 22 : #include <functional> 23 : #include <utility> 24 : #include <memory> 25 : 26 : namespace openmodelviewer::core::async 27 : { 28 : /** 29 : * @brief Represents a unit of asynchronous work producing a typed result. 30 : * 31 : * This task encapsulates a callable object (e.g., lambda or std::function) 32 : * and writes its result into a shared TaskData instance when executed. 33 : * 34 : * If the callable throws during execution, the exception is captured 35 : * and reported into the TaskData. This task is intended to be used 36 : * by the ThreadPool and is not directly exposed to user code. 37 : * 38 : * @tparam RType The return type produced by the callable. 39 : */ 40 : template<typename RType> 41 : class Task : public ITask 42 : { 43 : public: 44 : /** 45 : * @brief Executes the stored task. 46 : * 47 : * Invokes the internal callable and stores the result into TaskData. 48 : * If an exception is thrown, it is caught and stored as well. 49 : */ 50 94 : inline void execute() override 51 : { 52 94 : if (m_action && m_data) 53 : { 54 : try 55 : { 56 94 : RType data = m_action(); 57 85 : m_data->resolve(std::move(data)); 58 26 : } 59 8 : catch (...) 60 : { 61 8 : m_data->report(std::current_exception()); 62 : } 63 : 64 89 : m_data->invokeCallback(); 65 : } 66 89 : } 67 : 68 : /** 69 : * @brief Creates a new Task instance from a callable and TaskData. 70 : * 71 : * This static factory method constructs a Task using the given 72 : * callable and associates it with a shared TaskData for result tracking. 73 : * 74 : * @tparam FType The type of the callable object. 75 : * @param data The TaskData instance to store the result or error. 76 : * @param func The callable object to execute. 77 : * @return A unique_ptr to the newly created Task<RType> instance. 78 : */ 79 : template<typename FType> 80 94 : static inline std::unique_ptr<Task<RType>> make(std::shared_ptr<TaskData<RType>> data, FType&& func) 81 : { 82 94 : Task<RType>* rawTask = new Task<RType>(std::move(data), std::forward<FType>(func)); 83 94 : return std::unique_ptr<Task<RType>>(rawTask); 84 : } 85 : 86 : protected: 87 : /** 88 : * @brief Constructs a task from a callable and TaskData. 89 : * 90 : * This constructor is protected and used internally by the make() method. 91 : * 92 : * @param data Shared TaskData used to store the result or exception. 93 : * @param func The callable object to invoke during execution. 94 : */ 95 94 : explicit Task(std::shared_ptr<TaskData<RType>> data, std::function<RType()> func) : 96 94 : m_action(std::move(func)), 97 188 : m_data(std::move(data)) 98 : { 99 94 : } 100 : 101 : private: 102 : std::function<RType()> m_action; 103 : std::shared_ptr<TaskData<RType>> m_data; 104 : }; 105 : } // namespace openmodelviewer::core::async