aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDeterminant <ted.sybil@gmail.com>2018-02-01 20:21:53 -0500
committerDeterminant <ted.sybil@gmail.com>2018-02-01 20:21:53 -0500
commit25c438b9056e2dee99fcc8680a6c295df9aa939e (patch)
treef1d70b2354f63c76d2ed13c29f61fdc128b8adff
parente609deb93ca365b253efa2173ce83046835a8d84 (diff)
...
-rw-r--r--Makefile8
-rw-r--r--promise.hpp107
-rw-r--r--test.cpp9
3 files changed, 70 insertions, 54 deletions
diff --git a/Makefile b/Makefile
index 9b09161..46ebf2e 100644
--- a/Makefile
+++ b/Makefile
@@ -1,2 +1,6 @@
-test: test.cpp promise.hpp
- g++ -o test test.cpp -std=c++17
+.PHONY: all
+all: test14 test17
+test14: test.cpp promise.hpp
+ g++ -o $@ test.cpp -std=c++17
+test17: test.cpp promise.hpp
+ g++ -o $@ test.cpp -std=c++14
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 <tederminant@gmail.com>
+ *
+ * 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
diff --git a/test.cpp b/test.cpp
index 242222d..d99806f 100644
--- a/test.cpp
+++ b/test.cpp
@@ -1,6 +1,7 @@
#include <string>
#include "promise.hpp"
using promise::promise_t;
+using promise::any_cast;
struct A {
int operator()(int x) {
@@ -75,9 +76,9 @@ int main() {
auto p4 = promise::all(std::vector<promise_t>{p1, p2, p3})
.then([](const promise::values_t values) {
- printf("%d %s %s\n", std::any_cast<int>(values[0]),
- std::any_cast<std::string>(values[1]).c_str(),
- std::any_cast<std::string>(values[2]).c_str());
+ printf("%d %s %s\n", any_cast<int>(values[0]),
+ any_cast<std::string>(values[1]).c_str(),
+ any_cast<std::string>(values[2]).c_str());
return 100;
});
@@ -87,7 +88,7 @@ int main() {
return reason;
})
.then([](const promise::values_t values) {
- printf("finally %d\n", std::any_cast<int>(values[1]));
+ printf("finally %d\n", any_cast<int>(values[1]));
return promise::none;
});
puts("calling t");