Changeset 9fe2fd7 in mainline
- Timestamp:
- 2019-07-24T11:44:40Z (5 years ago)
- Branches:
- lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
- Children:
- a448937, f42ee6f
- Parents:
- 9fb280c (diff), 8c0b781 (diff)
Note: this is a merge changeset, the changes displayed below correspond to the merge itself.
Use the(diff)
links above to see all the changes relative to each parent. - git-author:
- Jaroslav Jindrak <Dzejrou@…> (2019-07-24 11:44:40)
- git-committer:
- GitHub <noreply@…> (2019-07-24 11:44:40)
- Location:
- uspace
- Files:
-
- 8 added
- 13 edited
- 1 moved
Legend:
- Unmodified
- Added
- Removed
-
uspace/app/cpptest/main.cpp
r9fb280c r9fe2fd7 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/Makefile
r9fb280c r9fe2fd7 47 47 src/mutex.cpp \ 48 48 src/new.cpp \ 49 src/refcount_obj.cpp \ 49 50 src/shared_mutex.cpp \ 50 51 src/stdexcept.cpp \ … … 63 64 src/__bits/test/deque.cpp \ 64 65 src/__bits/test/functional.cpp \ 66 src/__bits/test/future.cpp \ 65 67 src/__bits/test/list.cpp \ 66 68 src/__bits/test/map.cpp \ -
uspace/lib/cpp/include/__bits/chrono.hpp
r9fb280c r9fe2fd7 331 331 { 332 332 using CD = common_type_t<duration<Rep1, Period1>, duration<Rep2, Period2>>; 333 return CD(CD(lhs .count()) + CD(rhs.count()));333 return CD(CD(lhs).count() + CD(rhs).count()); 334 334 } 335 335 -
uspace/lib/cpp/include/__bits/functional/functional.hpp
r9fb280c r9fe2fd7 46 46 decltype(auto) invoke(F&& f, Args&&... args) 47 47 { 48 return aux::INVOKE(forward<F>(f) (forward<Args>(args)...));48 return aux::INVOKE(forward<F>(f),forward<Args>(args)...); 49 49 } 50 50 -
uspace/lib/cpp/include/__bits/memory/shared_payload.hpp
r9fb280c r9fe2fd7 30 30 #define LIBCPP_BITS_MEMORY_SHARED_PAYLOAD 31 31 32 #include <__bits/refcount_obj.hpp> 32 33 #include <cinttypes> 33 34 #include <utility> … … 43 44 namespace std::aux 44 45 { 45 /**46 * At the moment we do not have atomics, change this47 * to std::atomic<long> once we do.48 */49 using refcount_t = long;50 51 46 /** 52 47 * This allows us to construct shared_ptr from … … 66 61 67 62 template<class T> 68 class shared_payload_base 63 class shared_payload_base: public aux::refcount_obj 69 64 { 70 65 public: 71 virtual void destroy() = 0;72 66 virtual T* get() const noexcept = 0; 73 67 74 68 virtual uint8_t* deleter() const noexcept = 0; 75 69 76 virtual void increment() noexcept = 0;77 virtual void increment_weak() noexcept = 0;78 virtual bool decrement() noexcept = 0;79 virtual bool decrement_weak() noexcept = 0;80 virtual refcount_t refs() const noexcept = 0;81 virtual refcount_t weak_refs() const noexcept = 0;82 virtual bool expired() const noexcept = 0;83 70 virtual shared_payload_base* lock() noexcept = 0; 84 71 … … 91 78 public: 92 79 shared_payload(T* ptr, D deleter = D{}) 93 : data_{ptr}, deleter_{deleter}, 94 refcount_{1}, weak_refcount_{1} 80 : data_{ptr}, deleter_{deleter} 95 81 { /* DUMMY BODY */ } 96 82 … … 98 84 shared_payload(Args&&... args) 99 85 : data_{new T{forward<Args>(args)...}}, 100 deleter_{} , refcount_{1}, weak_refcount_{1}86 deleter_{} 101 87 { /* DUMMY BODY */ } 102 88 … … 104 90 shared_payload(allocator_arg_t, Alloc alloc, Args&&... args) 105 91 : data_{alloc.allocate(1)}, 106 deleter_{} , refcount_{1}, weak_refcount_{1}92 deleter_{} 107 93 { 108 94 alloc.construct(data_, forward<Args>(args)...); … … 112 98 shared_payload(D deleter, Alloc alloc, Args&&... args) 113 99 : data_{alloc.allocate(1)}, 114 deleter_{deleter} , refcount_{1}, weak_refcount_{1}100 deleter_{deleter} 115 101 { 116 102 alloc.construct(data_, forward<Args>(args)...); … … 119 105 void destroy() override 120 106 { 121 if ( refs() == 0)107 if (this->refs() == 0) 122 108 { 123 109 if (data_) … … 127 113 } 128 114 129 if ( weak_refs() == 0)115 if (this->weak_refs() == 0) 130 116 delete this; 131 117 } … … 142 128 } 143 129 144 void increment() noexcept override145 {146 __atomic_add_fetch(&refcount_, 1, __ATOMIC_ACQ_REL);147 }148 149 void increment_weak() noexcept override150 {151 __atomic_add_fetch(&weak_refcount_, 1, __ATOMIC_ACQ_REL);152 }153 154 bool decrement() noexcept override155 {156 if (__atomic_sub_fetch(&refcount_, 1, __ATOMIC_ACQ_REL) == 0)157 {158 /**159 * First call to destroy() will delete the held object,160 * so it doesn't matter what the weak_refcount_ is,161 * but we added one and we need to remove it now.162 */163 decrement_weak();164 165 return true;166 }167 else168 return false;169 }170 171 bool decrement_weak() noexcept override172 {173 return __atomic_sub_fetch(&weak_refcount_, 1, __ATOMIC_ACQ_REL) == 0 && refs() == 0;174 }175 176 refcount_t refs() const noexcept override177 {178 return __atomic_load_n(&refcount_, __ATOMIC_RELAXED);179 }180 181 refcount_t weak_refs() const noexcept override182 {183 return __atomic_load_n(&weak_refcount_, __ATOMIC_RELAXED);184 }185 186 bool expired() const noexcept override187 {188 return refs() == 0;189 }190 191 130 shared_payload_base<T>* lock() noexcept override 192 131 { 193 refcount_t rfs = refs();132 refcount_t rfs = this->refs(); 194 133 while (rfs != 0L) 195 134 { 196 if (__atomic_compare_exchange_n(& refcount_, &rfs, rfs + 1,135 if (__atomic_compare_exchange_n(&this->refcount_, &rfs, rfs + 1, 197 136 true, __ATOMIC_RELAXED, 198 137 __ATOMIC_RELAXED)) … … 208 147 T* data_; 209 148 D deleter_; 210 211 /**212 * We're using a trick where refcount_ > 0213 * means weak_refcount_ has 1 added to it,214 * this makes it easier for weak_ptrs that215 * can't decrement the weak_refcount_ to216 * zero with shared_ptrs using this object.217 */218 refcount_t refcount_;219 refcount_t weak_refcount_;220 149 }; 221 150 } -
uspace/lib/cpp/include/__bits/refcount_obj.hpp
r9fb280c r9fe2fd7 1 1 /* 2 * Copyright (c) 201 8Jaroslav Jindrak2 * Copyright (c) 2019 Jaroslav Jindrak 3 3 * All rights reserved. 4 4 * … … 27 27 */ 28 28 29 #ifndef LIBCPP_BITS_RE SULT_OF30 #define LIBCPP_BITS_RE SULT_OF29 #ifndef LIBCPP_BITS_REFCOUNT_OBJ 30 #define LIBCPP_BITS_REFCOUNT_OBJ 31 31 32 /** 33 * TODO: We have two implementations and I can't remember which 34 * one is the correnct one, investigate! 35 */ 36 #include <__bits/invoke.hpp> 37 38 namespace std 32 namespace std::aux 39 33 { 40 34 /** 41 * Note: This doesn't work, C++14 standard allows for F 42 * to be any complete type, our implementation 43 * currently works like the C++11 version where 44 * F has to be callable. 45 * TODO: Fix this. 35 * At the moment we do not have atomics, change this 36 * to std::atomic<long> once we do. 46 37 */ 38 using refcount_t = long; 47 39 48 template<class> 49 struct result_of; 40 class refcount_obj 41 { 42 public: 43 refcount_obj() = default; 50 44 51 template<class F, class... Args> 52 class result_of<F(Args...)>: aux::type_is< 53 decltype(aux::invoke(declval<F>(), declval<ArgTypes>()...)) 54 > 55 { /* DUMMY BODY */ }; 45 void increment() noexcept; 46 void increment_weak() noexcept; 47 bool decrement() noexcept; 48 bool decrement_weak() noexcept; 49 refcount_t refs() const noexcept; 50 refcount_t weak_refs() const noexcept; 51 bool expired() const noexcept; 56 52 57 template<class T> 58 using result_of_t = typename result_of<T>::type; 53 virtual ~refcount_obj() = default; 54 virtual void destroy() = 0; 55 56 protected: 57 /** 58 * We're using a trick where refcount_ > 0 59 * means weak_refcount_ has 1 added to it, 60 * this makes it easier for weak_ptrs that 61 * can't decrement the weak_refcount_ to 62 * zero with shared_ptrs using this object. 63 */ 64 refcount_t refcount_{1}; 65 refcount_t weak_refcount_{1}; 66 }; 59 67 } 60 68 -
uspace/lib/cpp/include/__bits/system_error.hpp
r9fb280c r9fe2fd7 33 33 #include <__bits/string/stringfwd.hpp> 34 34 #include <stdexcept> 35 #include <type_traits> 35 36 36 37 namespace std -
uspace/lib/cpp/include/__bits/test/tests.hpp
r9fb280c r9fe2fd7 1 1 /* 2 * Copyright (c) 201 8Jaroslav Jindrak2 * Copyright (c) 2019 Jaroslav Jindrak 3 3 * All rights reserved. 4 4 * … … 295 295 void test_mutating(); 296 296 }; 297 298 class future_test: public test_suite 299 { 300 public: 301 bool run(bool) override; 302 const char* name() override; 303 private: 304 void test_future(); 305 void test_promise(); 306 void test_future_promise(); 307 void test_async(); 308 void test_packaged_task(); 309 void test_shared_future(); 310 }; 297 311 } 298 312 -
uspace/lib/cpp/include/__bits/thread/future.hpp
r9fb280c r9fe2fd7 30 30 #define LIBCPP_BITS_THREAD_FUTURE 31 31 32 #include <__bits/thread/future_common.hpp> 33 #include <__bits/thread/shared_state.hpp> 34 #include <__bits/utility/forward_move.hpp> 32 35 #include <cassert> 33 #include <memory>34 #include <system_error>35 #include <type_traits>36 36 37 37 namespace std 38 38 { 39 39 /** 40 * 30.6 , futures:40 * 30.6.6, class template future: 41 41 */ 42 42 43 enum class future_errc 44 { // The 5001 start is to not collide with system_error's codes. 45 broken_promise = 5001, 46 future_already_retrieved, 47 promise_already_satisfied, 48 no_state 43 namespace aux 44 { 45 /** 46 * Note: Because of shared_future, this base class 47 * does implement copy constructor and copy 48 * assignment operator. This means that the 49 * children (std::future) need to delete this 50 * constructor and operator themselves. 51 */ 52 template<class R> 53 class future_base 54 { 55 public: 56 future_base() noexcept 57 : state_{nullptr} 58 { /* DUMMY BODY */ } 59 60 future_base(const future_base& rhs) 61 : state_{rhs.state_} 62 { 63 state_->increment(); 64 } 65 66 future_base(future_base&& rhs) noexcept 67 : state_{move(rhs.state_)} 68 { 69 rhs.state_ = nullptr; 70 } 71 72 future_base(aux::shared_state<R>* state) 73 : state_{state} 74 { 75 /** 76 * Note: This is a custom non-standard constructor that allows 77 * us to create a future directly from a shared state. This 78 * should never be a problem as aux::shared_state is a private 79 * type and future has no constructor templates. 80 */ 81 } 82 83 virtual ~future_base() 84 { 85 release_state_(); 86 } 87 88 future_base& operator=(const future_base& rhs) 89 { 90 release_state_(); 91 state_ = rhs.state_; 92 93 state_->increment(); 94 95 return *this; 96 } 97 98 future_base& operator=(future_base&& rhs) noexcept 99 { 100 release_state_(); 101 state_ = move(rhs.state_); 102 rhs.state_ = nullptr; 103 104 return *this; 105 } 106 107 bool valid() const noexcept 108 { 109 return state_ != nullptr; 110 } 111 112 void wait() const noexcept 113 { 114 assert(state_); 115 116 state_->wait(); 117 } 118 119 template<class Rep, class Period> 120 future_status 121 wait_for(const chrono::duration<Rep, Period>& rel_time) const 122 { 123 assert(state_); 124 125 return state_->wait_for(rel_time); 126 } 127 128 template<class Clock, class Duration> 129 future_status 130 wait_until( 131 const chrono::time_point<Clock, Duration>& abs_time 132 ) const 133 { 134 assert(state_); 135 136 return state_->wait_until(abs_time); 137 } 138 139 protected: 140 void release_state_() 141 { 142 if (!state_) 143 return; 144 145 /** 146 * Note: This is the 'release' move described in 147 * 30.6.4 (5). 148 * Last reference to state -> destroy state. 149 * Decrement refcount of state otherwise. 150 * Will not block, unless all following hold: 151 * 1) State was created by call to std::async. 152 * 2) State is not yet ready. 153 * 3) This was the last reference to the shared state. 154 */ 155 if (state_->decrement()) 156 { 157 /** 158 * The destroy call handles the special case 159 * when 1) - 3) hold. 160 */ 161 state_->destroy(); 162 delete state_; 163 state_ = nullptr; 164 } 165 } 166 167 aux::shared_state<R>* state_; 168 }; 169 } 170 171 template<class R> 172 class shared_future; 173 174 template<class R> 175 class future: public aux::future_base<aux::future_inner_t<R>> 176 { 177 friend class shared_future<R>; 178 179 public: 180 future() noexcept 181 : aux::future_base<aux::future_inner_t<R>>{} 182 { /* DUMMY BODY */ } 183 184 future(const future&) = delete; 185 186 future(future&& rhs) noexcept 187 : aux::future_base<aux::future_inner_t<R>>{move(rhs)} 188 { /* DUMMY BODY */ } 189 190 future(aux::shared_state<aux::future_inner_t<R>>* state) 191 : aux::future_base<aux::future_inner_t<R>>{state} 192 { /* DUMMY BODY */ } 193 194 future& operator=(const future&) = delete; 195 196 future& operator=(future&& rhs) noexcept = default; 197 198 shared_future<R> share() 199 { 200 return shared_future<R>{move(*this)}; 201 } 202 203 R get() 204 { 205 assert(this->state_); 206 207 this->wait(); 208 209 if (this->state_->has_exception()) 210 this->state_->throw_stored_exception(); 211 212 if constexpr (!is_same_v<R, void>) 213 { 214 if constexpr (is_reference_v<R>) 215 { 216 assert(this->state_->get()); 217 218 return *this->state_->get(); 219 } 220 else 221 return this->state_->get(); 222 } 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 } 49 235 }; 50 51 enum class launch52 {53 async,54 deferred55 };56 57 enum class future_status58 {59 ready,60 timeout,61 deferred62 };63 64 /**65 * 30.6.2, error handling:66 */67 68 template<>69 struct is_error_code_enum<future_errc>: true_type70 { /* DUMMY BODY */ };71 72 error_code make_error_code(future_errc) noexcept;73 error_condition make_error_condition(future_errc) noexcept;74 75 const error_category& future_category() noexcept;76 77 /**78 * 30.6.3, class future_error:79 */80 81 class future_error: public logic_error82 {83 public:84 future_error(error_code ec);85 86 const error_code& code() const noexcept;87 88 private:89 error_code code_;90 };91 92 /**93 * 30.6.4, shared state:94 */95 96 template<class R>97 class promise98 {99 };100 101 template<class R>102 class promise<R&>103 {104 };105 106 template<>107 class promise<void>108 {109 };110 111 template<class R>112 void swap(promise<R>& lhs, promise<R>& rhs) noexcept113 {114 lhs.swap(rhs);115 }116 117 template<class R, class Alloc>118 struct uses_allocator<promise<R>, Alloc>: true_type119 { /* DUMMY BODY */ };120 121 template<class R>122 class future123 {124 };125 126 template<class R>127 class future<R&>128 {129 };130 131 template<>132 class future<void>133 {134 };135 136 template<class R>137 class shared_future138 {139 };140 141 template<class R>142 class shared_future<R&>143 {144 };145 146 template<>147 class shared_future<void>148 {149 };150 151 template<class>152 class packaged_task; // undefined153 154 template<class R, class... Args>155 class packaged_task<R(Args...)>156 {157 };158 159 template<class R, class... Args>160 void swap(packaged_task<R(Args...)>& lhs, packaged_task<R(Args...)>& rhs) noexcept161 {162 lhs.swap(rhs);163 };164 165 template<class R, class Alloc>166 struct uses_allocator<packaged_task<R>, Alloc>: true_type167 { /* DUMMY BODY */ };168 169 template<class F, class... Args>170 future<result_of_t<decay_t<F>(decay_t<Args>...)>>171 async(F&& f, Args&&... args)172 {173 // TODO: implement174 __unimplemented();175 }176 177 template<class F, class... Args>178 future<result_of_t<decay_t<F>(decay_t<Args>...)>>179 async(launch, F&& f, Args&&... args)180 {181 // TODO: implement182 __unimplemented();183 }184 236 } 185 237 -
uspace/lib/cpp/include/__bits/trycatch.hpp
r9fb280c r9fe2fd7 67 67 68 68 /** 69 * The language allows us to odr-use a variable 70 * that is not defined. We use this to support 71 * macros redefining the catch keyword that are 72 * followed by a block that uses that symbol. 73 * 74 * Normally, that would produce a compiler error 75 * as the declaration of that variale would be removed 76 * with the catch statement, but if we use the following 77 * declaration's name as the name of the caught exception, 78 * all will work well because of this extern declaration. 79 * 80 * Note: We do not follow our usual convention of using 81 * the aux:: namespace because that cannot be used in 82 * variable declaration. 83 */ 84 extern int __exception; 85 86 /** 69 87 * These macros allow us to choose how the program 70 88 * should behave when an exception is thrown … … 87 105 #define LIBCPP_EXCEPTION_IGNORE /* IGNORE */ 88 106 #define LIBCPP_EXCEPTION_HANDLE_THROW LIBCPP_EXCEPTION_IGNORE 89 #define LIBCPP_EXCEPTION_HANDLE_CATCH LIBCPP_EXCEPTION_ HANG107 #define LIBCPP_EXCEPTION_HANDLE_CATCH LIBCPP_EXCEPTION_ABORT 90 108 91 109 #define try if constexpr (::std::aux::try_blocks_allowed) -
uspace/lib/cpp/include/__bits/tuple/tuple.hpp
r9fb280c r9fe2fd7 433 433 }; 434 434 435 template<> 436 class tuple<> 437 { 438 /** 439 * In some cases, e.g. for async() calls 440 * without argument to the functors, we need 441 * zero length tuples, which are provided by 442 * the following specialization. 443 * (Without it we get a resolution conflict between 444 * the default constructor and the Ts... constructor 445 * in the original tuple.) 446 */ 447 448 tuple() = default; 449 450 void swap(tuple&) noexcept 451 { /* DUMMY BODY */ } 452 }; 453 435 454 /** 436 455 * 20.4.2.7, relational operators: -
uspace/lib/cpp/include/future
r9fb280c r9fe2fd7 27 27 */ 28 28 29 #include <__bits/thread/async.hpp> 29 30 #include <__bits/thread/future.hpp> 31 #include <__bits/thread/future_common.hpp> 32 #include <__bits/thread/packaged_task.hpp> 33 #include <__bits/thread/promise.hpp> 34 #include <__bits/thread/shared_future.hpp> 35 #include <__bits/thread/shared_state.hpp> -
uspace/lib/cpp/src/__bits/runtime.cpp
r9fb280c r9fe2fd7 28 28 29 29 #include <__bits/abi.hpp> 30 #include <cassert> 30 31 #include <cstdlib> 31 32 #include <cstdint> … … 207 208 extern "C" void __cxa_end_cleanup() 208 209 { /* DUMMY BODY */ } 210 211 extern "C" int __cxa_thread_atexit(void(*)(void*), void*, void*) 212 { 213 // TODO: needed for thread_local variables 214 __unimplemented(); 215 return 0; 216 } 209 217 } -
uspace/lib/cpp/src/future.cpp
r9fb280c r9fe2fd7 81 81 return code_; 82 82 } 83 84 const char* future_error::what() const noexcept 85 { 86 return code().message().c_str(); 87 } 83 88 }
Note:
See TracChangeset
for help on using the changeset viewer.