Skip to content

Instantly share code, notes, and snippets.

@NateSeymour
Created March 11, 2019 21:23
Show Gist options
  • Save NateSeymour/091b8ae6cf9ac6d0bfea0a327b61ccda to your computer and use it in GitHub Desktop.
Save NateSeymour/091b8ae6cf9ac6d0bfea0a327b61ccda to your computer and use it in GitHub Desktop.
Javascript promises recreated in C++
#include <iostream>
#include <string>
#include "Promise.h"
int main()
{
std::string my_string = "This is my string!";
js::Promise<std::string>::$([my_string](auto p, auto value) -> void {
// Play around with the string a bit
p->resolve(my_string);
})->then([](auto p, auto value) -> void {
std::cout << value << std::endl;
});
std::cin.get();
return 0;
}
#pragma once
#include <mutex>
namespace js {
template<class C> class Promise
{
public:
bool failure = false;
std::exception exception;
void resolve(C t)
{
this->return_value = t;
}
void reject(C t)
{
this->return_value = t;
this->failure = true;
}
template<typename T> Promise<C>* then(T promise_function) { return this->register_callback(promise_function, true); }
template<typename T> Promise<C>* fail(T promise_function) { return this->register_callback(promise_function, false); }
template<typename T> static Promise<C>* $(T promise_function) { return new Promise<C>(promise_function); }
private:
C return_value;
std::mutex execution_lock;
Promise() {}
template<typename T> Promise(T promise_function)
{
std::thread promise_thread([](T promise_function, Promise<C>* promise) -> void
{
promise->execution_lock.lock();
Promise<C>::safe_call(promise_function, promise, promise);
promise->execution_lock.unlock();
}, promise_function, this);
promise_thread.detach();
}
template<typename T> Promise<C>* register_callback(T promise_function, bool then)
{
Promise<C>* new_promise = new Promise();
std::thread callback_thread([then](T promise_function, Promise<C>* caller, Promise<C>* p) -> void
{
p->execution_lock.lock();
caller->execution_lock.lock();
if (then)
{
if (!caller->failure)
{
Promise<C>::safe_call(promise_function, p, caller);
}
else {
p->reject(caller->return_value);
p->exception = caller->exception;
}
}
else {
if (caller->failure)
{
Promise<C>::safe_call(promise_function, p, caller);
}
}
caller->execution_lock.unlock();
delete caller;
p->execution_lock.unlock();
}, promise_function, this, new_promise);
callback_thread.detach();
return new_promise;
}
template<typename T> static void safe_call(T promise_function, Promise<C>* promise, Promise<C>* caller)
{
try {
promise_function(promise, caller->return_value);
}
catch (C e) {
promise->exception = std::exception();
promise->reject(e);
}
catch (std::exception& e) {
promise->exception = e;
promise->reject(C());
}
catch (...) {
promise->exception = std::exception();
promise->reject(C());
}
}
};
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment