MotionLib  1.0.0
SamBuCa motion library
FutureCoroutine.hpp
1 /*
2 ** Copyright (C) 2022 CERN
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-07-26T16:50:02
21 ** Author: Sylvain Fargier <sylvain.fargier@cern.ch>
22 */
23 
24 #ifndef FUTURECOROUTINE_HPP__
25 #define FUTURECOROUTINE_HPP__
26 
27 #include <chrono>
28 #include <future>
29 
30 #include <logger/Logger.hpp>
31 #include <oatpp/core/async/Coroutine.hpp>
32 
33 #include "Units.hpp"
34 
35 namespace smc {
36 namespace debug {
37 
38 extern const std::chrono::milliseconds FutureCoroutineMaxInterval;
39 
40 template<typename T>
42  public oatpp::async::CoroutineWithResult<FutureCoroutine<T>, const T &>
43 {
44 public:
45  typedef oatpp::async::CoroutineWithResult<FutureCoroutine<T>, const T &>
46  CoroutineWithResult;
47 
48  explicit FutureCoroutine(const std::shared_future<T> &future) :
49  future{future}
50  {}
51 
52  oatpp::async::Action act() override
53  {
54  if (!future.valid())
55  return oatpp::async::AbstractCoroutine::error<oatpp::async::Error>(
56  "failed");
57  else if (future.wait_for(std::chrono::seconds(0)) ==
58  std::future_status::ready)
59  return CoroutineWithResult::_return(future.get());
60  else
61  {
62  if (delay < FutureCoroutineMaxInterval)
63  delay = std::chrono::milliseconds(delay.count() << 1);
64  return CoroutineWithResult::waitRepeat(delay);
65  }
66  }
67 
68  std::chrono::milliseconds delay{1};
69  std::shared_future<T> future;
70 };
71 
72 template<>
73 class FutureCoroutine<void> :
74  public oatpp::async::Coroutine<FutureCoroutine<void>>
75 {
76 public:
77  explicit FutureCoroutine(const std::shared_future<void> &future) :
78  future{future}
79  {}
80 
81  Action act() override
82  {
83  if (!future.valid())
84  return error<Error>("failed");
85  else if (future.wait_for(std::chrono::seconds(0)) ==
86  std::future_status::ready)
87  {
88  future.get(); // throw if needed
89  return finish();
90  }
91  else
92  {
93  if (delay < FutureCoroutineMaxInterval)
94  delay = std::chrono::milliseconds(delay.count() << 1);
95  return waitRepeat(delay);
96  }
97  }
98 
99  std::chrono::milliseconds delay{1};
100  std::shared_future<void> future;
101 };
102 
103 template<typename T>
104 oatpp::async::CoroutineStarterForResult<const T &> wait(
105  const std::shared_future<T> &future)
106 {
107  return new FutureCoroutine<T>(future);
108 }
109 
110 inline oatpp::async::CoroutineStarter wait(const std::shared_future<void> &future)
111 {
112  return new FutureCoroutine<void>(future);
113 }
114 
115 } // namespace debug
116 } // namespace smc
117 
118 #endif
main motion-lib namespace
Definition: Client.cpp:30