From 25c438b9056e2dee99fcc8680a6c295df9aa939e Mon Sep 17 00:00:00 2001 From: Determinant Date: Thu, 1 Feb 2018 20:21:53 -0500 Subject: ... --- Makefile | 8 +++-- promise.hpp | 107 +++++++++++++++++++++++++++++++++--------------------------- test.cpp | 9 ++--- 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 + * + * 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 #include -#include #include -/** Implement type-safe Promise primitives similar to the ones specified by - * Javascript A+. */ +#if __has_include("any") +#include +#endif + +#if !defined(__cpp_lib_any) +#include +#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 + constexpr auto any_cast = static_cast(std::any_cast); + using bad_any_cast = std::bad_any_cast; +#else +#warning "using any type from boost" + using pm_any_t = boost::any; + template + constexpr auto any_cast = static_cast(boost::any_cast); + using bad_any_cast = boost::bad_any_cast; +#endif + using None = std::nullptr_t; using values_t = std::vector; 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 fulfilled_callback; - //function rejected_callback; std::vector> fulfilled_callbacks; std::vector> 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 cb) { - auto old_cbs = fulfilled_callback; - fulfilled_callback = function( - [cb, old_cbs]() { - old_cbs(); - cb(); - }); - } - - void add_on_rejected(function cb) { - auto old_cbs = rejected_callback; - rejected_callback = function( - [cb, old_cbs]() { - old_cbs(); - cb(); - }); - } - */ - void add_on_fulfilled(function 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 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(_result))); - } catch (std::bad_any_cast e) { PROMISE_ERR_MISMATCH_TYPE; } + return ret_type(on_fulfilled(any_cast(_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(_result))); - } catch (std::bad_any_cast e) { PROMISE_ERR_MISMATCH_TYPE; } + return fulfill_ret_type(on_fulfilled(any_cast(_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(_reason))); - } catch (std::bad_any_cast e) { PROMISE_ERR_MISMATCH_TYPE; } + return reject_ret_type(on_rejected(any_cast(_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(_reason))); - } catch (std::bad_any_cast e) { PROMISE_ERR_MISMATCH_TYPE; } + return ret_type(on_rejected(any_cast(_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 #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{p1, p2, p3}) .then([](const promise::values_t values) { - printf("%d %s %s\n", std::any_cast(values[0]), - std::any_cast(values[1]).c_str(), - std::any_cast(values[2]).c_str()); + printf("%d %s %s\n", any_cast(values[0]), + any_cast(values[1]).c_str(), + any_cast(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(values[1])); + printf("finally %d\n", any_cast(values[1])); return promise::none; }); puts("calling t"); -- cgit v1.2.3