1#pragma once
2
3#if __cplusplus < 201103L
4#error "C++ version lower than C++11"
5#endif
6
7#include <mutex>
8#include <condition_variable>
9#include <memory>
10#include <chrono>
11#include <cassert>
12
13namespace std {
14
15enum class future_status {
16    ready,
17    timeout,
18    deferred
19};
20
21namespace detail {
22
23class shared_state_base {
24protected:
25    typedef void (*deleter_fn)(void *v);
26
27    using scoped_lock = std::lock_guard<std::mutex>;
28    using unique_lock = std::unique_lock<std::mutex>;
29public:
30    explicit shared_state_base(deleter_fn d) : v_(nullptr), d_(d), valid_(true) {}
31
32    ~shared_state_base() { d_(v_); }
33
34    shared_state_base(shared_state_base &&other) = delete;
35
36    shared_state_base(const shared_state_base &other) = delete;
37
38    shared_state_base &operator=(shared_state_base &&other) = delete;
39
40    shared_state_base &operator=(const shared_state_base &other) = delete;
41
42    void wait() {
43        unique_lock lock(m_);
44        c_.wait(lock, [this] { return has_value(); });
45    }
46
47    template <class Rep, class Period>
48    std::future_status
49    wait_for(const std::chrono::duration<Rep, Period> &rel_time) {
50        unique_lock lock(m_);
51        if (c_.wait_for(lock, rel_time, [this] { return has_value(); })) {
52            return std::future_status::ready;
53        }
54        return std::future_status::timeout;
55    }
56
57    template <class Clock, class Duration>
58    std::future_status
59    wait_until(const std::chrono::time_point<Clock, Duration> &abs_time) {
60        unique_lock lock(m_);
61        if (c_.wait_until(lock, abs_time, [this] { return has_value(); })) {
62            return std::future_status::ready;
63        }
64        return std::future_status::timeout;
65    }
66
67protected:
68    bool has_value() { return v_ != nullptr; }
69
70protected:
71    std::mutex m_;
72    std::condition_variable c_;
73    void *v_;
74    deleter_fn d_;
75    bool valid_;
76};
77
78
79template <typename R>
80class shared_state: public shared_state_base {
81public:
82    shared_state() :shared_state_base(default_deleter_) {}
83
84    ~shared_state() {}
85
86    R &get() {
87        wait();
88        scoped_lock lock(m_);
89        assert(valid_);
90        valid_ = false;
91        return *(static_cast<R *>(v_));
92    }
93
94    void set(const R &v) {
95        scoped_lock lock(m_);
96        assert(!has_value());
97        v_ = new R(v);
98        valid_ = true;
99        c_.notify_one();
100    }
101
102    void set(R &&v) {
103        scoped_lock lock(m_);
104        assert(!has_value());
105        v_ = new R(std::move(v));
106        valid_ = true;
107        c_.notify_one();
108    }
109
110    bool valid() {
111        scoped_lock lock(m_);
112        return valid_;
113    }
114
115private:
116    static void default_deleter_(void *v) { delete static_cast<R *>(v); }
117};
118
119} // namespace detail
120
121template <typename R>
122class shared_future {
123};
124
125
126template <typename R>
127class future {
128    using state_type = std::shared_ptr<detail::shared_state<R>>;
129public:
130    future() {}
131
132    explicit future(const state_type &state) : state_(state) {}
133
134    future(future &&other) noexcept: state_(std::move(other.state_)) {
135        other.state_.reset();
136    }
137
138    future(const future &other) = delete;
139
140    ~future() {}
141
142    future &operator=(future &&other) noexcept {
143        if (&other != this) {
144            state_ = std::move(other.state_);
145            other.state_.reset();
146        }
147        return *this;
148    }
149
150    future &operator=(const future &other) = delete;
151
152    void swap(future &other) noexcept {
153        std::swap(state_, other.state_);
154    }
155
156    std::shared_future<R> share() noexcept { return std::shared_future<R>(); }
157
158    R get() { return state_->get(); }
159
160    bool valid() const noexcept { return state_->valid(); }
161
162    void wait() const { state_->wait(); }
163
164    template <class Rep, class Period>
165    std::future_status
166    wait_for(const std::chrono::duration<Rep, Period> &rel_time) const {
167        return state_->wait_for(rel_time);
168    }
169
170    template <class Clock, class Duration>
171    std::future_status
172    wait_until(const std::chrono::time_point<Clock, Duration> &abs_time) const {
173        return state_->wait_until(abs_time);
174    }
175
176private:
177    state_type state_;
178};
179
180
181template <>
182class future<void> {
183    using state_type = std::shared_ptr<detail::shared_state<int>>;
184public:
185    future() {}
186
187    explicit future(const state_type &state) : state_(state) {}
188
189    future(future &&other) noexcept: state_(std::move(other.state_)) {
190        other.state_.reset();
191    }
192
193    future(const future &other) = delete;
194
195    ~future() {}
196
197    future &operator=(future &&other) noexcept {
198        if (&other != this) {
199            state_ = std::move(other.state_);
200            other.state_.reset();
201        }
202        return *this;
203    }
204
205    future &operator=(const future &other) = delete;
206
207    void swap(future &other) noexcept {
208        std::swap(state_, other.state_);
209    }
210
211    std::shared_future<void> share() noexcept { return std::shared_future<void>(); }
212
213    void get() { state_->get(); }
214
215    bool valid() const noexcept { return state_->valid(); }
216
217    void wait() const { state_->wait(); }
218
219    template <class Rep, class Period>
220    std::future_status
221    wait_for(const std::chrono::duration<Rep, Period> &rel_time) const {
222        return state_->wait_for(rel_time);
223    }
224
225    template <class Clock, class Duration>
226    std::future_status
227    wait_until(const std::chrono::time_point<Clock, Duration> &abs_time) const {
228        return state_->wait_until(abs_time);
229    }
230
231private:
232    state_type state_;
233};
234
235
236template <typename R>
237class promise {
238    using state_type = std::shared_ptr<detail::shared_state<R>>;
239public:
240    promise() : state_(new detail::shared_state<R>()) {}
241
242    promise(promise &&other) noexcept: state_(std::move(other.state_)) {
243        other.state_.reset();
244    }
245
246    promise(const promise &other) = delete;
247
248    ~promise() {}
249
250    promise &operator=(promise &&other) noexcept {
251        if (&other != this) {
252            state_ = std::move(other.state_);
253            other.state_.reset();
254        }
255        return *this;
256    }
257
258    promise &operator=(const promise &other) = delete;
259
260    void swap(promise &other) noexcept {
261        std::swap(state_, other.state_);
262    }
263
264    std::future<R> get_future() { return std::future<R>(state_); }
265
266    void set_value(const R &value) { state_->set(value); }
267
268    void set_value(R &&value) { state_->set(std::move(value)); }
269
270    void set_value_at_thread_exit(const R &value);
271
272    void set_value_at_thread_exit(R &&value);
273
274    void set_exception(std::exception_ptr p);
275
276    void set_exception_at_thread_exit(std::exception_ptr p);
277
278private:
279    state_type state_;
280};
281
282
283template <>
284class promise<void> {
285    using state_type = std::shared_ptr<detail::shared_state<int>>;
286public:
287    promise() : state_(new detail::shared_state<int>()) {}
288
289    promise(promise &&other) noexcept: state_(std::move(other.state_)) {
290        other.state_.reset();
291    }
292
293    promise(const promise &other) = delete;
294
295    ~promise() {}
296
297    promise &operator=(promise &&other) noexcept {
298        if (&other != this) {
299            state_ = std::move(other.state_);
300            other.state_.reset();
301        }
302        return *this;
303    }
304
305    promise &operator=(const promise &other) = delete;
306
307    void swap(promise &other) noexcept {
308        std::swap(state_, other.state_);
309    }
310
311    std::future<void> get_future() { return std::future<void>(state_); }
312
313    void set_value() { state_->set(0); }
314
315    void set_value_at_thread_exit();
316
317    void set_exception(std::exception_ptr p);
318
319    void set_exception_at_thread_exit(std::exception_ptr p);
320
321private:
322    state_type state_;
323};
324
325
326template <class R>
327void swap(std::future<R> &lhs, std::future<R> &rhs) noexcept {
328    lhs.swap(rhs);
329}
330
331template <class R>
332void swap(std::promise<R> &lhs, std::promise<R> &rhs) noexcept {
333    lhs.swap(rhs);
334}
335
336} // namespace std
337