This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Re: [c++0x] std::thread fixes


2009/1/22 Benjamin Kosnik:
>
> This is ok: please check it in.

Done. Here's the second part.

        * include/std/thread: Remove unused headers.
        (__thread_data_base): Remove unused mutex and base.
        (thread::~thread): Only detach if joinable.
        (thread::joinable): Test if thread data ptr is empty.
        (thread::_M_thread_data_mutex): Remove.
        (thread::_M_get_thread_data): Remove.
        (thread::_M_make_thread_data): Remove overload, use make_shared.
        (thread::id::id): Make constructor explicit.
        * src/thread.cc (thread::join,thread::detach): Throw if not joinable.
        (thread::_M_start_thread): Break shared_ptr cycle on error.
        (__thread_proxy): Use shared_ptr swap instead of copy and reset.
        * testsuite/30_threads/thread/member/4.cc: New.
        * testsuite/30_threads/thread/member/5.cc: New.

tested x86_64 linux
Index: include/std/thread
===================================================================
--- include/std/thread	(revision 143577)
+++ include/std/thread	(working copy)
@@ -41,12 +41,10 @@
 #else
 
 #include <chrono>
-#include <exception>
 #include <functional>
 #include <memory>
 #include <mutex>
 #include <condition_variable>
-#include <type_traits>
 #include <cstddef>
 #include <bits/functexcept.h>
 #include <bits/gthr.h>
@@ -59,7 +57,7 @@ namespace std
 
   typedef shared_ptr<__thread_data_base> __thread_data_ptr;
 
-  class __thread_data_base : public enable_shared_from_this<__thread_data_base>
+  class __thread_data_base
   {
   public:
     __thread_data_base() = default;
@@ -69,7 +67,6 @@ namespace std
     
     __gthread_t 	_M_thread_handle;
     __thread_data_ptr 	_M_this_ptr;
-    mutex 		_M_data_mutex;
   };
   
   template<typename _Callable>
@@ -109,7 +106,10 @@ namespace std
       { _M_start_thread(); }
 
     ~thread()
-    { detach(); }
+    {
+      if (joinable())
+        detach();
+    }
 
     thread(const thread&) = delete;
     thread(thread&& __t)
@@ -130,7 +130,8 @@ namespace std
     { std::swap(_M_thread_data, __t._M_thread_data); }
 
     bool 
-    joinable() const;
+    joinable() const
+    { return _M_thread_data; }
 
     void 
     join();
@@ -141,6 +142,8 @@ namespace std
     thread::id
     get_id() const;
 
+    /** @pre thread is joinable
+     */
     native_handle_type 
     native_handle()
     { return _M_thread_data->_M_thread_handle; }
@@ -148,30 +151,18 @@ namespace std
     // static members
     static unsigned hardware_concurrency();
 
-    __thread_data_ptr
-    _M_get_thread_data() const
-    {
-      lock_guard<mutex> __l(_M_thread_data_mutex);
-      return _M_thread_data;
-    }
-
   private:
     template<typename _Callable>
       __thread_data_ptr 
       _M_make_thread_data(_Callable&& __f)
       { 
-	return __thread_data_ptr(
-	  new __thread_data<_Callable>(std::forward<_Callable>(__f)));
+	return make_shared<__thread_data<_Callable>>(
+            std::forward<_Callable>(__f));
       }
     
-    __thread_data_ptr
-    _M_make_thread_data(void(*__f)())
-    { return __thread_data_ptr(new __thread_data<void(*)()>(__f)); }
-    
     void _M_start_thread();
 
     __thread_data_ptr 	_M_thread_data;
-    mutable mutex 	_M_thread_data_mutex;
   };
 
   inline void
@@ -237,8 +228,7 @@ namespace std
 
     friend bool 
     operator==(thread::id __x, thread::id __y)
-    { return static_cast<bool>(__gthread_equal(__x._M_thread_id,
-					       __y._M_thread_id)); }
+    { return __gthread_equal(__x._M_thread_id, __y._M_thread_id); }
 
     friend bool
     operator<(thread::id __x, thread::id __y)
@@ -248,6 +238,7 @@ namespace std
       friend basic_ostream<_CharT, _Traits>&
       operator<<(basic_ostream<_CharT, _Traits>&& __out, thread::id __id); 
 
+    explicit 
     id(__gthread_t __id)
     : _M_thread_id(__id)
     { }
@@ -281,10 +272,6 @@ namespace std
 	return __out << __id._M_thread_id;
     }  
 
-  inline bool
-  thread::joinable() const
-  { return get_id() != thread::id(); }
-
   inline thread::id
   thread::get_id() const
   {
Index: src/thread.cc
===================================================================
--- src/thread.cc	(revision 143577)
+++ src/thread.cc	(working copy)
@@ -28,7 +28,7 @@
 // the GNU General Public License.
 
 #include <thread>
-#include <bits/move.h> // std::move
+#include <cerrno>
 
 #if defined(_GLIBCXX_HAS_GTHREADS) && defined(_GLIBCXX_USE_C99_STDINT_TR1)
 
@@ -41,8 +41,8 @@ namespace std
       void* __thread_proxy(void* __p)
       {
 	__thread_data_base* __t = static_cast<__thread_data_base*>(__p);
-	__thread_data_ptr __local_thread_data = __t->_M_this_ptr;
-	__t->_M_this_ptr.reset();
+	__thread_data_ptr __local_thread_data;
+	__local_thread_data.swap(__t->_M_this_ptr);
 
 	try
 	  {
@@ -61,30 +61,32 @@ namespace std
   void
   thread::join()
   {
-    if(joinable())
-      {
-	void* __r = 0;
-	int __e = __gthread_join(_M_thread_data->_M_thread_handle, &__r);
-	if(__e)
-	  __throw_system_error(__e);
+    int __e = EINVAL;
 
-	lock_guard<mutex> __lock(_M_thread_data_mutex);
-	_M_thread_data.reset();
-      }
+    if (_M_thread_data)
+    {
+      void* __r = 0;
+      __e = __gthread_join(_M_thread_data->_M_thread_handle, &__r);
+    }
+
+    if (__e)
+      __throw_system_error(__e);
+
+    _M_thread_data.reset();
   }
 
   void
   thread::detach()
   {    
-    if(joinable())
-      {
-	int __e = __gthread_detach(_M_thread_data->_M_thread_handle);
-	if(__e)
-	  __throw_system_error(__e);
+    int __e = EINVAL;
 
-	lock_guard<mutex> __lock(_M_thread_data_mutex);
-	_M_thread_data.reset();
-      }
+    if (_M_thread_data)
+      __e = __gthread_detach(_M_thread_data->_M_thread_handle);
+
+    if (__e)
+      __throw_system_error(__e);
+
+    _M_thread_data.reset();
   }
 
   void 
@@ -93,8 +95,11 @@ namespace std
     _M_thread_data->_M_this_ptr = _M_thread_data;
     int __e = __gthread_create(&_M_thread_data->_M_thread_handle, 
 			       &__thread_proxy, _M_thread_data.get());
-    if(__e)
+    if (__e)
+    {
+      _M_thread_data->_M_this_ptr.reset();
       __throw_system_error(__e);
+    }
   }
 }
 
Index: testsuite/30_threads/thread/member/4.cc
===================================================================
--- testsuite/30_threads/thread/member/4.cc	(revision 0)
+++ testsuite/30_threads/thread/member/4.cc	(revision 0)
@@ -0,0 +1,57 @@
+// { dg-do run { target *-*-freebsd* *-*-netbsd* *-*-linux* *-*-solaris* *-*-cygwin *-*-darwin* alpha*-*-osf* mips-sgi-irix6* } }
+// { dg-options " -std=gnu++0x -pthread" { target *-*-freebsd* *-*-netbsd* *-*-linux* alpha*-*-osf* mips-sgi-irix6* } }
+// { dg-options " -std=gnu++0x -pthreads" { target *-*-solaris* } }
+// { dg-options " -std=gnu++0x " { target *-*-cygwin *-*-darwin* } }
+// { dg-require-cstdint "" }
+// { dg-require-gthreads "" }
+
+// Copyright (C) 2009 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 2, 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 COPYING.  If not, write to the Free
+// Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
+// USA.
+
+// As a special exception, you may use this file as part of a free software
+// library without restriction.  Specifically, if other files instantiate
+// templates or use macros or inline functions from this file, or you compile
+// this file and link it with other files to produce an executable, this
+// file does not by itself cause the resulting executable to be covered by
+// the GNU General Public License.  This exception does not however
+// invalidate any other reasons why the executable file might be covered by
+// the GNU General Public License.
+
+#include <thread>
+#include <system_error>
+#include <testsuite_hooks.h>
+
+int main()
+{
+  bool test = false;
+
+  std::thread t;
+
+  try 
+  {
+    t.join();
+  }
+  catch (const std::system_error&)
+  {
+    test = true;
+  }
+
+  VERIFY( test );
+
+  return 0;
+}
Index: testsuite/30_threads/thread/member/5.cc
===================================================================
--- testsuite/30_threads/thread/member/5.cc	(revision 0)
+++ testsuite/30_threads/thread/member/5.cc	(revision 0)
@@ -0,0 +1,57 @@
+// { dg-do run { target *-*-freebsd* *-*-netbsd* *-*-linux* *-*-solaris* *-*-cygwin *-*-darwin* alpha*-*-osf* mips-sgi-irix6* } }
+// { dg-options " -std=gnu++0x -pthread" { target *-*-freebsd* *-*-netbsd* *-*-linux* alpha*-*-osf* mips-sgi-irix6* } }
+// { dg-options " -std=gnu++0x -pthreads" { target *-*-solaris* } }
+// { dg-options " -std=gnu++0x " { target *-*-cygwin *-*-darwin* } }
+// { dg-require-cstdint "" }
+// { dg-require-gthreads "" }
+
+// Copyright (C) 2009 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 2, 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 COPYING.  If not, write to the Free
+// Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
+// USA.
+
+// As a special exception, you may use this file as part of a free software
+// library without restriction.  Specifically, if other files instantiate
+// templates or use macros or inline functions from this file, or you compile
+// this file and link it with other files to produce an executable, this
+// file does not by itself cause the resulting executable to be covered by
+// the GNU General Public License.  This exception does not however
+// invalidate any other reasons why the executable file might be covered by
+// the GNU General Public License.
+
+#include <thread>
+#include <system_error>
+#include <testsuite_hooks.h>
+
+int main()
+{
+  bool test = false;
+
+  std::thread t;
+
+  try 
+  {
+    t.detach();
+  }
+  catch (const std::system_error&)
+  {
+    test = true;
+  }
+
+  VERIFY( test );
+
+  return 0;
+}

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]