GCC Code Coverage Report


Directory: ./
File: pdcom5/src/Future.h
Date: 2023-11-12 04:06:57
Exec Total Coverage
Lines: 35 49 71.4%
Branches: 12 58 20.7%

Line Branch Exec Source
1 /*****************************************************************************
2 * vim:tw=78
3 *
4 * Copyright (C) 2022 Bjarne von Horn (vh at igh dot de).
5 *
6 * This file is part of the PdCom library.
7 *
8 * The PdCom library is free software: you can redistribute it and/or modify
9 * it under the terms of the GNU Lesser General Public License as published by
10 * the Free Software Foundation, either version 3 of the License, or (at your
11 * option) any later version.
12 *
13 * The PdCom library is distributed in the hope that it will be useful, but
14 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
15 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
16 * License for more details.
17 *
18 * You should have received a copy of the GNU Lesser General Public License
19 * along with the PdCom library. If not, see <http://www.gnu.org/licenses/>.
20 *
21 *****************************************************************************/
22
23 #ifndef PDCOM5_FUTURE_IMPL_H
24 #define PDCOM5_FUTURE_IMPL_H
25
26 #include <functional>
27 #include <memory>
28 #include <pdcom5/Exception.h>
29 #include <pdcom5/Future.h>
30 #include <tuple>
31 #include <type_traits>
32
33 namespace PdCom {
34 namespace impl {
35 template <class Exception>
36 11 struct PromiseBase
37 {
38 std::function<void(Exception)> reject_;
39 };
40
41 template <class Exception, class... Result>
42 11 struct Promise : public PromiseBase<Exception>
43 {
44 std::function<void(Result...)> resolve_;
45 };
46 } // namespace impl
47 template <class Exception>
48 40 class PromiseBase
49 {
50 protected:
51 std::weak_ptr<impl::PromiseBase<Exception>> impl_;
52
53 public:
54 using ExceptionType = Exception;
55
56 8 PromiseBase(std::weak_ptr<impl::PromiseBase<Exception>> impl) noexcept :
57 8 impl_(std::move(impl))
58 8 {}
59 32 PromiseBase(PromiseBase &&) = default;
60 PromiseBase(PromiseBase const &) = delete;
61 PromiseBase &operator=(PromiseBase &&) = default;
62 PromiseBase &operator=(PromiseBase const &) = delete;
63
64 template <class... Args>
65 bool reject(Args &&...args);
66 };
67
68 template <class Exception, class... Result>
69 72 class Promise : public PromiseBase<Exception>
70 {
71 using Impl = impl::Promise<Exception, Result...>;
72
73 public:
74 using ResolveFn = std::function<void(Result...)>;
75
76
77 Promise() noexcept : PromiseBase<Exception>(nullptr) {}
78 8 Promise(std::weak_ptr<Impl> impl) noexcept :
79 8 PromiseBase<Exception>(std::move(impl))
80 8 {}
81
82 template <class... Args>
83 bool resolve(Args &&...result);
84
85 PromiseBase<Exception> toBase()
86 {
87 return {std::move(PromiseBase<Exception>::impl_)};
88 }
89 };
90
91 template <class Exception, class... Result>
92 8 const Future<Exception, Result...> &Future<Exception, Result...>::then(
93 Future<Exception, Result...>::ResolveFn resolve) const &
94 {
95
1/4
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 6 not taken.
✓ Branch 7 taken 8 times.
8 if (!impl_)
96 throw InvalidArgument("Future is empty");
97 8 impl_->resolve_ = resolve;
98 8 return *this;
99 }
100
101 template <class Exception, class... Result>
102 const Future<Exception, Result...> &
103 8 Future<Exception, Result...>::handle_exception(
104 Future<Exception, Result...>::RejectFn reject) const &
105 {
106
1/4
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 6 not taken.
✓ Branch 7 taken 8 times.
8 if (!impl_)
107 throw InvalidArgument("Future is empty");
108 8 impl_->reject_ = reject;
109 8 return *this;
110 }
111
112 template <class Exception, class... Result>
113 Future<Exception, Result...> Future<Exception, Result...>::then(
114 Future<Exception, Result...>::ResolveFn resolve) &&
115 {
116 if (!impl_)
117 throw InvalidArgument("Future is empty");
118 impl_->resolve_ = resolve;
119 return std::move(*this);
120 }
121
122 template <class Exception, class... Result>
123 Future<Exception, Result...> Future<Exception, Result...>::handle_exception(
124 Future<Exception, Result...>::RejectFn reject) &&
125 {
126 if (!impl_)
127 throw InvalidArgument("Future is empty");
128 impl_->reject_ = reject;
129 return std::move(*this);
130 }
131
132 template <class Exception, class... Result>
133 template <class... Args>
134 3 inline bool Promise<Exception, Result...>::resolve(Args &&...args)
135 {
136 3 bool ans = false;
137
1/4
✗ Branch 8 not taken.
✗ Branch 9 not taken.
✓ Branch 22 taken 3 times.
✗ Branch 23 not taken.
6 if (const auto impl = std::static_pointer_cast<Impl>(
138 PromiseBase<Exception>::impl_.lock())) {
139
1/4
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 8 taken 3 times.
✗ Branch 9 not taken.
3 if (impl->resolve_) {
140
2/6
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 15 taken 3 times.
✗ Branch 16 not taken.
✓ Branch 18 taken 3 times.
✗ Branch 19 not taken.
3 impl->resolve_(std::forward<Args>(args)...);
141 3 ans = true;
142 }
143 }
144 3 PromiseBase<Exception>::impl_.reset();
145 3 return ans;
146 }
147
148 template <class Exception>
149 template <class... Args>
150 5 inline bool PromiseBase<Exception>::reject(Args &&...args)
151 {
152
2/4
✓ Branch 3 taken 5 times.
✗ Branch 4 not taken.
✗ Branch 6 not taken.
✓ Branch 7 taken 5 times.
5 if (const auto impl = impl_.lock()) {
153
1/2
✓ Branch 3 taken 5 times.
✗ Branch 4 not taken.
5 if (impl->reject_) {
154
1/2
✓ Branch 6 taken 5 times.
✗ Branch 7 not taken.
5 impl->reject_(std::forward<Args>(args)...);
155
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 5 times.
5 return true;
156 }
157 }
158 impl_.reset();
159 return false;
160 }
161
162 template <class Exception, class... Result>
163 inline std::pair<Future<Exception, Result...>, Promise<Exception, Result...>>
164 8 createFuture()
165 {
166
1/2
✓ Branch 2 taken 8 times.
✗ Branch 3 not taken.
16 auto ans = std::make_shared<impl::Promise<Exception, Result...>>();
167 return {Future<Exception, Result...> {ans},
168 16 Promise<Exception, Result...> {ans}};
169 }
170
171 } // namespace PdCom
172
173
174 #endif // PDCOM5_FUTURE_IMPL_H
175