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