* include/std/future (__future_base::_State_base::wait()): Use lambda
expression for predicate and remove redundant test.
(__future_base::_State_base::wait_for()): Return future_status and
use lambda expression for predicate.
(__future_base::_State_base::wait_until()): Likewise.
(__basic_future::wait_for(), __basic_future::wait_until()): Likewise.
(__future_base::_Async_state): Replace with _Async_state_common
class for non-dependent functionality and _Async_state_impl class
template for dependent functionality.
(__future_base::_Async_state_common::_M_join): Serialize attempts to
join thread.
(__future_base::_Async_state_common::_M_run_deferred): Join.
(__future_base::_Async_state::_M_do_run): Replace with lambda.
* src/c++11/future.cc (__future_base::_Async_state_common): Define
destructor, so key function is in the library.
* config/abi/pre/gnu.ver: Add exports for ~_Async_state_common.
* testsuite/30_threads/packaged_task/members/get_future.cc: Expect
future_status return instead of bool.
* testsuite/30_threads/shared_future/members/wait_until.cc: Likewise.
* testsuite/30_threads/shared_future/members/wait_for.cc: Likewise.
* testsuite/30_threads/future/members/wait_until.cc: Likewise.
* testsuite/30_threads/future/members/wait_for.cc: Likewise.
* testsuite/30_threads/promise/members/set_value2.cc: Likewise.
* testsuite/30_threads/promise/members/set_value3.cc: Likewise.
* testsuite/30_threads/promise/members/swap.cc: Likewise.
git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@183788
138bc75d-0d04-0410-961f-
82ee72b054a4
+2012-02-01 Jonathan Wakely <jwakely.gcc@gmail.com>
+
+ PR libstdc++/49204
+ * include/std/future (__future_base::_State_base::wait()): Use lambda
+ expression for predicate and remove redundant test.
+ (__future_base::_State_base::wait_for()): Return future_status and
+ use lambda expression for predicate.
+ (__future_base::_State_base::wait_until()): Likewise.
+ (__basic_future::wait_for(), __basic_future::wait_until()): Likewise.
+ (__future_base::_Async_state): Replace with _Async_state_common
+ class for non-dependent functionality and _Async_state_impl class
+ template for dependent functionality.
+ (__future_base::_Async_state_common::_M_join): Serialize attempts to
+ join thread.
+ (__future_base::_Async_state_common::_M_run_deferred): Join.
+ (__future_base::_Async_state::_M_do_run): Replace with lambda.
+ * src/c++11/future.cc (__future_base::_Async_state_common): Define
+ destructor, so key function is in the library.
+ * config/abi/pre/gnu.ver: Add exports for ~_Async_state_common.
+ * testsuite/30_threads/packaged_task/members/get_future.cc: Expect
+ future_status return instead of bool.
+ * testsuite/30_threads/shared_future/members/wait_until.cc: Likewise.
+ * testsuite/30_threads/shared_future/members/wait_for.cc: Likewise.
+ * testsuite/30_threads/future/members/wait_until.cc: Likewise.
+ * testsuite/30_threads/future/members/wait_for.cc: Likewise.
+ * testsuite/30_threads/promise/members/set_value2.cc: Likewise.
+ * testsuite/30_threads/promise/members/set_value3.cc: Likewise.
+ * testsuite/30_threads/promise/members/swap.cc: Likewise.
+
2012-01-30 Tom Tromey <tromey@redhat.com>
PR libstdc++/51649:
# std::wstring::pop_back()
_ZNSbIwSt11char_traitsIwESaIwEE8pop_backEv;
+ # std::_Async_state_common::~_Async_state_common
+ _ZTINSt13__future_base19_Async_state_commonE;
+ _ZTSNSt13__future_base19_Async_state_commonE;
+ _ZTVNSt13__future_base19_Async_state_commonE;
+ _ZNSt13__future_base19_Async_state_commonD0Ev;
+ _ZNSt13__future_base19_Async_state_commonD1Ev;
+ _ZNSt13__future_base19_Async_state_commonD2Ev;
+
} GLIBCXX_3.4.16;
# Symbols in the support library (libsupc++) have their own tag.
// <future> -*- C++ -*-
-// Copyright (C) 2009, 2010, 2011 Free Software Foundation, Inc.
+// Copyright (C) 2009, 2010, 2011, 2012 Free Software Foundation, Inc.
//
// This file is part of the GNU ISO C++ Library. This library is free
// software; you can redistribute it and/or modify it under the
{
_M_run_deferred();
unique_lock<mutex> __lock(_M_mutex);
- if (!_M_ready())
- _M_cond.wait(__lock, std::bind<bool>(&_State_base::_M_ready, this));
+ _M_cond.wait(__lock, [&] { return _M_ready(); });
return *_M_result;
}
template<typename _Rep, typename _Period>
- bool
+ future_status
wait_for(const chrono::duration<_Rep, _Period>& __rel)
{
unique_lock<mutex> __lock(_M_mutex);
- auto __bound = std::bind<bool>(&_State_base::_M_ready, this);
- return _M_ready() || _M_cond.wait_for(__lock, __rel, __bound);
+ if (_M_cond.wait_for(__lock, __rel, [&] { return _M_ready(); }))
+ return future_status::ready;
+ return future_status::timeout;
}
template<typename _Clock, typename _Duration>
- bool
+ future_status
wait_until(const chrono::time_point<_Clock, _Duration>& __abs)
{
unique_lock<mutex> __lock(_M_mutex);
- auto __bound = std::bind<bool>(&_State_base::_M_ready, this);
- return _M_ready() || _M_cond.wait_until(__lock, __abs, __bound);
+ if (_M_cond.wait_until(__lock, __abs, [&] { return _M_ready(); }))
+ return future_status::ready;
+ return future_status::timeout;
}
void
bool _M_ready() const noexcept { return static_cast<bool>(_M_result); }
+ // Misnamed: waits for completion of async function.
virtual void _M_run_deferred() { }
};
template<typename _BoundFn, typename = typename _BoundFn::result_type>
class _Deferred_state;
+ class _Async_state_common;
+
template<typename _BoundFn, typename = typename _BoundFn::result_type>
- class _Async_state;
+ class _Async_state_impl;
template<typename _Signature>
class _Task_state;
}
template<typename _Rep, typename _Period>
- bool
+ future_status
wait_for(const chrono::duration<_Rep, _Period>& __rel) const
{
_State_base::_S_check(_M_state);
}
template<typename _Clock, typename _Duration>
- bool
+ future_status
wait_until(const chrono::time_point<_Clock, _Duration>& __abs) const
{
_State_base::_S_check(_M_state);
}
};
+ class __future_base::_Async_state_common : public __future_base::_State_base
+ {
+ protected:
+ ~_Async_state_common();
+
+ // Allow non-timed waiting functions to block until the thread completes,
+ // as if joined.
+ virtual void _M_run_deferred() { _M_join(); }
+
+ void _M_join() { std::call_once(_M_once, &thread::join, ref(_M_thread)); }
+
+ thread _M_thread;
+ once_flag _M_once;
+ };
+
template<typename _BoundFn, typename _Res>
- class __future_base::_Async_state final
- : public __future_base::_State_base
+ class __future_base::_Async_state_impl final
+ : public __future_base::_Async_state_common
{
public:
explicit
- _Async_state(_BoundFn&& __fn)
- : _M_result(new _Result<_Res>()), _M_fn(std::move(__fn)),
- _M_thread(mem_fn(&_Async_state::_M_do_run), this)
- { }
-
- ~_Async_state() { _M_thread.join(); }
-
- private:
- void _M_do_run()
+ _Async_state_impl(_BoundFn&& __fn)
+ : _M_result(new _Result<_Res>()), _M_fn(std::move(__fn))
{
- _M_set_result(_S_task_setter(_M_result, _M_fn));
+ _M_thread = std::thread{ [this] {
+ _M_set_result(_S_task_setter(_M_result, _M_fn));
+ } };
}
+ private:
typedef __future_base::_Ptr<_Result<_Res>> _Ptr_type;
_Ptr_type _M_result;
_BoundFn _M_fn;
- thread _M_thread;
};
template<typename _BoundFn>
__future_base::_S_make_async_state(_BoundFn&& __fn)
{
typedef typename remove_reference<_BoundFn>::type __fn_type;
- typedef _Async_state<__fn_type> __state_type;
+ typedef _Async_state_impl<__fn_type> __state_type;
return std::make_shared<__state_type>(std::move(__fn));
}
// future -*- C++ -*-
-// Copyright (C) 2009, 2010, 2011 Free Software Foundation, Inc.
+// Copyright (C) 2009, 2010, 2011, 2012 Free Software Foundation, Inc.
//
// This file is part of the GNU ISO C++ Library. This library is free
// software; you can redistribute it and/or modify it under the
__future_base::_Result_base::~_Result_base() = default;
__future_base::_State_base::~_State_base() = default;
+
+ __future_base::_Async_state_common::~_Async_state_common() { _M_join(); }
+
+ // Explicit instantiation due to -fno-implicit-instantiation.
+ template void call_once(once_flag&, void (thread::*&&)(), reference_wrapper<thread>&&);
#endif
_GLIBCXX_END_NAMESPACE_VERSION
std::chrono::milliseconds delay(100);
- VERIFY( !f1.wait_for(delay) );
+ VERIFY( f1.wait_for(delay) == std::future_status::timeout );
p1.set_value(1);
auto before = std::chrono::system_clock::now();
- VERIFY( f1.wait_for(delay) );
+ VERIFY( f1.wait_for(delay) == std::future_status::ready );
VERIFY( std::chrono::system_clock::now() < (before + delay) );
}
std::future<int> f1(p1.get_future());
auto when = make_time(10);
- VERIFY( !f1.wait_until(when) );
+ VERIFY( f1.wait_until(when) == std::future_status::timeout );
VERIFY( std::chrono::system_clock::now() >= when );
p1.set_value(1);
when = make_time(100);
- VERIFY( f1.wait_until(when) );
+ VERIFY( f1.wait_until(when) == std::future_status::ready );
VERIFY( std::chrono::system_clock::now() < when );
}
std::packaged_task<int&(int&)> p1(inc);
std::future<int&> f1 = p1.get_future();
+ std::chrono::milliseconds delay(1);
VERIFY( f1.valid() );
- VERIFY( !f1.wait_for(std::chrono::milliseconds(1)) );
+ VERIFY( f1.wait_for(delay) == std::future_status::timeout );
int i1 = 0;
test = true;
}
- VERIFY( f1.wait_for(std::chrono::milliseconds(1)) );
+ std::chrono::milliseconds delay(1);
+ VERIFY( f1.wait_for(delay) == std::future_status::ready );
VERIFY( f1.get() == 1 );
VERIFY( test );
}
test = true;
}
- VERIFY( f1.wait_for(std::chrono::milliseconds(1)) );
+ std::chrono::milliseconds delay(1);
+ VERIFY( f1.wait_for(delay) == std::future_status::ready );
VERIFY( f1.get() == 3 );
VERIFY( test );
}
std::promise<tester> pglobal;
std::future<tester> fglobal = pglobal.get_future();
+auto delay = std::chrono::milliseconds(1);
+
tester::tester(int)
{
bool test __attribute__((unused)) = true;
- VERIFY (!fglobal.wait_for(std::chrono::milliseconds(1)));
+ VERIFY (fglobal.wait_for(delay) == std::future_status::timeout);
}
tester::tester(const tester&)
{
bool test __attribute__((unused)) = true;
// if this copy happens while a mutex is locked next line could deadlock:
- VERIFY (!fglobal.wait_for(std::chrono::milliseconds(1)));
+ VERIFY (fglobal.wait_for(delay) == std::future_status::timeout);
}
tester& tester::operator=(const tester&)
{
bool test __attribute__((unused)) = true;
// if this copy happens while a mutex is locked next line could deadlock:
- VERIFY (!fglobal.wait_for(std::chrono::milliseconds(1)));
+ VERIFY (fglobal.wait_for(delay) == std::future_status::timeout);
return *this;
}
pglobal.set_value( tester(1) );
- VERIFY( fglobal.wait_for(std::chrono::milliseconds(1)) );
+ VERIFY (fglobal.wait_for(delay) == std::future_status::ready);
}
int main()
std::promise<int> p2;
p1.set_value(1);
p1.swap(p2);
- VERIFY( !p1.get_future().wait_for(std::chrono::milliseconds(1)) );
- VERIFY( p2.get_future().wait_for(std::chrono::milliseconds(1)) );
+ auto delay = std::chrono::milliseconds(1);
+ VERIFY( p1.get_future().wait_for(delay) == std::future_status::timeout );
+ VERIFY( p2.get_future().wait_for(delay) == std::future_status::ready );
}
int main()
std::chrono::milliseconds delay(100);
- VERIFY( !f1.wait_for(delay) );
- VERIFY( !f2.wait_for(delay) );
+ VERIFY( f1.wait_for(delay) == std::future_status::timeout );
+ VERIFY( f2.wait_for(delay) == std::future_status::timeout );
p1.set_value(1);
auto before = std::chrono::system_clock::now();
- VERIFY( f1.wait_for(delay) );
- VERIFY( f2.wait_for(delay) );
+ VERIFY( f1.wait_for(delay) == std::future_status::ready );
+ VERIFY( f2.wait_for(delay) == std::future_status::ready );
VERIFY( std::chrono::system_clock::now() < (before + 2*delay) );
}
std::shared_future<int> f2(f1);
auto when = make_time(10);
- VERIFY( !f1.wait_until(make_time(10)) );
+ VERIFY( f1.wait_until(make_time(10)) == std::future_status::timeout );
VERIFY( std::chrono::system_clock::now() >= when );
when = make_time(10);
- VERIFY( !f2.wait_until(make_time(10)) );
+ VERIFY( f2.wait_until(make_time(10)) == std::future_status::timeout );
VERIFY( std::chrono::system_clock::now() >= when );
p1.set_value(1);
when = make_time(100);
- VERIFY( f1.wait_until(when) );
- VERIFY( f2.wait_until(when) );
+ VERIFY( f1.wait_until(when) == std::future_status::ready );
+ VERIFY( f2.wait_until(when) == std::future_status::ready );
VERIFY( std::chrono::system_clock::now() < when );
}