source: mainline/uspace/lib/cpp/include/__bits/thread/packaged_task.hpp@ 239d25b

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

cpp: implemented packaged_task

  • Property mode set to 100644
File size: 6.1 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_PACKAGED_TASK
30#define LIBCPP_BITS_THREAD_PACKAGED_TASK
31
32#include <__bits/functional/function.hpp>
33#include <__bits/thread/future.hpp>
34#include <__bits/thread/future_common.hpp>
35#include <__bits/thread/shared_state.hpp>
36#include <type_traits>
37#include <utility>
38
39namespace std
40{
41 /**
42 * 30.6.9, class template packaged_task:
43 */
44
45 template<class>
46 class packaged_task; // undefined
47
48 template<class R, class... Args>
49 class packaged_task<R(Args...)>
50 {
51 public:
52 packaged_task() noexcept
53 : func_{}, state_{}
54 { /* DUMMY BODY */ }
55
56 template<
57 class F, enable_if_t<
58 !is_same_v<
59 decay_t<F>, packaged_task<R(Args...)>
60 >, int
61 > = 0
62 >
63 explicit packaged_task(F&& f)
64 : func_{forward<F>(f)}, state_{new aux::shared_state<R>{}}
65 { /* DUMMY BODY */ }
66
67 template<
68 class F, class Allocator, enable_if_t<
69 is_same_v<
70 decay_t<F>, packaged_task<R(Args...)>
71 >, int
72 > = 0
73 >
74 explicit packaged_task(allocator_arg_t, const Allocator& a, F&& f)
75 : packaged_task{forward<F>(f)}
76 {
77 // TODO: use the allocator
78 }
79
80 ~packaged_task()
81 {
82 if (state_)
83 {
84 if (!state_->is_set())
85 {
86 // TODO: store future_error
87 state_->mark_set(true);
88 }
89
90 if (state_->decrement())
91 {
92 state_->destroy();
93 delete state_;
94 state_ = nullptr;
95 }
96 }
97 }
98
99 packaged_task(const packaged_task&) = delete;
100 packaged_task& operator=(const packaged_task&) = delete;
101
102 packaged_task(packaged_task&& rhs)
103 : func_{move(rhs.func_)}, state_{move(rhs.state_)}
104 { /* DUMMY BODY */ }
105
106 packaged_task& operator=(packaged_task&& rhs)
107 {
108 if (state_)
109 {
110 if (state_->decrement())
111 {
112 state_->destroy();
113 delete state_;
114 state_ = nullptr;
115 }
116 }
117
118 func_ = move(rhs.func_);
119 state_ = move(rhs.state_);
120
121 return *this;
122 }
123
124 void swap(packaged_task& other) noexcept
125 {
126 std::swap(func_, other.func_);
127 std::swap(state_, other.state_);
128 }
129
130 bool valid() const noexcept
131 {
132 return state_ != nullptr;
133 }
134
135 future<R> get_future()
136 {
137 if (!state_)
138 throw future_error{make_error_code(future_errc::no_state)};
139
140 state_->increment();
141
142 return future<R>{state_};
143 }
144
145 /**
146 * Note: This is how the signature is in the standard,
147 * should be investigated and verified.
148 */
149 void operator()(Args... args)
150 {
151 if (!state_)
152 throw future_error{make_error_code(future_errc::no_state)};
153 if (state_->is_set())
154 {
155 throw future_error{
156 make_error_code(future_errc::promise_already_satisfied)
157 };
158 }
159
160 try
161 {
162 state_->set_value(invoke(func_, args...));
163 }
164 catch(...)
165 {
166 // TODO: store it
167 }
168 }
169
170 void make_ready_at_thread_exit(Args...)
171 {
172 // TODO: implement
173 }
174
175 void reset()
176 {
177 if (!state_)
178 throw future_error{make_error_code(future_errc::no_state)};
179
180 *this = packaged_task{move(func_)};
181 }
182
183 private:
184 function<R(Args...)> func_;
185
186 aux::shared_state<R>* state_;
187 };
188
189 template<class R, class... Args>
190 void swap(packaged_task<R(Args...)>& lhs, packaged_task<R(Args...)>& rhs) noexcept
191 {
192 lhs.swap(rhs);
193 };
194
195 template<class R, class Alloc>
196 struct uses_allocator<packaged_task<R>, Alloc>: true_type
197 { /* DUMMY BODY */ };
198}
199
200#endif
Note: See TracBrowser for help on using the repository browser.