1bc8d3f97eb5c958007f2713238472e0c1c8fe02Howard Hinnant//===------------------------- mutex.cpp ----------------------------------===//
2bc8d3f97eb5c958007f2713238472e0c1c8fe02Howard Hinnant//
3f5256e16dfc425c1d466f6308d4026d529ce9e0bHoward Hinnant//                     The LLVM Compiler Infrastructure
4bc8d3f97eb5c958007f2713238472e0c1c8fe02Howard Hinnant//
5b64f8b07c104c6cc986570ac8ee0ed16a9f23976Howard Hinnant// This file is dual licensed under the MIT and the University of Illinois Open
6b64f8b07c104c6cc986570ac8ee0ed16a9f23976Howard Hinnant// Source Licenses. See LICENSE.TXT for details.
7bc8d3f97eb5c958007f2713238472e0c1c8fe02Howard Hinnant//
8bc8d3f97eb5c958007f2713238472e0c1c8fe02Howard Hinnant//===----------------------------------------------------------------------===//
9bc8d3f97eb5c958007f2713238472e0c1c8fe02Howard Hinnant
10499c61f999dd032510ecd4a70c90bf4410c9762bHoward Hinnant#define _LIBCPP_BUILDING_MUTEX
11bc8d3f97eb5c958007f2713238472e0c1c8fe02Howard Hinnant#include "mutex"
12bc8d3f97eb5c958007f2713238472e0c1c8fe02Howard Hinnant#include "limits"
13bc8d3f97eb5c958007f2713238472e0c1c8fe02Howard Hinnant#include "system_error"
14bc8d3f97eb5c958007f2713238472e0c1c8fe02Howard Hinnant#include "cassert"
15bc8d3f97eb5c958007f2713238472e0c1c8fe02Howard Hinnant
16bc8d3f97eb5c958007f2713238472e0c1c8fe02Howard Hinnant_LIBCPP_BEGIN_NAMESPACE_STD
177112dae6acac544a0271a85d95342c583441e2d1Dan Albert#ifndef _LIBCPP_HAS_NO_THREADS
18bc8d3f97eb5c958007f2713238472e0c1c8fe02Howard Hinnant
19bc8d3f97eb5c958007f2713238472e0c1c8fe02Howard Hinnantconst defer_lock_t  defer_lock = {};
20bc8d3f97eb5c958007f2713238472e0c1c8fe02Howard Hinnantconst try_to_lock_t try_to_lock = {};
21bc8d3f97eb5c958007f2713238472e0c1c8fe02Howard Hinnantconst adopt_lock_t  adopt_lock = {};
22bc8d3f97eb5c958007f2713238472e0c1c8fe02Howard Hinnant
23bc8d3f97eb5c958007f2713238472e0c1c8fe02Howard Hinnantmutex::~mutex()
24bc8d3f97eb5c958007f2713238472e0c1c8fe02Howard Hinnant{
25ec3773c2dadbeadfc5def927116c2ee9d9c53066Howard Hinnant    pthread_mutex_destroy(&__m_);
26bc8d3f97eb5c958007f2713238472e0c1c8fe02Howard Hinnant}
27bc8d3f97eb5c958007f2713238472e0c1c8fe02Howard Hinnant
28bc8d3f97eb5c958007f2713238472e0c1c8fe02Howard Hinnantvoid
29bc8d3f97eb5c958007f2713238472e0c1c8fe02Howard Hinnantmutex::lock()
30bc8d3f97eb5c958007f2713238472e0c1c8fe02Howard Hinnant{
31bc8d3f97eb5c958007f2713238472e0c1c8fe02Howard Hinnant    int ec = pthread_mutex_lock(&__m_);
32bc8d3f97eb5c958007f2713238472e0c1c8fe02Howard Hinnant    if (ec)
33bc8d3f97eb5c958007f2713238472e0c1c8fe02Howard Hinnant        __throw_system_error(ec, "mutex lock failed");
34bc8d3f97eb5c958007f2713238472e0c1c8fe02Howard Hinnant}
35bc8d3f97eb5c958007f2713238472e0c1c8fe02Howard Hinnant
36bc8d3f97eb5c958007f2713238472e0c1c8fe02Howard Hinnantbool
37499c61f999dd032510ecd4a70c90bf4410c9762bHoward Hinnantmutex::try_lock() _NOEXCEPT
38bc8d3f97eb5c958007f2713238472e0c1c8fe02Howard Hinnant{
39bc8d3f97eb5c958007f2713238472e0c1c8fe02Howard Hinnant    return pthread_mutex_trylock(&__m_) == 0;
40bc8d3f97eb5c958007f2713238472e0c1c8fe02Howard Hinnant}
41bc8d3f97eb5c958007f2713238472e0c1c8fe02Howard Hinnant
42bc8d3f97eb5c958007f2713238472e0c1c8fe02Howard Hinnantvoid
43499c61f999dd032510ecd4a70c90bf4410c9762bHoward Hinnantmutex::unlock() _NOEXCEPT
44bc8d3f97eb5c958007f2713238472e0c1c8fe02Howard Hinnant{
45bc8d3f97eb5c958007f2713238472e0c1c8fe02Howard Hinnant    int ec = pthread_mutex_unlock(&__m_);
46fc910cb9a0b5a1ecd8b1f4c1c10ca54e2e433aa7Howard Hinnant    (void)ec;
47bc8d3f97eb5c958007f2713238472e0c1c8fe02Howard Hinnant    assert(ec == 0);
48bc8d3f97eb5c958007f2713238472e0c1c8fe02Howard Hinnant}
49bc8d3f97eb5c958007f2713238472e0c1c8fe02Howard Hinnant
50bc8d3f97eb5c958007f2713238472e0c1c8fe02Howard Hinnant// recursive_mutex
51bc8d3f97eb5c958007f2713238472e0c1c8fe02Howard Hinnant
52bc8d3f97eb5c958007f2713238472e0c1c8fe02Howard Hinnantrecursive_mutex::recursive_mutex()
53bc8d3f97eb5c958007f2713238472e0c1c8fe02Howard Hinnant{
54bc8d3f97eb5c958007f2713238472e0c1c8fe02Howard Hinnant    pthread_mutexattr_t attr;
55bc8d3f97eb5c958007f2713238472e0c1c8fe02Howard Hinnant    int ec = pthread_mutexattr_init(&attr);
56bc8d3f97eb5c958007f2713238472e0c1c8fe02Howard Hinnant    if (ec)
57bc8d3f97eb5c958007f2713238472e0c1c8fe02Howard Hinnant        goto fail;
58bc8d3f97eb5c958007f2713238472e0c1c8fe02Howard Hinnant    ec = pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE);
59bc8d3f97eb5c958007f2713238472e0c1c8fe02Howard Hinnant    if (ec)
60bc8d3f97eb5c958007f2713238472e0c1c8fe02Howard Hinnant    {
61bc8d3f97eb5c958007f2713238472e0c1c8fe02Howard Hinnant        pthread_mutexattr_destroy(&attr);
62bc8d3f97eb5c958007f2713238472e0c1c8fe02Howard Hinnant        goto fail;
63bc8d3f97eb5c958007f2713238472e0c1c8fe02Howard Hinnant    }
64bc8d3f97eb5c958007f2713238472e0c1c8fe02Howard Hinnant    ec = pthread_mutex_init(&__m_, &attr);
65bc8d3f97eb5c958007f2713238472e0c1c8fe02Howard Hinnant    if (ec)
66bc8d3f97eb5c958007f2713238472e0c1c8fe02Howard Hinnant    {
67bc8d3f97eb5c958007f2713238472e0c1c8fe02Howard Hinnant        pthread_mutexattr_destroy(&attr);
68bc8d3f97eb5c958007f2713238472e0c1c8fe02Howard Hinnant        goto fail;
69bc8d3f97eb5c958007f2713238472e0c1c8fe02Howard Hinnant    }
70bc8d3f97eb5c958007f2713238472e0c1c8fe02Howard Hinnant    ec = pthread_mutexattr_destroy(&attr);
71bc8d3f97eb5c958007f2713238472e0c1c8fe02Howard Hinnant    if (ec)
72bc8d3f97eb5c958007f2713238472e0c1c8fe02Howard Hinnant    {
73bc8d3f97eb5c958007f2713238472e0c1c8fe02Howard Hinnant        pthread_mutex_destroy(&__m_);
74bc8d3f97eb5c958007f2713238472e0c1c8fe02Howard Hinnant        goto fail;
75bc8d3f97eb5c958007f2713238472e0c1c8fe02Howard Hinnant    }
76bc8d3f97eb5c958007f2713238472e0c1c8fe02Howard Hinnant    return;
77bc8d3f97eb5c958007f2713238472e0c1c8fe02Howard Hinnantfail:
78bc8d3f97eb5c958007f2713238472e0c1c8fe02Howard Hinnant    __throw_system_error(ec, "recursive_mutex constructor failed");
79bc8d3f97eb5c958007f2713238472e0c1c8fe02Howard Hinnant}
80bc8d3f97eb5c958007f2713238472e0c1c8fe02Howard Hinnant
81bc8d3f97eb5c958007f2713238472e0c1c8fe02Howard Hinnantrecursive_mutex::~recursive_mutex()
82bc8d3f97eb5c958007f2713238472e0c1c8fe02Howard Hinnant{
83bc8d3f97eb5c958007f2713238472e0c1c8fe02Howard Hinnant    int e = pthread_mutex_destroy(&__m_);
84fc910cb9a0b5a1ecd8b1f4c1c10ca54e2e433aa7Howard Hinnant    (void)e;
85bc8d3f97eb5c958007f2713238472e0c1c8fe02Howard Hinnant    assert(e == 0);
86bc8d3f97eb5c958007f2713238472e0c1c8fe02Howard Hinnant}
87bc8d3f97eb5c958007f2713238472e0c1c8fe02Howard Hinnant
88bc8d3f97eb5c958007f2713238472e0c1c8fe02Howard Hinnantvoid
89bc8d3f97eb5c958007f2713238472e0c1c8fe02Howard Hinnantrecursive_mutex::lock()
90bc8d3f97eb5c958007f2713238472e0c1c8fe02Howard Hinnant{
91bc8d3f97eb5c958007f2713238472e0c1c8fe02Howard Hinnant    int ec = pthread_mutex_lock(&__m_);
92bc8d3f97eb5c958007f2713238472e0c1c8fe02Howard Hinnant    if (ec)
93bc8d3f97eb5c958007f2713238472e0c1c8fe02Howard Hinnant        __throw_system_error(ec, "recursive_mutex lock failed");
94bc8d3f97eb5c958007f2713238472e0c1c8fe02Howard Hinnant}
95bc8d3f97eb5c958007f2713238472e0c1c8fe02Howard Hinnant
96bc8d3f97eb5c958007f2713238472e0c1c8fe02Howard Hinnantvoid
97499c61f999dd032510ecd4a70c90bf4410c9762bHoward Hinnantrecursive_mutex::unlock() _NOEXCEPT
98bc8d3f97eb5c958007f2713238472e0c1c8fe02Howard Hinnant{
99bc8d3f97eb5c958007f2713238472e0c1c8fe02Howard Hinnant    int e = pthread_mutex_unlock(&__m_);
100fc910cb9a0b5a1ecd8b1f4c1c10ca54e2e433aa7Howard Hinnant    (void)e;
101bc8d3f97eb5c958007f2713238472e0c1c8fe02Howard Hinnant    assert(e == 0);
102bc8d3f97eb5c958007f2713238472e0c1c8fe02Howard Hinnant}
103bc8d3f97eb5c958007f2713238472e0c1c8fe02Howard Hinnant
104bc8d3f97eb5c958007f2713238472e0c1c8fe02Howard Hinnantbool
105499c61f999dd032510ecd4a70c90bf4410c9762bHoward Hinnantrecursive_mutex::try_lock() _NOEXCEPT
106bc8d3f97eb5c958007f2713238472e0c1c8fe02Howard Hinnant{
107bc8d3f97eb5c958007f2713238472e0c1c8fe02Howard Hinnant    return pthread_mutex_trylock(&__m_) == 0;
108bc8d3f97eb5c958007f2713238472e0c1c8fe02Howard Hinnant}
109bc8d3f97eb5c958007f2713238472e0c1c8fe02Howard Hinnant
110bc8d3f97eb5c958007f2713238472e0c1c8fe02Howard Hinnant// timed_mutex
111bc8d3f97eb5c958007f2713238472e0c1c8fe02Howard Hinnant
112bc8d3f97eb5c958007f2713238472e0c1c8fe02Howard Hinnanttimed_mutex::timed_mutex()
113bc8d3f97eb5c958007f2713238472e0c1c8fe02Howard Hinnant    : __locked_(false)
114bc8d3f97eb5c958007f2713238472e0c1c8fe02Howard Hinnant{
115bc8d3f97eb5c958007f2713238472e0c1c8fe02Howard Hinnant}
116bc8d3f97eb5c958007f2713238472e0c1c8fe02Howard Hinnant
117bc8d3f97eb5c958007f2713238472e0c1c8fe02Howard Hinnanttimed_mutex::~timed_mutex()
118bc8d3f97eb5c958007f2713238472e0c1c8fe02Howard Hinnant{
119bc8d3f97eb5c958007f2713238472e0c1c8fe02Howard Hinnant    lock_guard<mutex> _(__m_);
120bc8d3f97eb5c958007f2713238472e0c1c8fe02Howard Hinnant}
121bc8d3f97eb5c958007f2713238472e0c1c8fe02Howard Hinnant
122bc8d3f97eb5c958007f2713238472e0c1c8fe02Howard Hinnantvoid
123bc8d3f97eb5c958007f2713238472e0c1c8fe02Howard Hinnanttimed_mutex::lock()
124bc8d3f97eb5c958007f2713238472e0c1c8fe02Howard Hinnant{
125bc8d3f97eb5c958007f2713238472e0c1c8fe02Howard Hinnant    unique_lock<mutex> lk(__m_);
126bc8d3f97eb5c958007f2713238472e0c1c8fe02Howard Hinnant    while (__locked_)
127bc8d3f97eb5c958007f2713238472e0c1c8fe02Howard Hinnant        __cv_.wait(lk);
128bc8d3f97eb5c958007f2713238472e0c1c8fe02Howard Hinnant    __locked_ = true;
129bc8d3f97eb5c958007f2713238472e0c1c8fe02Howard Hinnant}
130bc8d3f97eb5c958007f2713238472e0c1c8fe02Howard Hinnant
131bc8d3f97eb5c958007f2713238472e0c1c8fe02Howard Hinnantbool
132499c61f999dd032510ecd4a70c90bf4410c9762bHoward Hinnanttimed_mutex::try_lock() _NOEXCEPT
133bc8d3f97eb5c958007f2713238472e0c1c8fe02Howard Hinnant{
134bc8d3f97eb5c958007f2713238472e0c1c8fe02Howard Hinnant    unique_lock<mutex> lk(__m_, try_to_lock);
135bc8d3f97eb5c958007f2713238472e0c1c8fe02Howard Hinnant    if (lk.owns_lock() && !__locked_)
136bc8d3f97eb5c958007f2713238472e0c1c8fe02Howard Hinnant    {
137bc8d3f97eb5c958007f2713238472e0c1c8fe02Howard Hinnant        __locked_ = true;
138bc8d3f97eb5c958007f2713238472e0c1c8fe02Howard Hinnant        return true;
139bc8d3f97eb5c958007f2713238472e0c1c8fe02Howard Hinnant    }
140bc8d3f97eb5c958007f2713238472e0c1c8fe02Howard Hinnant    return false;
141bc8d3f97eb5c958007f2713238472e0c1c8fe02Howard Hinnant}
142bc8d3f97eb5c958007f2713238472e0c1c8fe02Howard Hinnant
143bc8d3f97eb5c958007f2713238472e0c1c8fe02Howard Hinnantvoid
144499c61f999dd032510ecd4a70c90bf4410c9762bHoward Hinnanttimed_mutex::unlock() _NOEXCEPT
145bc8d3f97eb5c958007f2713238472e0c1c8fe02Howard Hinnant{
146bc8d3f97eb5c958007f2713238472e0c1c8fe02Howard Hinnant    lock_guard<mutex> _(__m_);
147bc8d3f97eb5c958007f2713238472e0c1c8fe02Howard Hinnant    __locked_ = false;
148bc8d3f97eb5c958007f2713238472e0c1c8fe02Howard Hinnant    __cv_.notify_one();
149bc8d3f97eb5c958007f2713238472e0c1c8fe02Howard Hinnant}
150bc8d3f97eb5c958007f2713238472e0c1c8fe02Howard Hinnant
151bc8d3f97eb5c958007f2713238472e0c1c8fe02Howard Hinnant// recursive_timed_mutex
152bc8d3f97eb5c958007f2713238472e0c1c8fe02Howard Hinnant
153bc8d3f97eb5c958007f2713238472e0c1c8fe02Howard Hinnantrecursive_timed_mutex::recursive_timed_mutex()
154bc8d3f97eb5c958007f2713238472e0c1c8fe02Howard Hinnant    : __count_(0),
155adff4895b2746f30b271bc219713e7ded5ae9677Howard Hinnant      __id_(0)
156bc8d3f97eb5c958007f2713238472e0c1c8fe02Howard Hinnant{
157bc8d3f97eb5c958007f2713238472e0c1c8fe02Howard Hinnant}
158bc8d3f97eb5c958007f2713238472e0c1c8fe02Howard Hinnant
159bc8d3f97eb5c958007f2713238472e0c1c8fe02Howard Hinnantrecursive_timed_mutex::~recursive_timed_mutex()
160bc8d3f97eb5c958007f2713238472e0c1c8fe02Howard Hinnant{
161bc8d3f97eb5c958007f2713238472e0c1c8fe02Howard Hinnant    lock_guard<mutex> _(__m_);
162bc8d3f97eb5c958007f2713238472e0c1c8fe02Howard Hinnant}
163bc8d3f97eb5c958007f2713238472e0c1c8fe02Howard Hinnant
164bc8d3f97eb5c958007f2713238472e0c1c8fe02Howard Hinnantvoid
165bc8d3f97eb5c958007f2713238472e0c1c8fe02Howard Hinnantrecursive_timed_mutex::lock()
166bc8d3f97eb5c958007f2713238472e0c1c8fe02Howard Hinnant{
167bc8d3f97eb5c958007f2713238472e0c1c8fe02Howard Hinnant    pthread_t id = pthread_self();
168bc8d3f97eb5c958007f2713238472e0c1c8fe02Howard Hinnant    unique_lock<mutex> lk(__m_);
169bc8d3f97eb5c958007f2713238472e0c1c8fe02Howard Hinnant    if (pthread_equal(id, __id_))
170bc8d3f97eb5c958007f2713238472e0c1c8fe02Howard Hinnant    {
171bc8d3f97eb5c958007f2713238472e0c1c8fe02Howard Hinnant        if (__count_ == numeric_limits<size_t>::max())
172bc8d3f97eb5c958007f2713238472e0c1c8fe02Howard Hinnant            __throw_system_error(EAGAIN, "recursive_timed_mutex lock limit reached");
173bc8d3f97eb5c958007f2713238472e0c1c8fe02Howard Hinnant        ++__count_;
174bc8d3f97eb5c958007f2713238472e0c1c8fe02Howard Hinnant        return;
175bc8d3f97eb5c958007f2713238472e0c1c8fe02Howard Hinnant    }
176bc8d3f97eb5c958007f2713238472e0c1c8fe02Howard Hinnant    while (__count_ != 0)
177bc8d3f97eb5c958007f2713238472e0c1c8fe02Howard Hinnant        __cv_.wait(lk);
178bc8d3f97eb5c958007f2713238472e0c1c8fe02Howard Hinnant    __count_ = 1;
179bc8d3f97eb5c958007f2713238472e0c1c8fe02Howard Hinnant    __id_ = id;
180bc8d3f97eb5c958007f2713238472e0c1c8fe02Howard Hinnant}
181bc8d3f97eb5c958007f2713238472e0c1c8fe02Howard Hinnant
182bc8d3f97eb5c958007f2713238472e0c1c8fe02Howard Hinnantbool
183499c61f999dd032510ecd4a70c90bf4410c9762bHoward Hinnantrecursive_timed_mutex::try_lock() _NOEXCEPT
184bc8d3f97eb5c958007f2713238472e0c1c8fe02Howard Hinnant{
185bc8d3f97eb5c958007f2713238472e0c1c8fe02Howard Hinnant    pthread_t id = pthread_self();
186bc8d3f97eb5c958007f2713238472e0c1c8fe02Howard Hinnant    unique_lock<mutex> lk(__m_, try_to_lock);
187bc8d3f97eb5c958007f2713238472e0c1c8fe02Howard Hinnant    if (lk.owns_lock() && (__count_ == 0 || pthread_equal(id, __id_)))
188bc8d3f97eb5c958007f2713238472e0c1c8fe02Howard Hinnant    {
189bc8d3f97eb5c958007f2713238472e0c1c8fe02Howard Hinnant        if (__count_ == numeric_limits<size_t>::max())
190bc8d3f97eb5c958007f2713238472e0c1c8fe02Howard Hinnant            return false;
191bc8d3f97eb5c958007f2713238472e0c1c8fe02Howard Hinnant        ++__count_;
192bc8d3f97eb5c958007f2713238472e0c1c8fe02Howard Hinnant        __id_ = id;
193bc8d3f97eb5c958007f2713238472e0c1c8fe02Howard Hinnant        return true;
194bc8d3f97eb5c958007f2713238472e0c1c8fe02Howard Hinnant    }
195bc8d3f97eb5c958007f2713238472e0c1c8fe02Howard Hinnant    return false;
196bc8d3f97eb5c958007f2713238472e0c1c8fe02Howard Hinnant}
197bc8d3f97eb5c958007f2713238472e0c1c8fe02Howard Hinnant
198bc8d3f97eb5c958007f2713238472e0c1c8fe02Howard Hinnantvoid
199499c61f999dd032510ecd4a70c90bf4410c9762bHoward Hinnantrecursive_timed_mutex::unlock() _NOEXCEPT
200bc8d3f97eb5c958007f2713238472e0c1c8fe02Howard Hinnant{
201bc8d3f97eb5c958007f2713238472e0c1c8fe02Howard Hinnant    unique_lock<mutex> lk(__m_);
202bc8d3f97eb5c958007f2713238472e0c1c8fe02Howard Hinnant    if (--__count_ == 0)
203bc8d3f97eb5c958007f2713238472e0c1c8fe02Howard Hinnant    {
204adff4895b2746f30b271bc219713e7ded5ae9677Howard Hinnant        __id_ = 0;
205bc8d3f97eb5c958007f2713238472e0c1c8fe02Howard Hinnant        lk.unlock();
206bc8d3f97eb5c958007f2713238472e0c1c8fe02Howard Hinnant        __cv_.notify_one();
207bc8d3f97eb5c958007f2713238472e0c1c8fe02Howard Hinnant    }
208bc8d3f97eb5c958007f2713238472e0c1c8fe02Howard Hinnant}
209bc8d3f97eb5c958007f2713238472e0c1c8fe02Howard Hinnant
2107112dae6acac544a0271a85d95342c583441e2d1Dan Albert#endif // !_LIBCPP_HAS_NO_THREADS
2117112dae6acac544a0271a85d95342c583441e2d1Dan Albert
212bc8d3f97eb5c958007f2713238472e0c1c8fe02Howard Hinnant// If dispatch_once_f ever handles C++ exceptions, and if one can get to it
213bc8d3f97eb5c958007f2713238472e0c1c8fe02Howard Hinnant// without illegal macros (unexpected macros not beginning with _UpperCase or
214bc8d3f97eb5c958007f2713238472e0c1c8fe02Howard Hinnant// __lowercase), and if it stops spinning waiting threads, then call_once should
215bc8d3f97eb5c958007f2713238472e0c1c8fe02Howard Hinnant// call into dispatch_once_f instead of here. Relevant radar this code needs to
216bc8d3f97eb5c958007f2713238472e0c1c8fe02Howard Hinnant// keep in sync with:  7741191.
217bc8d3f97eb5c958007f2713238472e0c1c8fe02Howard Hinnant
2187112dae6acac544a0271a85d95342c583441e2d1Dan Albert#ifndef _LIBCPP_HAS_NO_THREADS
219bc8d3f97eb5c958007f2713238472e0c1c8fe02Howard Hinnantstatic pthread_mutex_t mut = PTHREAD_MUTEX_INITIALIZER;
220bc8d3f97eb5c958007f2713238472e0c1c8fe02Howard Hinnantstatic pthread_cond_t  cv  = PTHREAD_COND_INITIALIZER;
2217112dae6acac544a0271a85d95342c583441e2d1Dan Albert#endif
222bc8d3f97eb5c958007f2713238472e0c1c8fe02Howard Hinnant
223bc8d3f97eb5c958007f2713238472e0c1c8fe02Howard Hinnantvoid
224bc8d3f97eb5c958007f2713238472e0c1c8fe02Howard Hinnant__call_once(volatile unsigned long& flag, void* arg, void(*func)(void*))
225bc8d3f97eb5c958007f2713238472e0c1c8fe02Howard Hinnant{
2267112dae6acac544a0271a85d95342c583441e2d1Dan Albert#if defined(_LIBCPP_HAS_NO_THREADS)
2277112dae6acac544a0271a85d95342c583441e2d1Dan Albert    if (flag == 0)
2287112dae6acac544a0271a85d95342c583441e2d1Dan Albert    {
2297112dae6acac544a0271a85d95342c583441e2d1Dan Albert#ifndef _LIBCPP_NO_EXCEPTIONS
2307112dae6acac544a0271a85d95342c583441e2d1Dan Albert        try
2317112dae6acac544a0271a85d95342c583441e2d1Dan Albert        {
2327112dae6acac544a0271a85d95342c583441e2d1Dan Albert#endif  // _LIBCPP_NO_EXCEPTIONS
2337112dae6acac544a0271a85d95342c583441e2d1Dan Albert            flag = 1;
2347112dae6acac544a0271a85d95342c583441e2d1Dan Albert            func(arg);
2357112dae6acac544a0271a85d95342c583441e2d1Dan Albert            flag = ~0ul;
2367112dae6acac544a0271a85d95342c583441e2d1Dan Albert#ifndef _LIBCPP_NO_EXCEPTIONS
2377112dae6acac544a0271a85d95342c583441e2d1Dan Albert        }
2387112dae6acac544a0271a85d95342c583441e2d1Dan Albert        catch (...)
2397112dae6acac544a0271a85d95342c583441e2d1Dan Albert        {
2407112dae6acac544a0271a85d95342c583441e2d1Dan Albert            flag = 0ul;
2417112dae6acac544a0271a85d95342c583441e2d1Dan Albert            throw;
2427112dae6acac544a0271a85d95342c583441e2d1Dan Albert        }
2437112dae6acac544a0271a85d95342c583441e2d1Dan Albert#endif  // _LIBCPP_NO_EXCEPTIONS
2447112dae6acac544a0271a85d95342c583441e2d1Dan Albert    }
2457112dae6acac544a0271a85d95342c583441e2d1Dan Albert#else // !_LIBCPP_HAS_NO_THREADS
246bc8d3f97eb5c958007f2713238472e0c1c8fe02Howard Hinnant    pthread_mutex_lock(&mut);
247bc8d3f97eb5c958007f2713238472e0c1c8fe02Howard Hinnant    while (flag == 1)
248bc8d3f97eb5c958007f2713238472e0c1c8fe02Howard Hinnant        pthread_cond_wait(&cv, &mut);
249bc8d3f97eb5c958007f2713238472e0c1c8fe02Howard Hinnant    if (flag == 0)
250bc8d3f97eb5c958007f2713238472e0c1c8fe02Howard Hinnant    {
251d444470d6cd1cad554139c4ba7f3c4f3fe921a5dHoward Hinnant#ifndef _LIBCPP_NO_EXCEPTIONS
252bc8d3f97eb5c958007f2713238472e0c1c8fe02Howard Hinnant        try
253bc8d3f97eb5c958007f2713238472e0c1c8fe02Howard Hinnant        {
25416e6e1d72fd6a10fc165eba4ca4ed2fa7c45df78Howard Hinnant#endif  // _LIBCPP_NO_EXCEPTIONS
255bc8d3f97eb5c958007f2713238472e0c1c8fe02Howard Hinnant            flag = 1;
256bc8d3f97eb5c958007f2713238472e0c1c8fe02Howard Hinnant            pthread_mutex_unlock(&mut);
257bc8d3f97eb5c958007f2713238472e0c1c8fe02Howard Hinnant            func(arg);
258bc8d3f97eb5c958007f2713238472e0c1c8fe02Howard Hinnant            pthread_mutex_lock(&mut);
259bc8d3f97eb5c958007f2713238472e0c1c8fe02Howard Hinnant            flag = ~0ul;
260bc8d3f97eb5c958007f2713238472e0c1c8fe02Howard Hinnant            pthread_mutex_unlock(&mut);
261bc8d3f97eb5c958007f2713238472e0c1c8fe02Howard Hinnant            pthread_cond_broadcast(&cv);
262d444470d6cd1cad554139c4ba7f3c4f3fe921a5dHoward Hinnant#ifndef _LIBCPP_NO_EXCEPTIONS
263bc8d3f97eb5c958007f2713238472e0c1c8fe02Howard Hinnant        }
264bc8d3f97eb5c958007f2713238472e0c1c8fe02Howard Hinnant        catch (...)
265bc8d3f97eb5c958007f2713238472e0c1c8fe02Howard Hinnant        {
266bc8d3f97eb5c958007f2713238472e0c1c8fe02Howard Hinnant            pthread_mutex_lock(&mut);
267bc8d3f97eb5c958007f2713238472e0c1c8fe02Howard Hinnant            flag = 0ul;
268bc8d3f97eb5c958007f2713238472e0c1c8fe02Howard Hinnant            pthread_mutex_unlock(&mut);
26921aefc3a6135c6447b8b43ac3f2349bf568e2900Howard Hinnant            pthread_cond_broadcast(&cv);
270bc8d3f97eb5c958007f2713238472e0c1c8fe02Howard Hinnant            throw;
271bc8d3f97eb5c958007f2713238472e0c1c8fe02Howard Hinnant        }
27216e6e1d72fd6a10fc165eba4ca4ed2fa7c45df78Howard Hinnant#endif  // _LIBCPP_NO_EXCEPTIONS
273bc8d3f97eb5c958007f2713238472e0c1c8fe02Howard Hinnant    }
274bc8d3f97eb5c958007f2713238472e0c1c8fe02Howard Hinnant    else
275bc8d3f97eb5c958007f2713238472e0c1c8fe02Howard Hinnant        pthread_mutex_unlock(&mut);
2767112dae6acac544a0271a85d95342c583441e2d1Dan Albert#endif // !_LIBCPP_HAS_NO_THREADS
2777112dae6acac544a0271a85d95342c583441e2d1Dan Albert
278bc8d3f97eb5c958007f2713238472e0c1c8fe02Howard Hinnant}
279bc8d3f97eb5c958007f2713238472e0c1c8fe02Howard Hinnant
280bc8d3f97eb5c958007f2713238472e0c1c8fe02Howard Hinnant_LIBCPP_END_NAMESPACE_STD
281