libstdc++: Make std::this_thread functions work without gthreads
authorJonathan Wakely <jwakely@redhat.com>
Tue, 11 Aug 2020 15:16:21 +0000 (16:16 +0100)
committerJonathan Wakely <jwakely@redhat.com>
Tue, 11 Aug 2020 15:16:21 +0000 (16:16 +0100)
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::thread::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.

12 files changed:
libstdc++-v3/include/std/thread
libstdc++-v3/src/c++11/thread.cc
libstdc++-v3/testsuite/30_threads/this_thread/2.cc [deleted file]
libstdc++-v3/testsuite/30_threads/this_thread/3.cc [deleted file]
libstdc++-v3/testsuite/30_threads/this_thread/4.cc [deleted file]
libstdc++-v3/testsuite/30_threads/this_thread/58038.cc
libstdc++-v3/testsuite/30_threads/this_thread/60421.cc
libstdc++-v3/testsuite/30_threads/this_thread/sleep_for-mt.cc [new file with mode: 0644]
libstdc++-v3/testsuite/30_threads/this_thread/sleep_for.cc [new file with mode: 0644]
libstdc++-v3/testsuite/30_threads/this_thread/sleep_until-mt.cc [new file with mode: 0644]
libstdc++-v3/testsuite/30_threads/this_thread/sleep_until.cc [new file with mode: 0644]
libstdc++-v3/testsuite/30_threads/this_thread/yield.cc [new file with mode: 0644]

index 0445ab1e319e372cf0711af70816f05fecd3aa5f..30ae93a0d5bf2a3bb4dd8fe9a4536b120f4a08e9 100644 (file)
 # 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
 
 # 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
index 2d8781724f24e9fa8eec42c17d2888a36c76529f..a4c87d816a58819775f83050ff9b37aecd3cd72a 100644 (file)
 #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
diff --git a/libstdc++-v3/testsuite/30_threads/this_thread/2.cc b/libstdc++-v3/testsuite/30_threads/this_thread/2.cc
deleted file mode 100644 (file)
index 00dde14..0000000
+++ /dev/null
@@ -1,45 +0,0 @@
-// { dg-do run }
-// { dg-options "-pthread"  }
-// { dg-require-effective-target c++11 }
-// { dg-require-effective-target pthread }
-// { dg-require-gthreads "" }
-
-// Copyright (C) 2008-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 <thread>
-#include <system_error>
-#include <testsuite_hooks.h>
-
-int main()
-{
-  try 
-    {
-      std::this_thread::yield();
-    }
-  catch (const std::system_error&)
-    {
-      VERIFY( false );
-    }
-  catch (...)
-    {
-      VERIFY( false );
-    }
-
-  return 0;
-}
diff --git a/libstdc++-v3/testsuite/30_threads/this_thread/3.cc b/libstdc++-v3/testsuite/30_threads/this_thread/3.cc
deleted file mode 100644 (file)
index 4599381..0000000
+++ /dev/null
@@ -1,60 +0,0 @@
-// { dg-do run }
-// { dg-options "-pthread"  }
-// { dg-require-effective-target c++11 }
-// { dg-require-effective-target pthread }
-// { dg-require-gthreads "" }
-// { dg-require-sleep "" }
-
-// Copyright (C) 2008-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 <system_error>
-#include <testsuite_hooks.h>
-
-namespace chr = std::chrono;
-
-void foo()
-{
-  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()
-{
-  try 
-    {
-      std::thread t(foo);
-      t.join();
-    }
-  catch (const std::system_error&)
-    {
-      VERIFY( false );
-    }
-  catch (...)
-    {
-      VERIFY( false );
-    }
-
-  return 0;
-}
diff --git a/libstdc++-v3/testsuite/30_threads/this_thread/4.cc b/libstdc++-v3/testsuite/30_threads/this_thread/4.cc
deleted file mode 100644 (file)
index fc8d10d..0000000
+++ /dev/null
@@ -1,60 +0,0 @@
-// { dg-do run }
-// { dg-options "-pthread"  }
-// { dg-require-effective-target c++11 }
-// { dg-require-effective-target pthread }
-// { dg-require-gthreads "" }
-// { dg-require-sleep "" }
-
-// Copyright (C) 2008-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 <system_error>
-#include <testsuite_hooks.h>
-
-namespace chr = std::chrono;
-
-void foo()
-{
-  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()
-{
-  try 
-    {
-      std::thread t(foo);
-      t.join();
-    }
-  catch (const std::system_error&)
-    {
-      VERIFY( false );
-    }
-  catch (...)
-    {
-      VERIFY( false );
-    }
-
-  return 0;
-}
index 54ff0fb53219a0fc9e4b3e620aa758e7d0d34fae..fd007368527a9d4536794139795513d154571994 100644 (file)
@@ -17,6 +17,7 @@
 
 // { dg-do run { target c++11 } }
 // { dg-require-time "" }
+// { dg-require-sleep "" }
 
 #include <thread>
 #include <chrono>
index 531bb366c01f9e95b0e4a12c3635411c687ced25..3f9d8b134d2ea47f5487abbc0ca7a54278d42411 100644 (file)
@@ -22,6 +22,7 @@
 // { dg-require-cstdint "" }
 // { dg-require-gthreads "" }
 // { dg-require-time "" }
+// { dg-require-sleep "" }
 
 #include <thread>
 #include <chrono>
diff --git a/libstdc++-v3/testsuite/30_threads/this_thread/sleep_for-mt.cc b/libstdc++-v3/testsuite/30_threads/this_thread/sleep_for-mt.cc
new file mode 100644 (file)
index 0000000..4599381
--- /dev/null
@@ -0,0 +1,60 @@
+// { dg-do run }
+// { dg-options "-pthread"  }
+// { dg-require-effective-target c++11 }
+// { dg-require-effective-target pthread }
+// { dg-require-gthreads "" }
+// { dg-require-sleep "" }
+
+// Copyright (C) 2008-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 <system_error>
+#include <testsuite_hooks.h>
+
+namespace chr = std::chrono;
+
+void foo()
+{
+  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()
+{
+  try 
+    {
+      std::thread t(foo);
+      t.join();
+    }
+  catch (const std::system_error&)
+    {
+      VERIFY( false );
+    }
+  catch (...)
+    {
+      VERIFY( false );
+    }
+
+  return 0;
+}
diff --git a/libstdc++-v3/testsuite/30_threads/this_thread/sleep_for.cc b/libstdc++-v3/testsuite/30_threads/this_thread/sleep_for.cc
new file mode 100644 (file)
index 0000000..9552a23
--- /dev/null
@@ -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();
+}
diff --git a/libstdc++-v3/testsuite/30_threads/this_thread/sleep_until-mt.cc b/libstdc++-v3/testsuite/30_threads/this_thread/sleep_until-mt.cc
new file mode 100644 (file)
index 0000000..fc8d10d
--- /dev/null
@@ -0,0 +1,60 @@
+// { dg-do run }
+// { dg-options "-pthread"  }
+// { dg-require-effective-target c++11 }
+// { dg-require-effective-target pthread }
+// { dg-require-gthreads "" }
+// { dg-require-sleep "" }
+
+// Copyright (C) 2008-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 <system_error>
+#include <testsuite_hooks.h>
+
+namespace chr = std::chrono;
+
+void foo()
+{
+  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()
+{
+  try 
+    {
+      std::thread t(foo);
+      t.join();
+    }
+  catch (const std::system_error&)
+    {
+      VERIFY( false );
+    }
+  catch (...)
+    {
+      VERIFY( false );
+    }
+
+  return 0;
+}
diff --git a/libstdc++-v3/testsuite/30_threads/this_thread/sleep_until.cc b/libstdc++-v3/testsuite/30_threads/this_thread/sleep_until.cc
new file mode 100644 (file)
index 0000000..6af8759
--- /dev/null
@@ -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();
+}
diff --git a/libstdc++-v3/testsuite/30_threads/this_thread/yield.cc b/libstdc++-v3/testsuite/30_threads/this_thread/yield.cc
new file mode 100644 (file)
index 0000000..08f4efa
--- /dev/null
@@ -0,0 +1,42 @@
+// { dg-do run { target c++11 } }
+// { dg-additional-options "-pthread" { target pthread } }
+
+// Copyright (C) 2008-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 <thread>
+#include <system_error>
+#include <testsuite_hooks.h>
+
+int main()
+{
+  try
+    {
+      std::this_thread::yield();
+    }
+  catch (const std::system_error&)
+    {
+      VERIFY( false );
+    }
+  catch (...)
+    {
+      VERIFY( false );
+    }
+
+  return 0;
+}