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

« back to all changes in this revision

Viewing changes to system/lib/libcxx/future.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
//===------------------------- future.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
#include "future"
 
11
#include "string"
 
12
 
 
13
_LIBCPP_BEGIN_NAMESPACE_STD
 
14
 
 
15
class _LIBCPP_HIDDEN __future_error_category
 
16
    : public __do_message
 
17
{
 
18
public:
 
19
    virtual const char* name() const _NOEXCEPT;
 
20
    virtual string message(int ev) const;
 
21
};
 
22
 
 
23
const char*
 
24
__future_error_category::name() const _NOEXCEPT
 
25
{
 
26
    return "future";
 
27
}
 
28
 
 
29
string
 
30
__future_error_category::message(int ev) const
 
31
{
 
32
    switch (static_cast<future_errc>(ev))
 
33
    {
 
34
    case future_errc::broken_promise:
 
35
        return string("The associated promise has been destructed prior "
 
36
                      "to the associated state becoming ready.");
 
37
    case future_errc::future_already_retrieved:
 
38
        return string("The future has already been retrieved from "
 
39
                      "the promise or packaged_task.");
 
40
    case future_errc::promise_already_satisfied:
 
41
        return string("The state of the promise has already been set.");
 
42
    case future_errc::no_state:
 
43
        return string("Operation not permitted on an object without "
 
44
                      "an associated state.");
 
45
    }
 
46
    return string("unspecified future_errc value\n");
 
47
}
 
48
 
 
49
const error_category&
 
50
future_category() _NOEXCEPT
 
51
{
 
52
    static __future_error_category __f;
 
53
    return __f;
 
54
}
 
55
 
 
56
future_error::future_error(error_code __ec)
 
57
    : logic_error(__ec.message()),
 
58
      __ec_(__ec)
 
59
{
 
60
}
 
61
 
 
62
future_error::~future_error() _NOEXCEPT
 
63
{
 
64
}
 
65
 
 
66
void
 
67
__assoc_sub_state::__on_zero_shared() _NOEXCEPT
 
68
{
 
69
    delete this;
 
70
}
 
71
 
 
72
void
 
73
__assoc_sub_state::set_value()
 
74
{
 
75
    unique_lock<mutex> __lk(__mut_);
 
76
#ifndef _LIBCPP_NO_EXCEPTIONS
 
77
    if (__has_value())
 
78
        throw future_error(make_error_code(future_errc::promise_already_satisfied));
 
79
#endif
 
80
    __state_ |= __constructed | ready;
 
81
    __cv_.notify_all();
 
82
    __lk.unlock();
 
83
}
 
84
 
 
85
void
 
86
__assoc_sub_state::set_value_at_thread_exit()
 
87
{
 
88
    unique_lock<mutex> __lk(__mut_);
 
89
#ifndef _LIBCPP_NO_EXCEPTIONS
 
90
    if (__has_value())
 
91
        throw future_error(make_error_code(future_errc::promise_already_satisfied));
 
92
#endif
 
93
    __state_ |= __constructed;
 
94
    __thread_local_data()->__make_ready_at_thread_exit(this);
 
95
    __lk.unlock();
 
96
}
 
97
 
 
98
void
 
99
__assoc_sub_state::set_exception(exception_ptr __p)
 
100
{
 
101
    unique_lock<mutex> __lk(__mut_);
 
102
#ifndef _LIBCPP_NO_EXCEPTIONS
 
103
    if (__has_value())
 
104
        throw future_error(make_error_code(future_errc::promise_already_satisfied));
 
105
#endif
 
106
    __exception_ = __p;
 
107
    __state_ |= ready;
 
108
    __lk.unlock();
 
109
    __cv_.notify_all();
 
110
}
 
111
 
 
112
void
 
113
__assoc_sub_state::set_exception_at_thread_exit(exception_ptr __p)
 
114
{
 
115
    unique_lock<mutex> __lk(__mut_);
 
116
#ifndef _LIBCPP_NO_EXCEPTIONS
 
117
    if (__has_value())
 
118
        throw future_error(make_error_code(future_errc::promise_already_satisfied));
 
119
#endif
 
120
    __exception_ = __p;
 
121
    __thread_local_data()->__make_ready_at_thread_exit(this);
 
122
    __lk.unlock();
 
123
}
 
124
 
 
125
void
 
126
__assoc_sub_state::__make_ready()
 
127
{
 
128
    unique_lock<mutex> __lk(__mut_);
 
129
    __state_ |= ready;
 
130
    __lk.unlock();
 
131
    __cv_.notify_all();
 
132
}
 
133
 
 
134
void
 
135
__assoc_sub_state::copy()
 
136
{
 
137
    unique_lock<mutex> __lk(__mut_);
 
138
    __sub_wait(__lk);
 
139
    if (__exception_ != nullptr)
 
140
        rethrow_exception(__exception_);
 
141
}
 
142
 
 
143
void
 
144
__assoc_sub_state::wait()
 
145
{
 
146
    unique_lock<mutex> __lk(__mut_);
 
147
    __sub_wait(__lk);
 
148
}
 
149
 
 
150
void
 
151
__assoc_sub_state::__sub_wait(unique_lock<mutex>& __lk)
 
152
{
 
153
    if (!__is_ready())
 
154
    {
 
155
        if (__state_ & static_cast<unsigned>(deferred))
 
156
        {
 
157
            __state_ &= ~static_cast<unsigned>(deferred);
 
158
            __lk.unlock();
 
159
            __execute();
 
160
        }
 
161
        else
 
162
            while (!__is_ready())
 
163
                __cv_.wait(__lk);
 
164
    }
 
165
}
 
166
 
 
167
void
 
168
__assoc_sub_state::__execute()
 
169
{
 
170
#ifndef _LIBCPP_NO_EXCEPTIONS
 
171
    throw future_error(make_error_code(future_errc::no_state));
 
172
#endif
 
173
}
 
174
 
 
175
future<void>::future(__assoc_sub_state* __state)
 
176
    : __state_(__state)
 
177
{
 
178
#ifndef _LIBCPP_NO_EXCEPTIONS
 
179
    if (__state_->__has_future_attached())
 
180
        throw future_error(make_error_code(future_errc::future_already_retrieved));
 
181
#endif
 
182
    __state_->__add_shared();
 
183
    __state_->__set_future_attached();
 
184
}
 
185
 
 
186
future<void>::~future()
 
187
{
 
188
    if (__state_)
 
189
        __state_->__release_shared();
 
190
}
 
191
 
 
192
void
 
193
future<void>::get()
 
194
{
 
195
    unique_ptr<__shared_count, __release_shared_count> __(__state_);
 
196
    __assoc_sub_state* __s = __state_;
 
197
    __state_ = nullptr;
 
198
    __s->copy();
 
199
}
 
200
 
 
201
promise<void>::promise()
 
202
    : __state_(new __assoc_sub_state)
 
203
{
 
204
}
 
205
 
 
206
promise<void>::~promise()
 
207
{
 
208
    if (__state_)
 
209
    {
 
210
        if (!__state_->__has_value() && __state_->use_count() > 1)
 
211
            __state_->set_exception(make_exception_ptr(
 
212
                      future_error(make_error_code(future_errc::broken_promise))
 
213
                                                      ));
 
214
        __state_->__release_shared();
 
215
    }
 
216
}
 
217
 
 
218
future<void>
 
219
promise<void>::get_future()
 
220
{
 
221
#ifndef _LIBCPP_NO_EXCEPTIONS
 
222
    if (__state_ == nullptr)
 
223
        throw future_error(make_error_code(future_errc::no_state));
 
224
#endif
 
225
    return future<void>(__state_);
 
226
}
 
227
 
 
228
void
 
229
promise<void>::set_value()
 
230
{
 
231
#ifndef _LIBCPP_NO_EXCEPTIONS
 
232
    if (__state_ == nullptr)
 
233
        throw future_error(make_error_code(future_errc::no_state));
 
234
#endif
 
235
    __state_->set_value();
 
236
}
 
237
 
 
238
void
 
239
promise<void>::set_exception(exception_ptr __p)
 
240
{
 
241
#ifndef _LIBCPP_NO_EXCEPTIONS
 
242
    if (__state_ == nullptr)
 
243
        throw future_error(make_error_code(future_errc::no_state));
 
244
#endif
 
245
    __state_->set_exception(__p);
 
246
}
 
247
 
 
248
void
 
249
promise<void>::set_value_at_thread_exit()
 
250
{
 
251
#ifndef _LIBCPP_NO_EXCEPTIONS
 
252
    if (__state_ == nullptr)
 
253
        throw future_error(make_error_code(future_errc::no_state));
 
254
#endif
 
255
    __state_->set_value_at_thread_exit();
 
256
}
 
257
 
 
258
void
 
259
promise<void>::set_exception_at_thread_exit(exception_ptr __p)
 
260
{
 
261
#ifndef _LIBCPP_NO_EXCEPTIONS
 
262
    if (__state_ == nullptr)
 
263
        throw future_error(make_error_code(future_errc::no_state));
 
264
#endif
 
265
    __state_->set_exception_at_thread_exit(__p);
 
266
}
 
267
 
 
268
shared_future<void>::~shared_future()
 
269
{
 
270
    if (__state_)
 
271
        __state_->__release_shared();
 
272
}
 
273
 
 
274
shared_future<void>&
 
275
shared_future<void>::operator=(const shared_future& __rhs)
 
276
{
 
277
    if (__rhs.__state_)
 
278
        __rhs.__state_->__add_shared();
 
279
    if (__state_)
 
280
        __state_->__release_shared();
 
281
    __state_ = __rhs.__state_;
 
282
    return *this;
 
283
}
 
284
 
 
285
_LIBCPP_END_NAMESPACE_STD