1*e4b17023SJohn Marino // mutex -*- C++ -*- 2*e4b17023SJohn Marino 3*e4b17023SJohn Marino // Copyright (C) 2008, 2009, 2010, 2012 Free Software Foundation, Inc. 4*e4b17023SJohn Marino // 5*e4b17023SJohn Marino // This file is part of the GNU ISO C++ Library. This library is free 6*e4b17023SJohn Marino // software; you can redistribute it and/or modify it under the 7*e4b17023SJohn Marino // terms of the GNU General Public License as published by the 8*e4b17023SJohn Marino // Free Software Foundation; either version 3, or (at your option) 9*e4b17023SJohn Marino // any later version. 10*e4b17023SJohn Marino 11*e4b17023SJohn Marino // This library is distributed in the hope that it will be useful, 12*e4b17023SJohn Marino // but WITHOUT ANY WARRANTY; without even the implied warranty of 13*e4b17023SJohn Marino // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14*e4b17023SJohn Marino // GNU General Public License for more details. 15*e4b17023SJohn Marino 16*e4b17023SJohn Marino // Under Section 7 of GPL version 3, you are granted additional 17*e4b17023SJohn Marino // permissions described in the GCC Runtime Library Exception, version 18*e4b17023SJohn Marino // 3.1, as published by the Free Software Foundation. 19*e4b17023SJohn Marino 20*e4b17023SJohn Marino // You should have received a copy of the GNU General Public License and 21*e4b17023SJohn Marino // a copy of the GCC Runtime Library Exception along with this program; 22*e4b17023SJohn Marino // see the files COPYING3 and COPYING.RUNTIME respectively. If not, see 23*e4b17023SJohn Marino // <http://www.gnu.org/licenses/>. 24*e4b17023SJohn Marino 25*e4b17023SJohn Marino #include <mutex> 26*e4b17023SJohn Marino 27*e4b17023SJohn Marino #if defined(_GLIBCXX_HAS_GTHREADS) && defined(_GLIBCXX_USE_C99_STDINT_TR1) 28*e4b17023SJohn Marino #ifndef _GLIBCXX_HAVE_TLS 29*e4b17023SJohn Marino namespace 30*e4b17023SJohn Marino { 31*e4b17023SJohn Marino inline std::unique_lock<std::mutex>*& __get_once_functor_lock_ptr()32*e4b17023SJohn Marino __get_once_functor_lock_ptr() 33*e4b17023SJohn Marino { 34*e4b17023SJohn Marino static std::unique_lock<std::mutex>* __once_functor_lock_ptr = 0; 35*e4b17023SJohn Marino return __once_functor_lock_ptr; 36*e4b17023SJohn Marino } 37*e4b17023SJohn Marino } 38*e4b17023SJohn Marino #endif 39*e4b17023SJohn Marino 40*e4b17023SJohn Marino namespace std _GLIBCXX_VISIBILITY(default) 41*e4b17023SJohn Marino { 42*e4b17023SJohn Marino _GLIBCXX_BEGIN_NAMESPACE_VERSION 43*e4b17023SJohn Marino 44*e4b17023SJohn Marino #ifdef _GLIBCXX_HAVE_TLS 45*e4b17023SJohn Marino __thread void* __once_callable; 46*e4b17023SJohn Marino __thread void (*__once_call)(); 47*e4b17023SJohn Marino #else 48*e4b17023SJohn Marino // Explicit instantiation due to -fno-implicit-instantiation. 49*e4b17023SJohn Marino template class function<void()>; 50*e4b17023SJohn Marino function<void()> __once_functor; 51*e4b17023SJohn Marino 52*e4b17023SJohn Marino mutex& 53*e4b17023SJohn Marino __get_once_mutex() 54*e4b17023SJohn Marino { 55*e4b17023SJohn Marino static mutex once_mutex; 56*e4b17023SJohn Marino return once_mutex; 57*e4b17023SJohn Marino } 58*e4b17023SJohn Marino 59*e4b17023SJohn Marino // code linked against ABI 3.4.12 and later uses this 60*e4b17023SJohn Marino void 61*e4b17023SJohn Marino __set_once_functor_lock_ptr(unique_lock<mutex>* __ptr) 62*e4b17023SJohn Marino { 63*e4b17023SJohn Marino __get_once_functor_lock_ptr() = __ptr; 64*e4b17023SJohn Marino } 65*e4b17023SJohn Marino 66*e4b17023SJohn Marino // unsafe - retained for compatibility with ABI 3.4.11 67*e4b17023SJohn Marino unique_lock<mutex>& 68*e4b17023SJohn Marino __get_once_functor_lock() 69*e4b17023SJohn Marino { 70*e4b17023SJohn Marino static unique_lock<mutex> once_functor_lock(__get_once_mutex(), defer_lock); 71*e4b17023SJohn Marino return once_functor_lock; 72*e4b17023SJohn Marino } 73*e4b17023SJohn Marino #endif 74*e4b17023SJohn Marino 75*e4b17023SJohn Marino extern "C" 76*e4b17023SJohn Marino { __once_proxy()77*e4b17023SJohn Marino void __once_proxy() 78*e4b17023SJohn Marino { 79*e4b17023SJohn Marino #ifndef _GLIBCXX_HAVE_TLS 80*e4b17023SJohn Marino function<void()> __once_call = std::move(__once_functor); 81*e4b17023SJohn Marino if (unique_lock<mutex>* __lock = __get_once_functor_lock_ptr()) 82*e4b17023SJohn Marino { 83*e4b17023SJohn Marino // caller is using new ABI and provided lock ptr 84*e4b17023SJohn Marino __get_once_functor_lock_ptr() = 0; 85*e4b17023SJohn Marino __lock->unlock(); 86*e4b17023SJohn Marino } 87*e4b17023SJohn Marino else 88*e4b17023SJohn Marino __get_once_functor_lock().unlock(); // global lock 89*e4b17023SJohn Marino #endif 90*e4b17023SJohn Marino __once_call(); 91*e4b17023SJohn Marino } 92*e4b17023SJohn Marino } 93*e4b17023SJohn Marino 94*e4b17023SJohn Marino _GLIBCXX_END_NAMESPACE_VERSION 95*e4b17023SJohn Marino } // namespace std 96*e4b17023SJohn Marino 97*e4b17023SJohn Marino #endif // _GLIBCXX_HAS_GTHREADS && _GLIBCXX_USE_C99_STDINT_TR1 98