Branch data Line data Source code
1 : : /* 2 : : ** Copyright (C) 2020 Sylvain Fargier 3 : : ** 4 : : ** This software is provided 'as-is', without any express or implied 5 : : ** warranty. In no event will the authors be held liable for any damages 6 : : ** arising from the use of this software. 7 : : ** 8 : : ** Permission is granted to anyone to use this software for any purpose, 9 : : ** including commercial applications, and to alter it and redistribute it 10 : : ** freely, subject to the following restrictions: 11 : : ** 12 : : ** 1. The origin of this software must not be misrepresented; you must not 13 : : ** claim that you wrote the original software. If you use this software 14 : : ** in a product, an acknowledgment in the product documentation would be 15 : : ** appreciated but is not required. 16 : : ** 2. Altered source versions must be plainly marked as such, and must not be 17 : : ** misrepresented as being the original software. 18 : : ** 3. This notice may not be removed or altered from any source distribution. 19 : : ** 20 : : ** Created on: 2022-02-17T21:47:18+01:00 21 : : ** Author: Sylvain Fargier <fargie_s> <fargier.sylvain@free.fr> 22 : : ** 23 : : */ 24 : : 25 : : #ifndef CCUT_ASYNC_HPP__ 26 : : #define CCUT_ASYNC_HPP__ 27 : : 28 : : #include <chrono> 29 : : #include <future> 30 : : #include <stdexcept> 31 : : 32 : : #include <logger/Logger.hpp> 33 : : 34 : : namespace ccut { 35 : : 36 : : /** 37 : : * @brief wait for a future to resolve 38 : : * @details this adds timeout to default wait, this method uses const to accept 39 : : * rvalues 40 : : * @param f future to resolve 41 : : * @param ms timeout delay 42 : : * @return the future resolved value 43 : : * @throws std::runtime_error on error 44 : : */ 45 : : template<typename T> 46 : 11 : T wait(const std::future<T> &f, 47 : 2 : const std::chrono::milliseconds &ms = std::chrono::milliseconds(5000)) 48 : : { 49 : 11 : if (f.wait_for(ms) != std::future_status::timeout) 50 : 9 : return const_cast<typename std::future<T> &>(f).get(); 51 : : else 52 : 2 : throw std::runtime_error("timeout"); 53 : : } 54 : : 55 : 6 : inline void wait( 56 : : const std::future<void> &f, 57 : 2 : const std::chrono::milliseconds &ms = std::chrono::milliseconds(5000)) 58 : : { 59 : 6 : if (f.wait_for(ms) != std::future_status::timeout) 60 : 4 : const_cast<std::future<void> &>(f).get(); 61 : : else 62 : 2 : throw std::runtime_error("timeout"); 63 : 2 : } 64 : : 65 : : /** 66 : : * @brief create an erroneous future 67 : : * @details mainly useful for early checks 68 : : * @param ex exception object to set 69 : : * @return a future in error state 70 : : */ 71 : : template<typename T = void, typename E> 72 : 4 : std::future<T> make_future_error(const E &ex) 73 : : { 74 : 4 : std::promise<T> p; 75 : 4 : p.set_exception(std::make_exception_ptr(ex)); 76 : 8 : return p.get_future(); 77 : 4 : } 78 : : 79 : : /** 80 : : * @brief safely get future result 81 : : * 82 : : * @param f future to resolve 83 : : * @param def default value returned 84 : : * @param msg error message 85 : : * @param ms timeout delay 86 : : * @return T 87 : : */ 88 : : template<typename T> 89 : 3 : T try_get(const std::future<T> &f, 90 : : const T &def, 91 : 2 : const std::chrono::milliseconds &ms = std::chrono::milliseconds(5000), 92 : : const std::string &msg = "failed to get promise value") noexcept 93 : : 94 : : { 95 : : try 96 : : { 97 : 3 : return ccut::wait(f, ms); 98 : : } 99 : 2 : catch (std::exception &ex) 100 : : { 101 : 2 : logger::error("ccut::async") << msg << ": " << ex.what(); 102 : : } 103 : 0 : catch (...) 104 : : { 105 : 0 : logger::error("ccut::async") << msg; 106 : : } 107 : 2 : return def; 108 : : } 109 : : 110 : : /** 111 : : * @brief safely get future result 112 : : * 113 : : * @param f future to resolve 114 : : * @param msg error message 115 : : * @param ms timeout delay 116 : : * @return true if promise succeeded 117 : : */ 118 : 3 : inline bool try_get( 119 : : const std::future<void> &f, 120 : 2 : const std::chrono::milliseconds &ms = std::chrono::milliseconds(5000), 121 : : const std::string &msg = "failed to get promise value") noexcept 122 : : { 123 : : try 124 : : { 125 : 3 : ccut::wait(f, ms); 126 : 1 : return true; 127 : : } 128 : 2 : catch (std::exception &ex) 129 : : { 130 : 2 : logger::error("ccut::async") << msg << ": " << ex.what(); 131 : 2 : } 132 : 0 : catch (...) 133 : : { 134 : 0 : logger::error("ccut::async") << msg; 135 : 0 : } 136 : 2 : return false; 137 : : } 138 : : 139 : : } // namespace ccut 140 : : 141 : : #endif