~ubuntu-branches/ubuntu/vivid/emscripten/vivid

« back to all changes in this revision

Viewing changes to system/lib/libcxx/mutex.cpp

  • Committer: Package Import Robot
  • Author(s): Sylvestre Ledru
  • Date: 2013-05-02 13:11:51 UTC
  • Revision ID: package-import@ubuntu.com-20130502131151-q8dvteqr1ef2x7xz
Tags: upstream-1.4.1~20130504~adb56cb
ImportĀ upstreamĀ versionĀ 1.4.1~20130504~adb56cb

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
//===------------------------- mutex.cpp ----------------------------------===//
 
2
//
 
3
//                     The LLVM Compiler Infrastructure
 
4
//
 
5
// This file is dual licensed under the MIT and the University of Illinois Open
 
6
// Source Licenses. See LICENSE.TXT for details.
 
7
//
 
8
//===----------------------------------------------------------------------===//
 
9
 
 
10
#define _LIBCPP_BUILDING_MUTEX
 
11
#include "mutex"
 
12
#include "limits"
 
13
#include "system_error"
 
14
#include "cassert"
 
15
 
 
16
_LIBCPP_BEGIN_NAMESPACE_STD
 
17
 
 
18
const defer_lock_t  defer_lock = {};
 
19
const try_to_lock_t try_to_lock = {};
 
20
const adopt_lock_t  adopt_lock = {};
 
21
 
 
22
mutex::~mutex()
 
23
{
 
24
    pthread_mutex_destroy(&__m_);
 
25
}
 
26
 
 
27
void
 
28
mutex::lock()
 
29
{
 
30
    int ec = pthread_mutex_lock(&__m_);
 
31
    if (ec)
 
32
        __throw_system_error(ec, "mutex lock failed");
 
33
}
 
34
 
 
35
bool
 
36
mutex::try_lock() _NOEXCEPT
 
37
{
 
38
    return pthread_mutex_trylock(&__m_) == 0;
 
39
}
 
40
 
 
41
void
 
42
mutex::unlock() _NOEXCEPT
 
43
{
 
44
    int ec = pthread_mutex_unlock(&__m_);
 
45
    assert(ec == 0);
 
46
}
 
47
 
 
48
// recursive_mutex
 
49
 
 
50
recursive_mutex::recursive_mutex()
 
51
{
 
52
    pthread_mutexattr_t attr;
 
53
    int ec = pthread_mutexattr_init(&attr);
 
54
    if (ec)
 
55
        goto fail;
 
56
    ec = pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE);
 
57
    if (ec)
 
58
    {
 
59
        pthread_mutexattr_destroy(&attr);
 
60
        goto fail;
 
61
    }
 
62
    ec = pthread_mutex_init(&__m_, &attr);
 
63
    if (ec)
 
64
    {
 
65
        pthread_mutexattr_destroy(&attr);
 
66
        goto fail;
 
67
    }
 
68
    ec = pthread_mutexattr_destroy(&attr);
 
69
    if (ec)
 
70
    {
 
71
        pthread_mutex_destroy(&__m_);
 
72
        goto fail;
 
73
    }
 
74
    return;
 
75
fail:
 
76
    __throw_system_error(ec, "recursive_mutex constructor failed");
 
77
}
 
78
 
 
79
recursive_mutex::~recursive_mutex()
 
80
{
 
81
    int e = pthread_mutex_destroy(&__m_);
 
82
    assert(e == 0);
 
83
}
 
84
 
 
85
void
 
86
recursive_mutex::lock()
 
87
{
 
88
    int ec = pthread_mutex_lock(&__m_);
 
89
    if (ec)
 
90
        __throw_system_error(ec, "recursive_mutex lock failed");
 
91
}
 
92
 
 
93
void
 
94
recursive_mutex::unlock() _NOEXCEPT
 
95
{
 
96
    int e = pthread_mutex_unlock(&__m_);
 
97
    assert(e == 0);
 
98
}
 
99
 
 
100
bool
 
101
recursive_mutex::try_lock() _NOEXCEPT
 
102
{
 
103
    return pthread_mutex_trylock(&__m_) == 0;
 
104
}
 
105
 
 
106
// timed_mutex
 
107
 
 
108
timed_mutex::timed_mutex()
 
109
    : __locked_(false)
 
110
{
 
111
}
 
112
 
 
113
timed_mutex::~timed_mutex()
 
114
{
 
115
    lock_guard<mutex> _(__m_);
 
116
}
 
117
 
 
118
void
 
119
timed_mutex::lock()
 
120
{
 
121
    unique_lock<mutex> lk(__m_);
 
122
    while (__locked_)
 
123
        __cv_.wait(lk);
 
124
    __locked_ = true;
 
125
}
 
126
 
 
127
bool
 
128
timed_mutex::try_lock() _NOEXCEPT
 
129
{
 
130
    unique_lock<mutex> lk(__m_, try_to_lock);
 
131
    if (lk.owns_lock() && !__locked_)
 
132
    {
 
133
        __locked_ = true;
 
134
        return true;
 
135
    }
 
136
    return false;
 
137
}
 
138
 
 
139
void
 
140
timed_mutex::unlock() _NOEXCEPT
 
141
{
 
142
    lock_guard<mutex> _(__m_);
 
143
    __locked_ = false;
 
144
    __cv_.notify_one();
 
145
}
 
146
 
 
147
// recursive_timed_mutex
 
148
 
 
149
recursive_timed_mutex::recursive_timed_mutex()
 
150
    : __count_(0),
 
151
      __id_(0)
 
152
{
 
153
}
 
154
 
 
155
recursive_timed_mutex::~recursive_timed_mutex()
 
156
{
 
157
    lock_guard<mutex> _(__m_);
 
158
}
 
159
 
 
160
void
 
161
recursive_timed_mutex::lock()
 
162
{
 
163
    pthread_t id = pthread_self();
 
164
    unique_lock<mutex> lk(__m_);
 
165
    if (pthread_equal(id, __id_))
 
166
    {
 
167
        if (__count_ == numeric_limits<size_t>::max())
 
168
            __throw_system_error(EAGAIN, "recursive_timed_mutex lock limit reached");
 
169
        ++__count_;
 
170
        return;
 
171
    }
 
172
    while (__count_ != 0)
 
173
        __cv_.wait(lk);
 
174
    __count_ = 1;
 
175
    __id_ = id;
 
176
}
 
177
 
 
178
bool
 
179
recursive_timed_mutex::try_lock() _NOEXCEPT
 
180
{
 
181
    pthread_t id = pthread_self();
 
182
    unique_lock<mutex> lk(__m_, try_to_lock);
 
183
    if (lk.owns_lock() && (__count_ == 0 || pthread_equal(id, __id_)))
 
184
    {
 
185
        if (__count_ == numeric_limits<size_t>::max())
 
186
            return false;
 
187
        ++__count_;
 
188
        __id_ = id;
 
189
        return true;
 
190
    }
 
191
    return false;
 
192
}
 
193
 
 
194
void
 
195
recursive_timed_mutex::unlock() _NOEXCEPT
 
196
{
 
197
    unique_lock<mutex> lk(__m_);
 
198
    if (--__count_ == 0)
 
199
    {
 
200
        __id_ = 0;
 
201
        lk.unlock();
 
202
        __cv_.notify_one();
 
203
    }
 
204
}
 
205
 
 
206
// If dispatch_once_f ever handles C++ exceptions, and if one can get to it
 
207
// without illegal macros (unexpected macros not beginning with _UpperCase or
 
208
// __lowercase), and if it stops spinning waiting threads, then call_once should
 
209
// call into dispatch_once_f instead of here. Relevant radar this code needs to
 
210
// keep in sync with:  7741191.
 
211
 
 
212
static pthread_mutex_t mut = PTHREAD_MUTEX_INITIALIZER;
 
213
static pthread_cond_t  cv  = PTHREAD_COND_INITIALIZER;
 
214
 
 
215
void
 
216
__call_once(volatile unsigned long& flag, void* arg, void(*func)(void*))
 
217
{
 
218
    pthread_mutex_lock(&mut);
 
219
    while (flag == 1)
 
220
        pthread_cond_wait(&cv, &mut);
 
221
    if (flag == 0)
 
222
    {
 
223
#ifndef _LIBCPP_NO_EXCEPTIONS
 
224
        try
 
225
        {
 
226
#endif  // _LIBCPP_NO_EXCEPTIONS
 
227
            flag = 1;
 
228
            pthread_mutex_unlock(&mut);
 
229
            func(arg);
 
230
            pthread_mutex_lock(&mut);
 
231
            flag = ~0ul;
 
232
            pthread_mutex_unlock(&mut);
 
233
            pthread_cond_broadcast(&cv);
 
234
#ifndef _LIBCPP_NO_EXCEPTIONS
 
235
        }
 
236
        catch (...)
 
237
        {
 
238
            pthread_mutex_lock(&mut);
 
239
            flag = 0ul;
 
240
            pthread_mutex_unlock(&mut);
 
241
            pthread_cond_broadcast(&cv);
 
242
            throw;
 
243
        }
 
244
#endif  // _LIBCPP_NO_EXCEPTIONS
 
245
    }
 
246
    else
 
247
        pthread_mutex_unlock(&mut);
 
248
}
 
249
 
 
250
_LIBCPP_END_NAMESPACE_STD