aboutsummaryrefslogtreecommitdiff
path: root/promise.hpp
diff options
context:
space:
mode:
Diffstat (limited to 'promise.hpp')
-rw-r--r--promise.hpp107
1 files changed, 59 insertions, 48 deletions
diff --git a/promise.hpp b/promise.hpp
index 0f9198c..25fbd3b 100644
--- a/promise.hpp
+++ b/promise.hpp
@@ -1,16 +1,61 @@
#ifndef _CPPROMISE_HPP
#define _CPPROMISE_HPP
+/**
+ * MIT License
+ * Copyright (c) 2018 Ted Yin <[email protected]>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
#include <vector>
#include <memory>
-#include <any>
#include <functional>
-/** Implement type-safe Promise primitives similar to the ones specified by
- * Javascript A+. */
+#if __has_include("any")
+#include <any>
+#endif
+
+#if !defined(__cpp_lib_any)
+#include <boost/any.hpp>
+#endif
+
+/**
+ * Implement type-safe Promise primitives similar to the ones specified by
+ * Javascript Promise/A+.
+ */
namespace promise {
using std::function;
+
+#if defined(__cpp_lib_any)
using pm_any_t = std::any;
+ template<typename T>
+ constexpr auto any_cast = static_cast<T(*)(const std::any&)>(std::any_cast<T>);
+ using bad_any_cast = std::bad_any_cast;
+#else
+#warning "using any type from boost"
+ using pm_any_t = boost::any;
+ template<typename T>
+ constexpr auto any_cast = static_cast<T(*)(const boost::any&)>(boost::any_cast<T>);
+ using bad_any_cast = boost::bad_any_cast;
+#endif
+
using None = std::nullptr_t;
using values_t = std::vector<pm_any_t>;
const auto none = nullptr;
@@ -82,8 +127,6 @@ namespace promise {
#define PROMISE_ERR_MISMATCH_TYPE do {throw std::runtime_error("mismatching promise value types");} while (0)
class Promise {
- //function<void()> fulfilled_callback;
- //function<void()> rejected_callback;
std::vector<function<void()>> fulfilled_callbacks;
std::vector<function<void()>> rejected_callbacks;
enum class State {
@@ -94,27 +137,6 @@ namespace promise {
pm_any_t result;
pm_any_t reason;
- /* this implementation causes stack overflow because of the nested lambdas */
- /*
- void add_on_fulfilled(function<void()> cb) {
- auto old_cbs = fulfilled_callback;
- fulfilled_callback = function<void()>(
- [cb, old_cbs]() {
- old_cbs();
- cb();
- });
- }
-
- void add_on_rejected(function<void()> cb) {
- auto old_cbs = rejected_callback;
- rejected_callback = function<void()>(
- [cb, old_cbs]() {
- old_cbs();
- cb();
- });
- }
- */
-
void add_on_fulfilled(function<void()> cb) {
fulfilled_callbacks.push_back(cb);
}
@@ -181,18 +203,8 @@ namespace promise {
public:
- Promise():
- /*
- fulfilled_callback(do_nothing),
- rejected_callback(do_nothing),
- */
- state(State::Pending) {
- //printf("%lx constructed\n", (uintptr_t)this);
- }
-
- ~Promise() {
- //printf("%lx freed\n", (uintptr_t)this);
- }
+ Promise(): state(State::Pending) {}
+ ~Promise() {}
template<typename FuncFulfilled, typename FuncRejected>
promise_t then(FuncFulfilled on_fulfilled,
@@ -275,7 +287,6 @@ namespace promise {
case State::Pending:
result = _result;
state = State::Fulfilled;
- //fulfilled_callback();
for (const auto &cb: fulfilled_callbacks) cb();
rejected_callbacks.clear();
break;
@@ -290,7 +301,6 @@ namespace promise {
case State::Pending:
reason = _reason;
state = State::Rejected;
- //rejected_callback();
for (const auto &cb: rejected_callbacks) cb();
rejected_callbacks.clear();
break;
@@ -369,8 +379,8 @@ namespace promise {
return ptr->then(
[on_fulfilled](pm_any_t _result) mutable {
try {
- return ret_type(on_fulfilled(std::any_cast<arg_type>(_result)));
- } catch (std::bad_any_cast e) { PROMISE_ERR_MISMATCH_TYPE; }
+ return ret_type(on_fulfilled(any_cast<arg_type>(_result)));
+ } catch (bad_any_cast e) { PROMISE_ERR_MISMATCH_TYPE; }
});
}
@@ -384,13 +394,13 @@ namespace promise {
return ptr->then(
[on_fulfilled](pm_any_t _result) mutable {
try {
- return fulfill_ret_type(on_fulfilled(std::any_cast<fulfill_arg_type>(_result)));
- } catch (std::bad_any_cast e) { PROMISE_ERR_MISMATCH_TYPE; }
+ return fulfill_ret_type(on_fulfilled(any_cast<fulfill_arg_type>(_result)));
+ } catch (bad_any_cast e) { PROMISE_ERR_MISMATCH_TYPE; }
},
[on_rejected](pm_any_t _reason) mutable {
try {
- return reject_ret_type(on_rejected(std::any_cast<reject_arg_type>(_reason)));
- } catch (std::bad_any_cast e) { PROMISE_ERR_MISMATCH_TYPE; }
+ return reject_ret_type(on_rejected(any_cast<reject_arg_type>(_reason)));
+ } catch (bad_any_cast e) { PROMISE_ERR_MISMATCH_TYPE; }
});
}
@@ -401,9 +411,10 @@ namespace promise {
return ptr->fail(
[on_rejected](pm_any_t _reason) mutable {
try {
- return ret_type(on_rejected(std::any_cast<arg_type>(_reason)));
- } catch (std::bad_any_cast e) { PROMISE_ERR_MISMATCH_TYPE; }
+ return ret_type(on_rejected(any_cast<arg_type>(_reason)));
+ } catch (bad_any_cast e) { PROMISE_ERR_MISMATCH_TYPE; }
});
}
}
+
#endif