diff options
| author | Howard Hinnant <hhinnant@apple.com> | 2011-05-16 19:05:11 +0000 |
|---|---|---|
| committer | Howard Hinnant <hhinnant@apple.com> | 2011-05-16 19:05:11 +0000 |
| commit | 872a91167ebe2780f0b899c392bce491a0573bfa (patch) | |
| tree | 76f7a98764611f846691586c0b58ab603a378f0d | |
| parent | 8df61ea84d65ecfa9e78d8c6f7631d515d51d560 (diff) | |
| download | bcm5719-llvm-872a91167ebe2780f0b899c392bce491a0573bfa.tar.gz bcm5719-llvm-872a91167ebe2780f0b899c392bce491a0573bfa.zip | |
Brought call_once variadic call up to current spec, which allows move-only functors and move-only arguments, but disallows functors with non-const lvalue reference parameters.
llvm-svn: 131414
| -rw-r--r-- | libcxx/include/mutex | 45 | ||||
| -rw-r--r-- | libcxx/test/thread/thread.mutex/thread.once/thread.once.callonce/call_once.pass.cpp | 20 |
2 files changed, 61 insertions, 4 deletions
diff --git a/libcxx/include/mutex b/libcxx/include/mutex index 21d38342dd1..fcfe4b71d89 100644 --- a/libcxx/include/mutex +++ b/libcxx/include/mutex @@ -175,6 +175,9 @@ template<class Callable, class ...Args> #include <__config> #include <__mutex_base> #include <functional> +#ifndef _LIBCPP_HAS_NO_VARIADICS +#include <tuple> +#endif #pragma GCC system_header @@ -455,6 +458,39 @@ private: #endif // _LIBCPP_HAS_NO_VARIADICS }; +#ifndef _LIBCPP_HAS_NO_VARIADICS + +template <class _F> +class __call_once_param +{ + _F __f_; +public: +#ifndef _LIBCPP_HAS_NO_RVALUE_REFERENCES + _LIBCPP_INLINE_VISIBILITY + explicit __call_once_param(_F&& __f) : __f_(_STD::move(__f)) {} +#else + _LIBCPP_INLINE_VISIBILITY + explicit __call_once_param(const _F& __f) : __f_(__f) {} +#endif + + _LIBCPP_INLINE_VISIBILITY + void operator()() + { + typedef typename __make_tuple_indices<tuple_size<_F>::value, 1>::type _Index; + __execute(_Index()); + } + +private: + template <size_t ..._Indices> + _LIBCPP_INLINE_VISIBILITY + void __execute(__tuple_indices<_Indices...>) + { + _STD::move(_STD::get<0>(__f_))(_STD::move(_STD::get<_Indices>(__f_))...); + } +}; + +#else + template <class _F> class __call_once_param { @@ -475,6 +511,8 @@ public: } }; +#endif + template <class _F> void __call_once_proxy(void* __vp) @@ -494,10 +532,9 @@ call_once(once_flag& __flag, _Callable&& __func, _Args&&... __args) { if (__builtin_expect(__flag.__state_ , ~0ul) != ~0ul) { - typedef decltype(std::bind(std::forward<_Callable>(__func), - std::forward<_Args>(__args)...)) _G; - __call_once_param<_G> __p(std::bind(std::forward<_Callable>(__func), - std::forward<_Args>(__args)...)); + typedef tuple<typename decay<_Callable>::type, typename decay<_Args>::type...> _G; + __call_once_param<_G> __p(_G(__decay_copy(_STD::forward<_Callable>(__func)), + __decay_copy(_STD::forward<_Args>(__args))...)); __call_once(__flag.__state_, &__p, &__call_once_proxy<_G>); } } diff --git a/libcxx/test/thread/thread.mutex/thread.once/thread.once.callonce/call_once.pass.cpp b/libcxx/test/thread/thread.mutex/thread.once/thread.once.callonce/call_once.pass.cpp index 68ee43946b4..b4f76b45c5b 100644 --- a/libcxx/test/thread/thread.mutex/thread.once/thread.once.callonce/call_once.pass.cpp +++ b/libcxx/test/thread/thread.mutex/thread.once/thread.once.callonce/call_once.pass.cpp @@ -129,6 +129,22 @@ void f42() std::call_once(flg41, init41); } +#ifndef _LIBCPP_HAS_NO_VARIADICS + +class MoveOnly +{ + MoveOnly(const MoveOnly&); +public: + MoveOnly() {} + MoveOnly(MoveOnly&&) {} + + void operator()(MoveOnly&&) + { + } +}; + +#endif + int main() { // check basic functionality @@ -174,5 +190,9 @@ int main() t1.join(); assert(init2::called == 5); } + { + std::once_flag f; + std::call_once(f, MoveOnly(), MoveOnly()); + } #endif // _LIBCPP_HAS_NO_VARIADICS } |

