Changeset 8e24583 in mainline
- Timestamp:
- 2019-07-03T16:59:49Z (6 years ago)
- Branches:
- lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
- Children:
- 46c66f8
- Parents:
- 96fec16
- Location:
- uspace
- Files:
-
- 8 edited
Legend:
- Unmodified
- Added
- Removed
-
uspace/app/cpptest/main.cpp
r96fec16 r8e24583 121 121 ts.add<std::test::functional_test>(); 122 122 ts.add<std::test::algorithm_test>(); 123 ts.add<std::test::future_test>(); 123 124 124 125 return ts.run(true) ? 0 : 1; -
uspace/lib/cpp/include/__bits/test/tests.hpp
r96fec16 r8e24583 304 304 void test_future(); 305 305 void test_promise(); 306 void test_future_promise(); 306 307 void test_async(); 307 308 void test_packaged_task(); -
uspace/lib/cpp/include/__bits/thread/future.hpp
r96fec16 r8e24583 101 101 state_ = move(rhs.state_); 102 102 rhs.state_ = nullptr; 103 104 return *this; 103 105 } 104 106 … … 183 185 184 186 future(future&& rhs) noexcept 185 : aux::future_base<aux::future_inner_t<R>>{move(rhs .state_)}187 : aux::future_base<aux::future_inner_t<R>>{move(rhs)} 186 188 { /* DUMMY BODY */ } 187 189 … … 220 222 } 221 223 } 224 225 /** 226 * Useful for testing as we can check some information 227 * otherwise unavailable to us without waiting, e.g. 228 * to check whether the state is ready, its reference 229 * count etc. 230 */ 231 aux::shared_state<aux::future_inner_t<R>>* __state() noexcept 232 { 233 return this->state_; 234 } 222 235 }; 223 236 } -
uspace/lib/cpp/include/__bits/thread/packaged_task.hpp
r96fec16 r8e24583 127 127 func_ = move(rhs.func_); 128 128 state_ = move(rhs.state_); 129 rhs.state_ = nullptr; 129 130 130 131 return *this; -
uspace/lib/cpp/include/__bits/thread/promise.hpp
r96fec16 r8e24583 109 109 } 110 110 111 /** 112 * Useful for testing as we can check some information 113 * otherwise unavailable to us without waiting, e.g. 114 * to check whether the state is ready, its reference 115 * count etc. 116 */ 117 aux::shared_state<R>* __state() 118 { 119 return state_; 120 } 121 111 122 protected: 112 123 void abandon_state_() … … 250 261 try 251 262 { 252 this->state_->set_value(forward (val), false);263 this->state_->set_value(forward<R>(val), false); 253 264 aux::set_state_value_at_thread_exit(this->state_); 254 265 } -
uspace/lib/cpp/include/__bits/thread/shared_future.hpp
r96fec16 r8e24583 96 96 } 97 97 } 98 99 /** 100 * Useful for testing as we can check some information 101 * otherwise unavailable to us without waiting, e.g. 102 * to check whether the state is ready, its reference 103 * count etc. 104 */ 105 aux::shared_state<aux::future_inner_t<R>>* __state() noexcept 106 { 107 return this->state_; 108 } 98 109 }; 99 110 } -
uspace/lib/cpp/include/__bits/thread/shared_state.hpp
r96fec16 r8e24583 115 115 wait_for(const chrono::duration<Rep, Period>& rel_time) 116 116 { 117 if (value_set_) 118 return future_status::ready; 119 117 120 aux::threading::mutex::lock(mutex_); 118 121 auto res = timed_wait_( … … 128 131 wait_until(const chrono::time_point<Clock, Duration>& abs_time) 129 132 { 133 if (value_set_) 134 return future_status::ready; 135 130 136 aux::threading::mutex::lock(mutex_); 131 137 auto res = timed_wait_( … … 189 195 aux::threading::mutex::unlock(mutex_); 190 196 191 aux::threading::condvar::broadcast(condvar_); 197 if (set) 198 aux::threading::condvar::broadcast(condvar_); 192 199 } 193 200 … … 199 206 aux::threading::mutex::unlock(mutex_); 200 207 201 aux::threading::condvar::broadcast(condvar_); 208 if (set) 209 aux::threading::condvar::broadcast(condvar_); 202 210 } 203 211 … … 293 301 294 302 protected: 295 future_status timed_wait_(aux::time_unit_t ) override303 future_status timed_wait_(aux::time_unit_t time) override 296 304 { 297 305 /** … … 299 307 * behaviour should be compliant. 300 308 */ 301 return future_status::timeout; 309 aux::threading::time::sleep(time); 310 if (this->value_set_) 311 return future_status::ready; 312 else 313 return future_status::timeout; 302 314 } 303 315 -
uspace/lib/cpp/src/__bits/test/future.cpp
r96fec16 r8e24583 27 27 */ 28 28 29 #include <__bits/test/mock.hpp> 29 30 #include <__bits/test/tests.hpp> 31 #include <chrono> 32 #include <exception> 30 33 #include <future> 34 #include <tuple> 35 #include <utility> 36 37 using namespace std::chrono_literals; 38 39 namespace 40 { 41 template<class R> 42 auto prepare() 43 { 44 auto res = std::tuple< 45 std::promise<R>, std::future<R>, 46 std::aux::shared_state<R>* 47 >{}; 48 std::get<0>(res) = std::promise<R>{}; 49 std::get<1>(res) = std::get<0>(res).get_future(); 50 std::get<2>(res) = std::get<1>(res).__state(); 51 52 return res; 53 } 54 } 31 55 32 56 namespace std::test … … 39 63 test_future(); 40 64 test_promise(); 65 test_future_promise(); 41 66 test_async(); 42 67 test_packaged_task(); … … 53 78 void future_test::test_future() 54 79 { 55 // TODO: 80 std::future<int> f1{}; 81 test("default constructed invalid", !f1.valid()); 82 83 std::future<int> f2{new std::aux::shared_state<int>{}}; 84 test("state constructed valid", f2.valid()); 85 86 f1 = std::move(f2); 87 test("move assignment source invalid", !f2.valid()); 88 test("move assignment destination valid", f1.valid()); 89 90 std::future<int> f3{std::move(f1)}; 91 test("move construction source invalid", !f1.valid()); 92 test("move construction destination valid", f3.valid()); 56 93 } 57 94 58 95 void future_test::test_promise() 59 96 { 60 // TODO: 97 std::promise<int> p1{}; 98 test("default constructed promise has state", p1.__state()); 99 100 std::promise<int> p2{}; 101 auto* s1 = p1.__state(); 102 auto* s2 = p2.__state(); 103 p2.swap(p1); 104 std::swap(s1, s2); 105 106 test_eq("swap switches states pt1", s1, p1.__state()); 107 test_eq("swap switches states pt2", s2, p2.__state()); 108 109 std::promise<int> p3{std::move(p1)}; 110 test_eq("move construction state moved", s1, p3.__state()); 111 test_eq("move construction source empty", p1.__state(), nullptr); 112 113 p1 = std::move(p3); 114 test_eq("move assignment state move", s1, p1.__state()); 115 test_eq("move assignment source empty", p3.__state(), nullptr); 116 117 p1.set_value(42); 118 test("set_value marks state as ready", s1->is_set()); 119 test_eq("set_value sets value", s1->get(), 42); 120 } 121 122 void future_test::test_future_promise() 123 { 124 /** 125 * Note: As we currently have no exception 126 * propagation support, we do not test 127 * exceptions here. However, the logic there 128 * is basically identical to that of the value 129 * setting. 130 */ 131 auto [p1, f1, s1] = prepare<int>(); 132 test_eq("refcount in basic case", s1->refs(), 2); 133 134 p1.set_value(1); 135 test("simple case valid", f1.valid()); 136 test_eq("simple case get", f1.get(), 1); 137 138 auto [p2, f2, s2] = prepare<int>(); 139 std::thread t2{ 140 [&p2](){ 141 std::this_thread::sleep_for(20ms); 142 p2.set_value(42); 143 } 144 }; 145 146 test_eq("parallel get waits and has correct value", f2.get(), 42); 147 148 auto [p3, f3, s3] = prepare<int>(); 149 std::thread t3{ 150 [&p3](){ 151 std::this_thread::sleep_for(20ms); 152 p3.set_value(42); 153 } 154 }; 155 156 f3.wait(); 157 test("after wait value is set", s3->is_set()); 158 test_eq("after wait value is correct", s3->get(), 42); 159 160 auto [p4, f4, s4] = prepare<int>(); 161 std::thread t4{ 162 [&p4](){ 163 p4.set_value_at_thread_exit(42); 164 } 165 }; 166 std::this_thread::sleep_for(10ms); // Let the value be set inside state. 167 168 /* test("shared state marked as ready at thread exit", s4->is_set()); */ 169 test_eq("value set inside state while in thread", s4->get(), 42); 170 /* test_eq("value set at thread exit", f4.get(), 42); */ 171 172 mock::clear(); 173 std::aux::shared_state<std::test::mock>* s5{}; 174 { 175 std::promise<std::test::mock> p5{}; 176 s5 = p5.__state(); 177 test_eq("refcount with just promise", s5->refs(), 1); 178 { 179 auto f5 = p5.get_future(); 180 test_eq("refcount after creating future", s5->refs(), 2); 181 } 182 test_eq("refcount after future is destroyed", s5->refs(), 1); 183 test_eq("state not destroyed with future", mock::destructor_calls, 0U); 184 } 185 test_eq("state destroyed with promise", mock::destructor_calls, 1U); 186 187 mock::clear(); 188 { 189 std::aux::shared_state<std::test::mock>* s6{}; 190 std::future<std::test::mock> f6{}; 191 { 192 std::promise<std::test::mock> p6{}; 193 s6 = p6.__state(); 194 { 195 f6 = p6.get_future(); 196 test_eq("move construction only increments refcount once", s6->refs(), 2); 197 } 198 } 199 test_eq("refcount after promise is destroyed", s6->refs(), 1); 200 test_eq("state not destroyed with promise", mock::destructor_calls, 0U); 201 } 202 test_eq("state destroyed with future", mock::destructor_calls, 1U); 203 204 auto [p7, f7, s7] = prepare<int>(); 205 auto res7 = f7.wait_for(5ms); 206 test_eq("wait_for timeout", res7, std::future_status::timeout); 207 208 res7 = f7.wait_until(std::chrono::system_clock::now() + 5ms); 209 test_eq("wait_until timeout", res7, std::future_status::timeout); 210 211 std::thread t7{ 212 [&p7](){ 213 std::this_thread::sleep_for(5ms); 214 p7.set_value(42); 215 } 216 }; 217 res7 = f7.wait_for(10ms); 218 test_eq("wait_for ready", res7, std::future_status::ready); 219 220 auto [p8, f8, s8] = prepare<int>(); 221 std::thread t8{ 222 [&p8](){ 223 std::this_thread::sleep_for(5ms); 224 p8.set_value(42); 225 } 226 }; 227 228 auto res8 = f8.wait_until(std::chrono::system_clock::now() + 10ms); 229 test_eq("wait_until ready", res8, std::future_status::ready); 230 231 int x{}; 232 std::promise<int&> p9{}; 233 std::future<int&> f9 = p9.get_future(); 234 p9.set_value(x); 235 int& y = f9.get(); 236 237 test_eq("reference equal to original", x, y); 238 239 ++x; 240 test_eq("equal after modifying original", x, y); 241 242 ++y; 243 test_eq("equal after modifying reference", x, y); 61 244 } 62 245 63 246 void future_test::test_async() 64 247 { 65 // TODO: 248 auto res1 = std::async( 249 [](){ 250 return 42; 251 } 252 ); 253 test_eq("ret async default policy", res1.get(), 42); 254 255 auto res2 = std::async( 256 std::launch::deferred, [](){ 257 return 42; 258 } 259 ); 260 test_eq("ret async deferred policy", res2.get(), 42); 261 262 auto res3 = std::async( 263 std::launch::async, [](){ 264 return 42; 265 } 266 ); 267 test_eq("ret async async policy", res3.get(), 42); 268 269 int x{}; 270 auto res4 = std::async( 271 [&x](){ 272 x = 42; 273 } 274 ); 275 276 res4.get(); 277 test_eq("void async", x, 42); 66 278 } 67 279 68 280 void future_test::test_packaged_task() 69 281 { 70 // TODO: 282 std::packaged_task<int(int)> pt1{}; 283 test("default constructed packaged_task not valid", !pt1.valid()); 284 285 pt1 = std::packaged_task<int(int)>{ 286 [](int x){ 287 return x + 1; 288 } 289 }; 290 test("packaged_task default constructed and move assigned valid", pt1.valid()); 291 292 auto f1 = pt1.get_future(); 293 test("future from valid packaged_task valid", f1.valid()); 294 295 pt1(10); 296 test_eq("result stored in future correct", f1.get(), 11); 297 298 std::packaged_task<int()> pt2{ 299 [](){ 300 return 42; 301 } 302 }; 303 auto f2 = pt2.get_future(); 304 pt2(); 305 test_eq("no argument packaged_task return value correct", f2.get(), 42); 306 307 pt2.reset(); 308 test_eq("reset causes refcount decrement", f2.__state()->refs(), 1); 309 310 auto f3 = pt2.get_future(); 311 pt2(); 312 test_eq("invocation after reset returns correct value", f3.get(), 42); 313 test("reset recreates state", (f2.__state() != f3.__state())); 71 314 } 72 315 73 316 void future_test::test_shared_future() 74 317 { 75 // TODO: 318 auto [p1, f1, s1] = prepare<int>(); 319 auto sf1 = f1.share(); 320 321 test("future invalid after share", !f1.valid()); 322 test_eq("shared state moved on share", sf1.__state(), s1); 323 test_eq("no refcount increment on share", s1->refs(), 2); 324 325 { 326 auto sf2 = sf1; 327 test_eq("refcount increment on copy", s1->refs(), 3); 328 test_eq("shared state shared between copies", sf1.__state(), sf2.__state()); 329 } 330 test_eq("refcount decrement when copy gets destroyed", s1->refs(), 2); 331 332 auto sf2 = sf1; 333 int res1{}, res2{}; 334 std::thread t1{ 335 [&](){ 336 res1 = sf1.get(); 337 } 338 }; 339 std::thread t2{ 340 [&](){ 341 res2 = sf2.get(); 342 } 343 }; 344 345 std::this_thread::sleep_for(20ms); 346 p1.set_value(42); 347 std::this_thread::sleep_for(20ms); 348 test_eq("first result correct", res1, 42); 349 test_eq("second result correct", res2, 42); 76 350 } 77 351 }
Note:
See TracChangeset
for help on using the changeset viewer.