mirror of
https://gcc.gnu.org/git/gcc.git
synced 2024-11-24 03:14:08 +08:00
libstdc++: Make std::this_thread functions work without gthreads
The only function in namespace std::this_thread that actually depends on
thread support being present is this_thread::get_id(). The other
functions (yield, sleep_for and sleep_until) can be defined for targets
without gthreads.
A small change is needed in std::this_thread::sleep_for which currently
uses the __gthread_time_t typedef. Since it just calls nanosleep
directly, it should use timespec directly instead of the typedef.
Even std::this_thread::get_id() could be made to work, the only
difficulty is that it returns a value of type std:🧵:id and
std::thread is only defined when gthreads support exists.
libstdc++-v3/ChangeLog:
* include/std/thread [!_GLIBCXX_HAS_GTHREADS] (this_thread::yield)
(this_thread::sleep_until): Define.
[!_GLIBCXX_HAS_GTHREADS] (this_thread::sleep_for): Define. Replace
use of __gthread_time_t typedef with timespec.
* src/c++11/thread.cc [!_GLIBCXX_HAS_GTHREADS] (__sleep_for):
Likewise.
* testsuite/30_threads/this_thread/2.cc: Moved to...
* testsuite/30_threads/this_thread/yield.cc: ...here.
* testsuite/30_threads/this_thread/3.cc: Moved to...
* testsuite/30_threads/this_thread/sleep_for-mt.cc: ...here.
* testsuite/30_threads/this_thread/4.cc: Moved to...
* testsuite/30_threads/this_thread/sleep_until-mt.cc: ...here.
* testsuite/30_threads/this_thread/58038.cc: Add
dg-require-sleep.
* testsuite/30_threads/this_thread/60421.cc: Likewise.
* testsuite/30_threads/this_thread/sleep_for.cc: New test.
* testsuite/30_threads/this_thread/sleep_until.cc: New test.
This commit is contained in:
parent
7840b4dc05
commit
5bbb1f3000
@ -35,12 +35,16 @@
|
||||
# include <bits/c++0x_warning.h>
|
||||
#else
|
||||
|
||||
#include <bits/c++config.h>
|
||||
#include <chrono> // std::chrono::*
|
||||
|
||||
#ifdef _GLIBCXX_USE_NANOSLEEP
|
||||
# include <cerrno> // errno, EINTR
|
||||
# include <time.h> // nanosleep
|
||||
#endif
|
||||
|
||||
#if defined(_GLIBCXX_HAS_GTHREADS)
|
||||
#include <bits/gthr.h>
|
||||
|
||||
#include <chrono> // std::chrono::*
|
||||
#include <memory> // std::unique_ptr
|
||||
#include <tuple> // std::tuple
|
||||
|
||||
@ -49,14 +53,11 @@
|
||||
# include <stop_token> // std::stop_source, std::stop_token, std::nostopstate
|
||||
#endif
|
||||
|
||||
#ifdef _GLIBCXX_USE_NANOSLEEP
|
||||
# include <cerrno> // errno, EINTR
|
||||
# include <time.h> // nanosleep
|
||||
#endif
|
||||
|
||||
#include <bits/functional_hash.h> // std::hash
|
||||
#include <bits/invoke.h> // std::__invoke
|
||||
|
||||
#endif // _GLIBCXX_HAS_GTHREADS
|
||||
|
||||
namespace std _GLIBCXX_VISIBILITY(default)
|
||||
{
|
||||
_GLIBCXX_BEGIN_NAMESPACE_VERSION
|
||||
@ -69,6 +70,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
|
||||
* @{
|
||||
*/
|
||||
|
||||
#if defined(_GLIBCXX_HAS_GTHREADS)
|
||||
/// thread
|
||||
class thread
|
||||
{
|
||||
@ -352,6 +354,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
|
||||
else
|
||||
return __out << __id._M_thread;
|
||||
}
|
||||
#endif // _GLIBCXX_HAS_GTHREADS
|
||||
|
||||
/** @namespace std::this_thread
|
||||
* @brief ISO C++ 2011 namespace for interacting with the current thread
|
||||
@ -360,6 +363,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
|
||||
*/
|
||||
namespace this_thread
|
||||
{
|
||||
#if defined _GLIBCXX_HAS_GTHREADS
|
||||
/// get_id
|
||||
inline thread::id
|
||||
get_id() noexcept
|
||||
@ -374,12 +378,13 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
|
||||
#endif
|
||||
return thread::id(__gthread_self());
|
||||
}
|
||||
#endif // _GLIBCXX_HAS_GTHREADS
|
||||
|
||||
/// yield
|
||||
inline void
|
||||
yield() noexcept
|
||||
{
|
||||
#ifdef _GLIBCXX_USE_SCHED_YIELD
|
||||
#if defined _GLIBCXX_HAS_GTHREADS && defined _GLIBCXX_USE_SCHED_YIELD
|
||||
__gthread_yield();
|
||||
#endif
|
||||
}
|
||||
@ -397,7 +402,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
|
||||
auto __s = chrono::duration_cast<chrono::seconds>(__rtime);
|
||||
auto __ns = chrono::duration_cast<chrono::nanoseconds>(__rtime - __s);
|
||||
#ifdef _GLIBCXX_USE_NANOSLEEP
|
||||
__gthread_time_t __ts =
|
||||
struct ::timespec __ts =
|
||||
{
|
||||
static_cast<std::time_t>(__s.count()),
|
||||
static_cast<long>(__ns.count())
|
||||
@ -432,8 +437,6 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
|
||||
}
|
||||
}
|
||||
|
||||
// @} group threads
|
||||
|
||||
#ifdef __cpp_lib_jthread
|
||||
|
||||
class jthread
|
||||
@ -562,8 +565,10 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
|
||||
thread _M_thread;
|
||||
};
|
||||
#endif // __cpp_lib_jthread
|
||||
|
||||
// @} group threads
|
||||
|
||||
_GLIBCXX_END_NAMESPACE_VERSION
|
||||
} // namespace
|
||||
#endif // _GLIBCXX_HAS_GTHREADS
|
||||
#endif // C++11
|
||||
#endif // _GLIBCXX_THREAD
|
||||
|
@ -29,6 +29,16 @@
|
||||
#include <cerrno>
|
||||
#include <cxxabi_forced.h>
|
||||
|
||||
#ifndef _GLIBCXX_USE_NANOSLEEP
|
||||
# ifdef _GLIBCXX_HAVE_SLEEP
|
||||
# include <unistd.h>
|
||||
# elif defined(_GLIBCXX_HAVE_WIN32_SLEEP)
|
||||
# include <windows.h>
|
||||
# else
|
||||
# error "No sleep function known for this target"
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#ifdef _GLIBCXX_HAS_GTHREADS
|
||||
|
||||
#if defined(_GLIBCXX_USE_GET_NPROCS)
|
||||
@ -59,16 +69,6 @@ static inline int get_nprocs()
|
||||
# define _GLIBCXX_NPROCS 0
|
||||
#endif
|
||||
|
||||
#ifndef _GLIBCXX_USE_NANOSLEEP
|
||||
# ifdef _GLIBCXX_HAVE_SLEEP
|
||||
# include <unistd.h>
|
||||
# elif defined(_GLIBCXX_HAVE_WIN32_SLEEP)
|
||||
# include <windows.h>
|
||||
# else
|
||||
# error "No sleep function known for this target"
|
||||
# endif
|
||||
#endif
|
||||
|
||||
namespace std _GLIBCXX_VISIBILITY(default)
|
||||
{
|
||||
extern "C"
|
||||
@ -180,13 +180,21 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
|
||||
return __n;
|
||||
}
|
||||
|
||||
_GLIBCXX_END_NAMESPACE_VERSION
|
||||
} // namespace std
|
||||
|
||||
#endif // _GLIBCXX_HAS_GTHREADS
|
||||
|
||||
namespace std _GLIBCXX_VISIBILITY(default)
|
||||
{
|
||||
_GLIBCXX_BEGIN_NAMESPACE_VERSION
|
||||
namespace this_thread
|
||||
{
|
||||
void
|
||||
__sleep_for(chrono::seconds __s, chrono::nanoseconds __ns)
|
||||
{
|
||||
#ifdef _GLIBCXX_USE_NANOSLEEP
|
||||
__gthread_time_t __ts =
|
||||
struct ::timespec __ts =
|
||||
{
|
||||
static_cast<std::time_t>(__s.count()),
|
||||
static_cast<long>(__ns.count())
|
||||
@ -231,8 +239,5 @@ namespace this_thread
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
_GLIBCXX_END_NAMESPACE_VERSION
|
||||
} // namespace std
|
||||
|
||||
#endif // _GLIBCXX_HAS_GTHREADS
|
||||
|
@ -17,6 +17,7 @@
|
||||
|
||||
// { dg-do run { target c++11 } }
|
||||
// { dg-require-time "" }
|
||||
// { dg-require-sleep "" }
|
||||
|
||||
#include <thread>
|
||||
#include <chrono>
|
||||
|
@ -22,6 +22,7 @@
|
||||
// { dg-require-cstdint "" }
|
||||
// { dg-require-gthreads "" }
|
||||
// { dg-require-time "" }
|
||||
// { dg-require-sleep "" }
|
||||
|
||||
#include <thread>
|
||||
#include <chrono>
|
||||
|
43
libstdc++-v3/testsuite/30_threads/this_thread/sleep_for.cc
Normal file
43
libstdc++-v3/testsuite/30_threads/this_thread/sleep_for.cc
Normal file
@ -0,0 +1,43 @@
|
||||
// { dg-do run { target c++11 } }
|
||||
// { dg-require-sleep "" }
|
||||
|
||||
// Copyright (C) 2020 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
|
||||
// terms of the GNU General Public License as published by the
|
||||
// Free Software Foundation; either version 3, or (at your option)
|
||||
// any later version.
|
||||
|
||||
// This library is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
|
||||
// You should have received a copy of the GNU General Public License along
|
||||
// with this library; see the file COPYING3. If not see
|
||||
// <http://www.gnu.org/licenses/>.
|
||||
|
||||
#include <chrono>
|
||||
#include <thread>
|
||||
#include <testsuite_hooks.h>
|
||||
|
||||
// This tests this_thread::sleep_until without using -pthread
|
||||
|
||||
namespace chr = std::chrono;
|
||||
|
||||
void
|
||||
test01()
|
||||
{
|
||||
chr::system_clock::time_point begin = chr::system_clock::now();
|
||||
chr::microseconds ms(500);
|
||||
|
||||
std::this_thread::sleep_for(ms);
|
||||
|
||||
VERIFY( (chr::system_clock::now() - begin) >= ms );
|
||||
}
|
||||
|
||||
int main()
|
||||
{
|
||||
test01();
|
||||
}
|
43
libstdc++-v3/testsuite/30_threads/this_thread/sleep_until.cc
Normal file
43
libstdc++-v3/testsuite/30_threads/this_thread/sleep_until.cc
Normal file
@ -0,0 +1,43 @@
|
||||
// { dg-do run { target c++11 } }
|
||||
// { dg-require-sleep "" }
|
||||
|
||||
// Copyright (C) 2020 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
|
||||
// terms of the GNU General Public License as published by the
|
||||
// Free Software Foundation; either version 3, or (at your option)
|
||||
// any later version.
|
||||
|
||||
// This library is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
|
||||
// You should have received a copy of the GNU General Public License along
|
||||
// with this library; see the file COPYING3. If not see
|
||||
// <http://www.gnu.org/licenses/>.
|
||||
|
||||
#include <chrono>
|
||||
#include <thread>
|
||||
#include <testsuite_hooks.h>
|
||||
|
||||
// This tests this_thread::sleep_until without using -pthread
|
||||
|
||||
namespace chr = std::chrono;
|
||||
|
||||
void
|
||||
test01()
|
||||
{
|
||||
chr::system_clock::time_point begin = chr::system_clock::now();
|
||||
chr::microseconds ms(500);
|
||||
|
||||
std::this_thread::sleep_until(chr::system_clock::now() + ms);
|
||||
|
||||
VERIFY( (chr::system_clock::now() - begin) >= ms );
|
||||
}
|
||||
|
||||
int main()
|
||||
{
|
||||
test01();
|
||||
}
|
@ -1,8 +1,5 @@
|
||||
// { dg-do run }
|
||||
// { dg-options "-pthread" }
|
||||
// { dg-require-effective-target c++11 }
|
||||
// { dg-require-effective-target pthread }
|
||||
// { dg-require-gthreads "" }
|
||||
// { dg-do run { target c++11 } }
|
||||
// { dg-additional-options "-pthread" { target pthread } }
|
||||
|
||||
// Copyright (C) 2008-2020 Free Software Foundation, Inc.
|
||||
//
|
||||
@ -28,7 +25,7 @@
|
||||
|
||||
int main()
|
||||
{
|
||||
try
|
||||
try
|
||||
{
|
||||
std::this_thread::yield();
|
||||
}
|
Loading…
Reference in New Issue
Block a user