OSDN Git Service

2008-09-28 Chris Fairles <cfairles@gcc.gnu.org>
authorcfairles <cfairles@138bc75d-0d04-0410-961f-82ee72b054a4>
Sun, 28 Sep 2008 09:05:07 +0000 (09:05 +0000)
committercfairles <cfairles@138bc75d-0d04-0410-961f-82ee72b054a4>
Sun, 28 Sep 2008 09:05:07 +0000 (09:05 +0000)
        * include/std/mutex (try_lock): Implement generic try_lock.
        * testsuite/30_threads/try_lock/1.cc: New.
        * testsuite/30_threads/try_lock/2.cc: Likewise.
        * testsuite/30_threads/try_lock/3.cc: Likewise.
        * testsuite/30_threads/mutex/cons/assign_neg.cc: Adjust line numbers.
        * testsuite/30_threads/mutex/cons/copy_neg.cc: Likewise.
        * testsuite/30_threads/timed_mutex/cons/assign_neg.cc: Likewise.
        * testsuite/30_threads/timed_mutex/cons/copy_neg.cc: Likewise.
        * testsuite/30_threads/recursive_mutex/cons/assign_neg.cc: Likewise.
        * testsuite/30_threads/recursive_mutex/cons/copy_neg.cc: Likewise.
        * testsuite/30_threads/recursive_timed_mutex/cons/assign_neg.cc:
        Likewise.
        * testsuite/30_threads/recursive_timed_mutex/cons/copy_neg.cc: Likewise.

git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@140729 138bc75d-0d04-0410-961f-82ee72b054a4

13 files changed:
libstdc++-v3/ChangeLog
libstdc++-v3/include/std/mutex
libstdc++-v3/testsuite/30_threads/mutex/cons/assign_neg.cc
libstdc++-v3/testsuite/30_threads/mutex/cons/copy_neg.cc
libstdc++-v3/testsuite/30_threads/recursive_mutex/cons/assign_neg.cc
libstdc++-v3/testsuite/30_threads/recursive_mutex/cons/copy_neg.cc
libstdc++-v3/testsuite/30_threads/recursive_timed_mutex/cons/assign_neg.cc
libstdc++-v3/testsuite/30_threads/recursive_timed_mutex/cons/copy_neg.cc
libstdc++-v3/testsuite/30_threads/timed_mutex/cons/assign_neg.cc
libstdc++-v3/testsuite/30_threads/timed_mutex/cons/copy_neg.cc
libstdc++-v3/testsuite/30_threads/try_lock/1.cc [new file with mode: 0644]
libstdc++-v3/testsuite/30_threads/try_lock/2.cc [new file with mode: 0644]
libstdc++-v3/testsuite/30_threads/try_lock/3.cc [new file with mode: 0644]

index 66bd48a..74ec226 100644 (file)
@@ -1,3 +1,19 @@
+2008-09-28  Chris Fairles <cfairles@gcc.gnu.org>
+
+       * include/std/mutex (try_lock): Implement generic try_lock.
+       * testsuite/30_threads/try_lock/1.cc: New.
+       * testsuite/30_threads/try_lock/2.cc: Likewise.
+       * testsuite/30_threads/try_lock/3.cc: Likewise.
+       * testsuite/30_threads/mutex/cons/assign_neg.cc: Adjust line numbers.
+       * testsuite/30_threads/mutex/cons/copy_neg.cc: Likewise.
+       * testsuite/30_threads/timed_mutex/cons/assign_neg.cc: Likewise.
+       * testsuite/30_threads/timed_mutex/cons/copy_neg.cc: Likewise.
+       * testsuite/30_threads/recursive_mutex/cons/assign_neg.cc: Likewise.
+       * testsuite/30_threads/recursive_mutex/cons/copy_neg.cc: Likewise.
+       * testsuite/30_threads/recursive_timed_mutex/cons/assign_neg.cc:
+       Likewise.
+       * testsuite/30_threads/recursive_timed_mutex/cons/copy_neg.cc: Likewise.
+       
 2008-09-26  Peter O'Gorman  <pogma@thewrittenword.com>
             Steve Ellcey  <sje@cup.hp.com>
 
index e4ceaf2..f3848d0 100644 (file)
@@ -41,6 +41,7 @@
 # include <c++0x_warning.h>
 #else
 
+#include <tuple>
 #include <cstddef>
 #include <chrono>
 #include <exception>
@@ -601,9 +602,81 @@ namespace std
     swap(unique_lock<_Mutex>& __x, unique_lock<_Mutex>&& __y)
     { __x.swap(__y); }
 
-  template<typename _L1, typename _L2, typename ..._L3>
+  template<int _Idx>
+    struct __unlock_impl
+    {
+      template<typename... _Lock>
+        static void
+        __do_unlock(tuple<_Lock&...>& __locks)
+        {
+         std::get<_Idx>(__locks).unlock();
+         __unlock_impl<_Idx - 1>::__do_unlock(__locks);
+       }
+    };
+  
+  template<>
+    struct __unlock_impl<-1>
+    {
+      template<typename... _Lock>
+        static void
+        __do_unlock(tuple<_Lock&...>&)
+        { }
+    };
+
+  template<int _Idx, bool _Continue = true>
+    struct __try_lock_impl
+    {
+      template<typename... _Lock>
+        static int
+        __do_try_lock(tuple<_Lock&...>& __locks)
+        {
+         if(std::get<_Idx>(__locks).try_lock())
+           {
+             return __try_lock_impl<_Idx + 1,
+               _Idx + 2 < sizeof...(_Lock)>::__do_try_lock(__locks);
+           }
+         else
+           {
+             __unlock_impl<_Idx>::__do_unlock(__locks);
+             return _Idx;
+           }
+       }
+    };
+  
+  template<int _Idx>
+    struct __try_lock_impl<_Idx, false>
+    {
+      template<typename... _Lock>
+        static int
+        __do_try_lock(tuple<_Lock&...>& __locks)
+        {
+         if(std::get<_Idx>(__locks).try_lock())
+           return -1;
+         else
+           {
+             __unlock_impl<_Idx>::__do_unlock(__locks);
+             return _Idx;
+           }
+       }
+    };
+  
+  /** @brief Generic try_lock.
+   *  @param __l1 Meets Mutex requirements (try_lock() may throw).
+   *  @param __l2 Meets Mutex requirements (try_lock() may throw).
+   *  @param __l3 Meets Mutex requirements (try_lock() may throw).
+   *  @return Returns -1 if all try_lock() calls return true. Otherwise returns 
+   *          a 0-based index corresponding to the argument that returned false.
+   *  @post Either all arguments are locked, or none will be.
+   *
+   *  Sequentially calls try_lock() on each argument.
+   */
+  template<typename _Lock1, typename _Lock2, typename... _Lock3>
     int
-    try_lock(_L1& __l1, _L2& __l2, _L3&... __l3);
+    try_lock(_Lock1& __l1, _Lock2& __l2, _Lock3&... __l3)
+    {
+      tuple<_Lock1&, _Lock2&, _Lock3&...> __locks(__l1, __l2, __l3...);
+      return __try_lock_impl<0>::__do_try_lock(__locks);
+    }
 
   template<typename _L1, typename _L2, typename ..._L3>
     void
index 388743d..ba7a53f 100644 (file)
@@ -42,4 +42,4 @@ void test01()
 }
 
 // { dg-error "used here" "" { target *-*-* } 41 }
-// { dg-error "deleted function" "" { target *-*-* } 76 }
+// { dg-error "deleted function" "" { target *-*-* } 77 }
index 37daed3..b1c97fe 100644 (file)
@@ -41,4 +41,4 @@ void test01()
 }
 
 // { dg-error "used here" "" { target *-*-* } 40 }
-// { dg-error "deleted function" "" { target *-*-* } 75 }
+// { dg-error "deleted function" "" { target *-*-* } 76 }
index 1ca7f1c..b1b6c15 100644 (file)
@@ -42,4 +42,4 @@ void test01()
 }
 
 // { dg-error "used here" "" { target *-*-* } 41 } 
-// { dg-error "deleted function" "" { target *-*-* } 128 }
+// { dg-error "deleted function" "" { target *-*-* } 129 }
index d732245..2fa153b 100644 (file)
@@ -41,4 +41,4 @@ void test01()
 }
 
 // { dg-error "used here" "" { target *-*-* } 40 } 
-// { dg-error "deleted function" "" { target *-*-* } 127 }
+// { dg-error "deleted function" "" { target *-*-* } 128 }
index 2832093..4d93bee 100644 (file)
@@ -42,4 +42,4 @@ void test01()
 }
 
 // { dg-error "used here" "" { target *-*-* } 41 } 
-// { dg-error "deleted function" "" { target *-*-* } 282 }
+// { dg-error "deleted function" "" { target *-*-* } 283 }
index 95eda1f..e1b63c2 100644 (file)
@@ -41,4 +41,4 @@ void test01()
 }
 
 // { dg-error "used here" "" { target *-*-* } 40 } 
-// { dg-error "deleted function" "" { target *-*-* } 281 }
+// { dg-error "deleted function" "" { target *-*-* } 282 }
index 719ef0c..715a579 100644 (file)
@@ -42,4 +42,4 @@ void test01()
 }
 
 // { dg-error "used here" "" { target *-*-* } 41 } 
-// { dg-error "deleted function" "" { target *-*-* } 179 }
+// { dg-error "deleted function" "" { target *-*-* } 180 }
index 20f309e..3c22c1e 100644 (file)
@@ -41,4 +41,4 @@ void test01()
 }
 
 // { dg-error "used here" "" { target *-*-* } 40 } 
-// { dg-error "deleted function" "" { target *-*-* } 178 }
+// { dg-error "deleted function" "" { target *-*-* } 179 }
diff --git a/libstdc++-v3/testsuite/30_threads/try_lock/1.cc b/libstdc++-v3/testsuite/30_threads/try_lock/1.cc
new file mode 100644 (file)
index 0000000..4f86190
--- /dev/null
@@ -0,0 +1,72 @@
+// { 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) 2008 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 <mutex>
+#include <system_error>
+#include <testsuite_hooks.h>
+
+int main()
+{
+  bool test __attribute__((unused)) = true;
+  typedef std::mutex mutex_type;
+  typedef std::unique_lock<mutex_type> lock_type;
+
+  try
+    {
+      mutex_type m1, m2, m3;
+      lock_type l1(m1, std::defer_lock), 
+       l2(m2, std::defer_lock),
+       l3(m3, std::defer_lock);
+
+      try
+       {
+         int result = std::try_lock(l1, l2, l3);
+         VERIFY( result == -1 );
+       }
+      catch (const std::system_error& e)
+       {
+         VERIFY( false );
+       }
+    }
+  catch (const std::system_error& e)
+    {
+      VERIFY( false );
+    }
+  catch (...)
+    {
+      VERIFY( false );
+    }
+
+  return 0;
+}
diff --git a/libstdc++-v3/testsuite/30_threads/try_lock/2.cc b/libstdc++-v3/testsuite/30_threads/try_lock/2.cc
new file mode 100644 (file)
index 0000000..b2046f0
--- /dev/null
@@ -0,0 +1,117 @@
+// { 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) 2008 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 <mutex>
+#include <system_error>
+#include <testsuite_hooks.h>
+
+void test01()
+{
+  bool test __attribute__((unused)) = true;
+
+  try
+    {
+      std::mutex m1, m2, m3;
+      m1.lock();
+      int result = std::try_lock(m1, m2, m3);
+      VERIFY( result == 0 );
+      m1.lock();
+      m2.lock();
+      m3.lock();
+    }
+  catch (const std::system_error& e)
+    {
+      VERIFY( false );
+    }
+  catch (...)
+    {
+      VERIFY( false );
+    }
+}
+
+void test02()
+{
+  bool test __attribute__((unused)) = true;
+
+  try
+    {
+      std::mutex m1, m2, m3;
+      m2.lock();
+      int result = std::try_lock(m1, m2, m3);
+      VERIFY( result == 1 );
+      m1.lock();
+      m2.lock();
+      m3.lock();
+    }
+  catch (const std::system_error& e)
+    {
+      VERIFY( false );
+    }
+  catch (...)
+    {
+      VERIFY( false );
+    }
+}
+
+void test03()
+{
+  bool test __attribute__((unused)) = true;
+
+  try
+    {
+      std::mutex m1, m2, m3;
+      m3.lock();
+      int result = std::try_lock(m1, m2, m3);
+      VERIFY( result == 2 );
+      m1.lock();
+      m2.lock();
+      m3.lock();
+    }
+  catch (const std::system_error& e)
+    {
+      VERIFY( false );
+    }
+  catch (...)
+    {
+      VERIFY( false );
+    }
+}
+
+int main()
+{
+  test01();
+  test02();
+  test03();
+  return 0;
+}
diff --git a/libstdc++-v3/testsuite/30_threads/try_lock/3.cc b/libstdc++-v3/testsuite/30_threads/try_lock/3.cc
new file mode 100644 (file)
index 0000000..a8bd413
--- /dev/null
@@ -0,0 +1,100 @@
+// { 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) 2008 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 <mutex>
+#include <system_error>
+#include <testsuite_hooks.h>
+
+struct user_lock
+{
+  user_lock() : is_locked(false) { }
+  ~user_lock() = default;
+  user_lock(const user_lock&) = default;
+
+  void lock()
+  {
+    bool test __attribute__((unused)) = true;
+    VERIFY( !is_locked );
+    is_locked = true;
+  }
+
+  bool try_lock() 
+  { return is_locked ? false : (is_locked = true); }
+
+  void unlock()
+  {
+    bool test __attribute__((unused)) = true;
+    VERIFY( is_locked );
+    is_locked = false;
+  }
+
+private:
+  bool is_locked;
+};
+
+int main()
+{
+  bool test __attribute__((unused)) = true;
+
+  try
+    {
+      std::mutex m1;
+      std::recursive_mutex m2;
+      user_lock m3;
+
+      try
+       {
+         //heterogeneous types
+         int result = std::try_lock(m1, m2, m3);
+         VERIFY( result == -1 );
+         m1.unlock();
+         m2.unlock();
+         m3.unlock();
+       }
+      catch (const std::system_error& e)
+       {
+         VERIFY( false );
+       }
+    }
+  catch (const std::system_error& e)
+    {
+      VERIFY( false );
+    }
+  catch (...)
+    {
+      VERIFY( false );
+    }
+
+  return 0;
+}