Loop in std::this_thread sleep functions
PR libstdc++/60421 * include/std/thread (this_thread::sleep_for): Retry on EINTR. (this_thread::sleep_until): Retry if time not reached. * src/c++11/thread.cc (__sleep_for): Retry on EINTR. * testsuite/30_threads/this_thread/60421.cc: Test interruption and non-steady clocks. From-SVN: r230183
This commit is contained in:
parent
f83e226207
commit
f55e699d3d
@ -1,3 +1,12 @@
|
||||
2015-11-11 Jonathan Wakely <jwakely@redhat.com>
|
||||
|
||||
PR libstdc++/60421
|
||||
* include/std/thread (this_thread::sleep_for): Retry on EINTR.
|
||||
(this_thread::sleep_until): Retry if time not reached.
|
||||
* src/c++11/thread.cc (__sleep_for): Retry on EINTR.
|
||||
* testsuite/30_threads/this_thread/60421.cc: Test interruption and
|
||||
non-steady clocks.
|
||||
|
||||
2015-11-11 Ville Voutilainen <ville.voutilainen@gmail.com>
|
||||
|
||||
LWG 2510, make the default constructors of library tag types
|
||||
|
@ -297,7 +297,8 @@ _GLIBCXX_END_NAMESPACE_VERSION
|
||||
static_cast<std::time_t>(__s.count()),
|
||||
static_cast<long>(__ns.count())
|
||||
};
|
||||
::nanosleep(&__ts, 0);
|
||||
while (::nanosleep(&__ts, &__ts) == -1 && errno == EINTR)
|
||||
{ }
|
||||
#else
|
||||
__sleep_for(__s, __ns);
|
||||
#endif
|
||||
@ -309,8 +310,17 @@ _GLIBCXX_END_NAMESPACE_VERSION
|
||||
sleep_until(const chrono::time_point<_Clock, _Duration>& __atime)
|
||||
{
|
||||
auto __now = _Clock::now();
|
||||
if (__now < __atime)
|
||||
sleep_for(__atime - __now);
|
||||
if (_Clock::is_steady)
|
||||
{
|
||||
if (__now < __atime)
|
||||
sleep_for(__atime - __now);
|
||||
return;
|
||||
}
|
||||
while (__now < __atime)
|
||||
{
|
||||
sleep_for(__atime - __now);
|
||||
__now = _Clock::now();
|
||||
}
|
||||
}
|
||||
|
||||
_GLIBCXX_END_NAMESPACE_VERSION
|
||||
|
@ -221,7 +221,8 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
|
||||
static_cast<std::time_t>(__s.count()),
|
||||
static_cast<long>(__ns.count())
|
||||
};
|
||||
::nanosleep(&__ts, 0);
|
||||
while (::nanosleep(&__ts, &__ts) == -1 && errno == EINTR)
|
||||
{ }
|
||||
#elif defined(_GLIBCXX_HAVE_SLEEP)
|
||||
# ifdef _GLIBCXX_HAVE_USLEEP
|
||||
::sleep(__s.count());
|
||||
|
@ -15,12 +15,19 @@
|
||||
// with this library; see the file COPYING3. If not see
|
||||
// <http://www.gnu.org/licenses/>.
|
||||
|
||||
// { dg-options "-std=gnu++11" }
|
||||
// { dg-do run { target *-*-freebsd* *-*-dragonfly* *-*-netbsd* *-*-linux* *-*-gnu* *-*-solaris* *-*-cygwin *-*-rtems* *-*-darwin* powerpc-ibm-aix* } }
|
||||
// { dg-options " -std=gnu++11 -pthread" { target *-*-freebsd* *-*-dragonfly* *-*-netbsd* *-*-linux* *-*-gnu* powerpc-ibm-aix* } }
|
||||
// { dg-options " -std=gnu++11 -pthreads" { target *-*-solaris* } }
|
||||
// { dg-options " -std=gnu++11 " { target *-*-cygwin *-*-rtems* *-*-darwin* } }
|
||||
// { dg-require-cstdint "" }
|
||||
// { dg-require-gthreads "" }
|
||||
// { dg-require-time "" }
|
||||
|
||||
#include <thread>
|
||||
#include <chrono>
|
||||
#include <atomic>
|
||||
#include <cstdint>
|
||||
#include <signal.h>
|
||||
#include <testsuite_hooks.h>
|
||||
|
||||
void
|
||||
@ -28,11 +35,64 @@ test01()
|
||||
{
|
||||
std::this_thread::sleep_for(std::chrono::seconds(0));
|
||||
std::this_thread::sleep_for(std::chrono::seconds(-1));
|
||||
std::this_thread::sleep_for(std::chrono::duration<uint64_t>::zero());
|
||||
std::this_thread::sleep_for(std::chrono::duration<std::uint64_t>::zero());
|
||||
}
|
||||
|
||||
void
|
||||
test02()
|
||||
{
|
||||
bool test __attribute__((unused)) = true;
|
||||
|
||||
// test interruption of this_thread::sleep_for() by a signal
|
||||
struct sigaction sa{ };
|
||||
sa.sa_handler = +[](int) { };
|
||||
sigaction(SIGUSR1, &sa, 0);
|
||||
bool result = false;
|
||||
std::atomic<bool> sleeping{false};
|
||||
std::thread t([&result, &sleeping] {
|
||||
auto start = std::chrono::system_clock::now();
|
||||
auto time = std::chrono::seconds(3);
|
||||
sleeping = true;
|
||||
std::this_thread::sleep_for(time);
|
||||
result = std::chrono::system_clock::now() >= (start + time);
|
||||
});
|
||||
while (!sleeping) { }
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(500));
|
||||
pthread_kill(t.native_handle(), SIGUSR1);
|
||||
t.join();
|
||||
VERIFY( result );
|
||||
}
|
||||
|
||||
struct slow_clock
|
||||
{
|
||||
using rep = std::chrono::system_clock::rep;
|
||||
using period = std::chrono::system_clock::period;
|
||||
using duration = std::chrono::system_clock::duration;
|
||||
using time_point = std::chrono::time_point<slow_clock, duration>;
|
||||
static constexpr bool is_steady = false;
|
||||
|
||||
static time_point now()
|
||||
{
|
||||
auto real = std::chrono::system_clock::now();
|
||||
return time_point{real.time_since_epoch() / 2};
|
||||
}
|
||||
};
|
||||
|
||||
void
|
||||
test03()
|
||||
{
|
||||
bool test __attribute__((unused)) = true;
|
||||
|
||||
// test that this_thread::sleep_until() handles clock adjustments
|
||||
auto when = slow_clock::now() + std::chrono::seconds(2);
|
||||
std::this_thread::sleep_until(when);
|
||||
VERIFY( slow_clock::now() >= when );
|
||||
}
|
||||
|
||||
int
|
||||
main()
|
||||
{
|
||||
test01();
|
||||
test02();
|
||||
test03();
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user