source: mainline/uspace/lib/cpp/include/__bits/thread/promise.hpp@ 7480341

lfn serial ticket/834-toolchain-update topic/msim-upgrade topic/simplify-dev-export
Last change on this file since 7480341 was a95e75e, checked in by Jaroslav Jindrak <dzejrou@…>, 6 years ago

cpp: split future.hpp into subheaders for each type

  • Property mode set to 100644
File size: 6.0 KB
Line 
1/*
2 * Copyright (c) 2019 Jaroslav Jindrak
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 *
9 * - Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * - Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
14 * - The name of the author may not be used to endorse or promote products
15 * derived from this software without specific prior written permission.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
18 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
19 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
20 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
21 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
22 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 */
28
29#ifndef LIBCPP_BITS_THREAD_PROMISE
30#define LIBCPP_BITS_THREAD_PROMISE
31
32#include <__bits/thread/future.hpp>
33#include <__bits/thread/shared_state.hpp>
34#include <__bits/aux.hpp>
35#include <utility>
36
37namespace std
38{
39 /**
40 * 30.6.5, class template promise:
41 */
42
43 template<class R>
44 class promise
45 {
46 public:
47 promise()
48 : state_{new aux::shared_state<R>{}}
49 { /* DUMMY BODY */ }
50
51 template<class Allocator>
52 promise(allocator_arg_t, const Allocator& a)
53 : promise{}
54 {
55 // TODO: Use the allocator.
56 }
57
58 promise(promise&& rhs) noexcept
59 : state_{}
60 {
61 state_ = rhs.state_;
62 rhs.state_ = nullptr;
63 }
64
65 promise(const promise&) = delete;
66
67 ~promise()
68 {
69 abandon_state_();
70 }
71
72 promise& operator=(promise&& rhs) noexcept
73 {
74 abandon_state_();
75 promise{std::move(rhs)}.swap(*this);
76 }
77
78 promise& operator=(const promise&) = delete;
79
80 void swap(promise& other) noexcept
81 {
82 std::swap(state_, other.state_);
83 }
84
85 future<R> get_future()
86 {
87 return future<R>{state_};
88 }
89
90 void set_value(const R& val)
91 {
92 if (!state_)
93 throw future_error{make_error_code(future_errc::no_state)};
94 if (state_->is_set())
95 {
96 throw future_error{
97 make_error_code(future_errc::promise_already_satisfied)
98 };
99 }
100
101 state_->set_value(val, true);
102 }
103
104 void set_value(R&& val)
105 {
106 if (!state_)
107 throw future_error{make_error_code(future_errc::no_state)};
108 if (state_->is_set())
109 {
110 throw future_error{
111 make_error_code(future_errc::promise_already_satisfied)
112 };
113 }
114
115 state_->set_value(std::forward<R>(val), true);
116 }
117
118 void set_exception(exception_ptr ptr)
119 {
120 assert(state_);
121
122 state_->set_exception(ptr);
123 }
124
125 void set_value_at_thread_exit(const R& val)
126 {
127 if (!state_)
128 throw future_error{make_error_code(future_errc::no_state)};
129 if (state_->is_set())
130 {
131 throw future_error{
132 make_error_code(future_errc::promise_already_satisfied)
133 };
134 }
135
136 state_->set_value(val, false);
137 // TODO: schedule it to be set as ready when thread exits
138 }
139
140 void set_value_at_thread_exit(R&& val)
141 {
142 if (!state_)
143 throw future_error{make_error_code(future_errc::no_state)};
144 if (state_->is_set())
145 {
146 throw future_error{
147 make_error_code(future_errc::promise_already_satisfied)
148 };
149 }
150
151 state_->set_value(std::forward<R>(val), false);
152 // TODO: schedule it to be set as ready when thread exits
153 }
154
155 void set_exception_at_thread_exit(exception_ptr)
156 {
157 // TODO: No exception handling, no-op at this time.
158 }
159
160 private:
161 void abandon_state_()
162 {
163 /**
164 * Note: This is the 'abandon' move described in
165 * 30.6.4 (7).
166 * 1) If state is not ready:
167 * a) Store exception of type future_error with
168 * error condition broken_promise.
169 * b) Mark state as ready.
170 * 2) Rekease the state.
171 */
172 }
173
174 aux::shared_state<R>* state_;
175 };
176
177 template<class R>
178 class promise<R&>
179 {
180 // TODO: Copy & modify once promise is done.
181 };
182
183 template<>
184 class promise<void>
185 {
186 // TODO: Copy & modify once promise is done.
187 };
188
189 template<class R>
190 void swap(promise<R>& lhs, promise<R>& rhs) noexcept
191 {
192 lhs.swap(rhs);
193 }
194
195 template<class R, class Alloc>
196 struct uses_allocator<promise<R>, Alloc>: true_type
197 { /* DUMMY BODY */ };
198}
199
200#endif
Note: See TracBrowser for help on using the repository browser.