diff options
-rw-r--r-- | libstdc++-v3/ChangeLog | 8 | ||||
-rw-r--r-- | libstdc++-v3/config/abi/pre/gnu.ver | 3 | ||||
-rw-r--r-- | libstdc++-v3/include/std/mutex | 14 | ||||
-rw-r--r-- | libstdc++-v3/src/mutex.cc | 24 | ||||
-rw-r--r-- | libstdc++-v3/testsuite/30_threads/call_once/call_once2.cc | 56 |
5 files changed, 78 insertions, 27 deletions
diff --git a/libstdc++-v3/ChangeLog b/libstdc++-v3/ChangeLog index 8841a70..60f7ef2 100644 --- a/libstdc++-v3/ChangeLog +++ b/libstdc++-v3/ChangeLog @@ -1,3 +1,11 @@ +2009-04-25 Jonathan Wakely <jwakely.gcc@gmail.com> + + * include/std/mutex (__get_once_functor_lock, __get_once_mutex): + Replace global lock object with local locks on global mutex. + * src/mutex.cc: Likewise. + * config/abi/pre/gnu.ver: Adjust. + * testsuite/30_threads/call_once/call_once2.cc: New. + 2009-04-25 Paolo Carlini <paolo.carlini@oracle.com> PR libstdc++/39880 diff --git a/libstdc++-v3/config/abi/pre/gnu.ver b/libstdc++-v3/config/abi/pre/gnu.ver index 57183c1..bd2c63e 100644 --- a/libstdc++-v3/config/abi/pre/gnu.ver +++ b/libstdc++-v3/config/abi/pre/gnu.ver @@ -879,7 +879,8 @@ GLIBCXX_3.4.11 { _ZSt11__once_call; _ZSt15__once_callable; _ZSt14__once_functor; - _ZSt23__get_once_functor_lockv; + _ZSt19__once_functor_lock; + _ZSt16__get_once_mutexv; __once_proxy; # condition_variable diff --git a/libstdc++-v3/include/std/mutex b/libstdc++-v3/include/std/mutex index f26acc0..3a22aab 100644 --- a/libstdc++-v3/include/std/mutex +++ b/libstdc++-v3/include/std/mutex @@ -728,9 +728,10 @@ namespace std } #else extern function<void()> __once_functor; + extern unique_lock<mutex>* __once_functor_lock; - extern unique_lock<mutex>& - __get_once_functor_lock(); + extern mutex& + __get_once_mutex(); #endif extern "C" void __once_proxy(); @@ -745,18 +746,13 @@ namespace std __once_callable = &__bound_functor; __once_call = &__once_call_impl<decltype(__bound_functor)>; #else - unique_lock<mutex>& __functor_lock = __get_once_functor_lock(); - __functor_lock.lock(); + unique_lock<mutex> __functor_lock(__get_once_mutex()); __once_functor = bind(__f, __args...); + __once_functor_lock = &__functor_lock; #endif int __e = __gthread_once(&(__once._M_once), &__once_proxy); -#ifndef _GLIBCXX_HAVE_TLS - if (__functor_lock) - __functor_lock.unlock(); -#endif - if (__e) __throw_system_error(__e); } diff --git a/libstdc++-v3/src/mutex.cc b/libstdc++-v3/src/mutex.cc index e0a9489..a9467c2 100644 --- a/libstdc++-v3/src/mutex.cc +++ b/libstdc++-v3/src/mutex.cc @@ -25,18 +25,6 @@ #include <mutex> #if defined(_GLIBCXX_HAS_GTHREADS) && defined(_GLIBCXX_USE_C99_STDINT_TR1) -#ifndef _GLIBCXX_HAVE_TLS -namespace -{ - std::mutex& - get_once_mutex() - { - static std::mutex once_mutex; - return once_mutex; - } -} -#endif - namespace std { const defer_lock_t defer_lock = defer_lock_t(); @@ -55,11 +43,13 @@ namespace std template class function<void()>; function<void()> __once_functor; - unique_lock<mutex>& - __get_once_functor_lock() + unique_lock<mutex>* __once_functor_lock; + + mutex& + __get_once_mutex() { - static unique_lock<mutex> once_functor_lock(get_once_mutex(), defer_lock); - return once_functor_lock; + static mutex once_mutex; + return once_mutex; } #endif @@ -69,7 +59,7 @@ namespace std { #ifndef _GLIBCXX_HAVE_TLS function<void()> __once_call = std::move(__once_functor); - __get_once_functor_lock().unlock(); + __once_functor_lock->unlock(); #endif __once_call(); } diff --git a/libstdc++-v3/testsuite/30_threads/call_once/call_once2.cc b/libstdc++-v3/testsuite/30_threads/call_once/call_once2.cc new file mode 100644 index 0000000..aa12591 --- /dev/null +++ b/libstdc++-v3/testsuite/30_threads/call_once/call_once2.cc @@ -0,0 +1,56 @@ +// { 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 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 <mutex> +#include <thread> +#include <testsuite_hooks.h> + +std::once_flag flag; +int value = 0; + +struct Inc { void operator()() const { ++value; } }; + +struct Func +{ + void operator()() const + { + Inc inc; + for (int i = 0; i < 10000; ++i) + std::call_once(flag, inc); + } +}; + +int main() +{ + Func f; + std::thread t1(f); + std::thread t2(f); + std::thread t3(f); + t1.join(); + t2.join(); + t3.join(); + VERIFY( value == 1 ); + return 0; +} |