mirror of
https://github.com/geode-sdk/geode.git
synced 2024-11-26 17:36:05 -05:00
almost finished reworking promises, they compile now but sometimes dont work
This commit is contained in:
parent
8101ae50ab
commit
bc98c9b84e
6 changed files with 109 additions and 114 deletions
|
@ -11,7 +11,7 @@ namespace geode {
|
|||
std::optional<uint8_t> percentage;
|
||||
|
||||
DefaultProgress() = default;
|
||||
DefaultProgress(auto msg) : message(msg) {}
|
||||
DefaultProgress(std::string const& msg) : message(msg) {}
|
||||
DefaultProgress(auto msg, uint8_t percentage) : message(msg), percentage(percentage) {}
|
||||
};
|
||||
}
|
||||
|
@ -46,12 +46,12 @@ namespace geode {
|
|||
Promise() : m_data(std::make_shared<Data>()) {}
|
||||
|
||||
Promise(utils::MiniFunction<void(OnResolved, OnRejected)> source, bool threaded = true)
|
||||
: Promise([source](auto resolve, auto reject, auto, auto) {
|
||||
: Promise([source](auto resolve, auto reject, auto, auto const&) {
|
||||
source(resolve, reject);
|
||||
}) {}
|
||||
}, threaded) {}
|
||||
|
||||
Promise(utils::MiniFunction<void(OnResolved, OnRejected, OnProgress, OnCancelled)> source, bool threaded = true)
|
||||
: Promise([source](auto onStateChanged) {
|
||||
Promise(utils::MiniFunction<void(OnResolved, OnRejected, OnProgress, std::atomic_bool const&)> source, bool threaded = true)
|
||||
: Promise([source](auto onStateChanged, auto const& cancelled) {
|
||||
source(
|
||||
[onStateChanged](auto&& value) {
|
||||
onStateChanged(State(std::in_place_index<STATE_VALUE_INDEX>, value));
|
||||
|
@ -62,13 +62,12 @@ namespace geode {
|
|||
[onStateChanged](auto&& progress) {
|
||||
onStateChanged(State(std::in_place_index<STATE_PROGRESS_INDEX>, progress));
|
||||
},
|
||||
[onStateChanged]() {
|
||||
onStateChanged(State(std::in_place_index<STATE_CANCELLED_INDEX>, CancelledState()));
|
||||
}
|
||||
cancelled
|
||||
);
|
||||
}) {}
|
||||
}, threaded, std::monostate()) {}
|
||||
|
||||
Promise(utils::MiniFunction<void(OnStateChange)> source, bool threaded = true) : m_data(std::make_shared<Data>()) {
|
||||
Promise(utils::MiniFunction<void(OnStateChange, std::atomic_bool const&)> source, bool threaded, std::monostate tag) : m_data(std::make_shared<Data>()) {
|
||||
m_data->shouldStartThreaded = threaded;
|
||||
if (threaded) {
|
||||
std::thread([source = std::move(source), data = m_data]() mutable {
|
||||
Promise::invoke_source(std::move(source), data);
|
||||
|
@ -88,7 +87,10 @@ namespace geode {
|
|||
template <class T2>
|
||||
requires (!std::is_void_v<T2>)
|
||||
Promise<T2, E, P> then(utils::MiniFunction<T2(T)>&& callback) {
|
||||
if (m_data->cancelled) return make_cancelled<T2, E, P>();
|
||||
if (m_data->cancelled) {
|
||||
return make_cancelled<T2, E, P>();
|
||||
}
|
||||
|
||||
std::unique_lock<std::mutex> _(m_data->mutex);
|
||||
|
||||
// Check if this Promise has already been resolved, and if so
|
||||
|
@ -103,47 +105,16 @@ namespace geode {
|
|||
return make_cancelled<T2, E, P>();
|
||||
}
|
||||
|
||||
return Promise<T2, E, P>([data = m_data, callback](auto fwdStateToNextPromise) {
|
||||
data->callback = [fwdStateToNextPromise, callback](auto&& state) {
|
||||
// Can't use std::visit if Value and Error are the same >:(
|
||||
switch (state.index()) {
|
||||
case STATE_VALUE_INDEX: {
|
||||
auto mapped = callback(std::get<STATE_VALUE_INDEX>(state));
|
||||
fwdStateToNextPromise(Promise<T2, E, P>::State(
|
||||
std::in_place_index<STATE_VALUE_INDEX>,
|
||||
std::move(mapped)
|
||||
));
|
||||
} break;
|
||||
|
||||
case STATE_ERROR_INDEX: {
|
||||
fwdStateToNextPromise(Promise<T2, E, P>::State(
|
||||
std::in_place_index<STATE_ERROR_INDEX>,
|
||||
std::move(std::get<STATE_ERROR_INDEX>(state))
|
||||
));
|
||||
} break;
|
||||
|
||||
case STATE_PROGRESS_INDEX: {
|
||||
fwdStateToNextPromise(Promise<T2, E, P>::State(
|
||||
std::in_place_index<STATE_PROGRESS_INDEX>,
|
||||
std::move(std::get<STATE_PROGRESS_INDEX>(state))
|
||||
));
|
||||
} break;
|
||||
|
||||
case STATE_CANCELLED_INDEX: {
|
||||
fwdStateToNextPromise(Promise<T2, E, P>::State(
|
||||
std::in_place_index<STATE_CANCELLED_INDEX>,
|
||||
std::move(std::get<STATE_CANCELLED_INDEX>(state))
|
||||
));
|
||||
} break;
|
||||
}
|
||||
};
|
||||
});
|
||||
return make_fwd<STATE_VALUE_INDEX, T2, E, P>(callback, m_data);
|
||||
}
|
||||
|
||||
template <class T2, class E2>
|
||||
requires (!std::is_void_v<T2>)
|
||||
Promise<T2, E2, P> then(utils::MiniFunction<Result<T2, E2>(Result<T, E>)>&& callback) {
|
||||
if (m_data->cancelled) return make_cancelled<T2, E2, P>();
|
||||
if (m_data->cancelled) {
|
||||
return make_cancelled<T2, E2, P>();
|
||||
}
|
||||
|
||||
std::unique_lock<std::mutex> _(m_data->mutex);
|
||||
|
||||
// Check if this Promise has already been resolved, and if so
|
||||
|
@ -163,8 +134,8 @@ namespace geode {
|
|||
return make_cancelled<T2, E2, P>();
|
||||
}
|
||||
|
||||
return Promise<T2, E2, P>([data = m_data, callback](auto fwdStateToNextPromise) {
|
||||
data->callback = [fwdStateToNextPromise, callback](auto&& state) {
|
||||
return Promise<T2, E2, P>([data = m_data, callback](auto fwdStateToNextPromise, auto const& nextPromiseCancelled) {
|
||||
data->callback = [&nextPromiseCancelled, fwdStateToNextPromise, callback](auto&& state) {
|
||||
// Can't use std::visit if Value and Error are the same >:(
|
||||
switch (state.index()) {
|
||||
case STATE_VALUE_INDEX: {
|
||||
|
@ -214,7 +185,7 @@ namespace geode {
|
|||
} break;
|
||||
}
|
||||
};
|
||||
});
|
||||
}, m_data->shouldStartThreaded, std::monostate());
|
||||
}
|
||||
|
||||
Promise expect(utils::MiniFunction<void(Error)>&& callback) {
|
||||
|
@ -226,7 +197,10 @@ namespace geode {
|
|||
template <class E2>
|
||||
requires (!std::is_void_v<E2>)
|
||||
Promise<T, E2, P> expect(utils::MiniFunction<E2(E)>&& callback) {
|
||||
if (m_data->cancelled) return make_cancelled<T, E2, P>();
|
||||
if (m_data->cancelled) {
|
||||
return make_cancelled<T, E2, P>();
|
||||
}
|
||||
|
||||
std::unique_lock<std::mutex> _(m_data->mutex);
|
||||
|
||||
// Check if this Promise has already been resolved, and if so
|
||||
|
@ -241,41 +215,7 @@ namespace geode {
|
|||
return make_cancelled<T, E2, P>();
|
||||
}
|
||||
|
||||
return Promise<T, E2, P>([data = m_data, callback](auto fwdStateToNextPromise) {
|
||||
data->callback = [fwdStateToNextPromise, callback](auto&& state) {
|
||||
// Can't use std::visit if Value and Error are the same >:(
|
||||
switch (state.index()) {
|
||||
case STATE_VALUE_INDEX: {
|
||||
fwdStateToNextPromise(Promise<T, E2, P>::State(
|
||||
std::in_place_index<STATE_VALUE_INDEX>,
|
||||
std::move(std::get<STATE_VALUE_INDEX>(state))
|
||||
));
|
||||
} break;
|
||||
|
||||
case STATE_ERROR_INDEX: {
|
||||
auto mapped = callback(std::get<STATE_ERROR_INDEX>(state));
|
||||
fwdStateToNextPromise(Promise<T, E2, P>::State(
|
||||
std::in_place_index<STATE_ERROR_INDEX>,
|
||||
std::move(mapped)
|
||||
));
|
||||
} break;
|
||||
|
||||
case STATE_PROGRESS_INDEX: {
|
||||
fwdStateToNextPromise(Promise<T, E2, P>::State(
|
||||
std::in_place_index<STATE_PROGRESS_INDEX>,
|
||||
std::move(std::get<STATE_PROGRESS_INDEX>(state))
|
||||
));
|
||||
} break;
|
||||
|
||||
case STATE_CANCELLED_INDEX: {
|
||||
fwdStateToNextPromise(Promise<T, E2, P>::State(
|
||||
std::in_place_index<STATE_CANCELLED_INDEX>,
|
||||
std::move(std::get<STATE_CANCELLED_INDEX>(state))
|
||||
));
|
||||
} break;
|
||||
}
|
||||
};
|
||||
});
|
||||
return make_fwd<STATE_ERROR_INDEX, T, E2, P>(callback, m_data);
|
||||
}
|
||||
|
||||
Promise progress(utils::MiniFunction<void(Progress)>&& callback) {
|
||||
|
@ -287,7 +227,10 @@ namespace geode {
|
|||
template <class P2>
|
||||
requires (!std::is_void_v<P2>)
|
||||
Promise<T, E, P2> progress(utils::MiniFunction<P2(P)>&& callback) {
|
||||
if (m_data->cancelled) return make_cancelled<T, E, P2>();
|
||||
if (m_data->cancelled) {
|
||||
return make_cancelled<T, E, P2>();
|
||||
}
|
||||
|
||||
std::unique_lock<std::mutex> _(m_data->mutex);
|
||||
|
||||
// Check if this Promise has already been resolved
|
||||
|
@ -295,21 +238,14 @@ namespace geode {
|
|||
return make_cancelled<T, E, P2>();
|
||||
}
|
||||
|
||||
return Promise<T, E, P2>([data = m_data, callback](auto fwdStateToNextPromise) {
|
||||
data->callback = [fwdStateToNextPromise, callback](auto&& state) {
|
||||
if (state.index() == STATE_PROGRESS_INDEX) {
|
||||
auto mapped = callback(std::get<STATE_PROGRESS_INDEX>(state));
|
||||
fwdStateToNextPromise(Promise<T, E, P2>::State(std::in_place_index<STATE_PROGRESS_INDEX>, mapped));
|
||||
}
|
||||
else {
|
||||
fwdStateToNextPromise(state);
|
||||
}
|
||||
};
|
||||
});
|
||||
return make_fwd<STATE_PROGRESS_INDEX, T, E, P2>(callback, m_data);
|
||||
}
|
||||
|
||||
Promise finally(utils::MiniFunction<void()>&& callback) {
|
||||
if (m_data->cancelled) return make_cancelled();
|
||||
if (m_data->cancelled) {
|
||||
return make_cancelled();
|
||||
}
|
||||
|
||||
std::unique_lock<std::mutex> _(m_data->mutex);
|
||||
|
||||
// Check if this Promise has already been resolved, and if so
|
||||
|
@ -380,6 +316,7 @@ namespace geode {
|
|||
OnStateChange callback;
|
||||
std::optional<std::variant<Value, Error>> result;
|
||||
std::atomic_bool cancelled;
|
||||
bool shouldStartThreaded;
|
||||
};
|
||||
std::shared_ptr<Data> m_data;
|
||||
|
||||
|
@ -390,12 +327,59 @@ namespace geode {
|
|||
return std::move(ret);
|
||||
}
|
||||
|
||||
template <size_t Ix, class T2, class E2, class P2>
|
||||
static Promise<T2, E2, P2> make_fwd(auto mapper, std::shared_ptr<Data> data) {
|
||||
return Promise<T2, E2, P2>([data, mapper](auto fwdStateToNextPromise, auto const&) {
|
||||
data->callback = [fwdStateToNextPromise, mapper](auto&& state) {
|
||||
if (state.index() == Ix) {
|
||||
auto mapped = mapper(std::get<Ix>(state));
|
||||
fwdStateToNextPromise(Promise<T2, E2, P2>::State(
|
||||
std::in_place_index<Ix>,
|
||||
mapped
|
||||
));
|
||||
}
|
||||
// Can't use std::visit if Value and Error are the same >:(
|
||||
else switch (state.index()) {
|
||||
case STATE_VALUE_INDEX: if constexpr (Ix != STATE_VALUE_INDEX) {
|
||||
fwdStateToNextPromise(Promise<T2, E2, P2>::State(
|
||||
std::in_place_index<STATE_VALUE_INDEX>,
|
||||
std::move(std::get<STATE_VALUE_INDEX>(state))
|
||||
));
|
||||
} break;
|
||||
|
||||
case STATE_ERROR_INDEX: if constexpr (Ix != STATE_ERROR_INDEX) {
|
||||
fwdStateToNextPromise(Promise<T2, E2, P2>::State(
|
||||
std::in_place_index<STATE_ERROR_INDEX>,
|
||||
std::move(std::get<STATE_ERROR_INDEX>(state))
|
||||
));
|
||||
} break;
|
||||
|
||||
case STATE_PROGRESS_INDEX: if constexpr (Ix != STATE_PROGRESS_INDEX) {
|
||||
fwdStateToNextPromise(Promise<T2, E2, P2>::State(
|
||||
std::in_place_index<STATE_PROGRESS_INDEX>,
|
||||
std::move(std::get<STATE_PROGRESS_INDEX>(state))
|
||||
));
|
||||
} break;
|
||||
|
||||
case STATE_CANCELLED_INDEX: if constexpr (Ix != STATE_CANCELLED_INDEX) {
|
||||
fwdStateToNextPromise(Promise<T2, E2, P2>::State(
|
||||
std::in_place_index<STATE_CANCELLED_INDEX>,
|
||||
std::move(std::get<STATE_CANCELLED_INDEX>(state))
|
||||
));
|
||||
} break;
|
||||
}
|
||||
};
|
||||
}, data->shouldStartThreaded, std::monostate());
|
||||
}
|
||||
|
||||
static void invoke_callback(State&& state, std::shared_ptr<Data> data) {
|
||||
if (data->cancelled) return;
|
||||
std::unique_lock<std::mutex> _(data->mutex);
|
||||
|
||||
if (data->callback) {
|
||||
data->callback(State(state));
|
||||
Loader::get()->queueInMainThread([callback = data->callback, state = State(state)]() {
|
||||
callback(state);
|
||||
});
|
||||
}
|
||||
|
||||
// Store the state to let future installed callbacks be immediately resolved
|
||||
|
@ -410,10 +394,13 @@ namespace geode {
|
|||
}
|
||||
}
|
||||
|
||||
static void invoke_source(utils::MiniFunction<void(OnStateChange)>&& source, std::shared_ptr<Data> data) {
|
||||
source([data](auto&& state) {
|
||||
static void invoke_source(utils::MiniFunction<void(OnStateChange, std::atomic_bool const&)>&& source, std::shared_ptr<Data> data) {
|
||||
source(
|
||||
[data](auto&& state) {
|
||||
invoke_callback(std::move(state), data);
|
||||
});
|
||||
},
|
||||
data->cancelled
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -472,11 +459,12 @@ namespace geode {
|
|||
// the same IDs again, so technically if some promise takes
|
||||
// literally forever then this could cause issues later on
|
||||
static size_t ID_COUNTER = 0;
|
||||
ID_COUNTER += 1;
|
||||
// Reserve 0 for PromiseEventFilter not listening to anything
|
||||
if (ID_COUNTER == 0) {
|
||||
ID_COUNTER += 1;
|
||||
}
|
||||
size_t id = ++ID_COUNTER;
|
||||
size_t id = ID_COUNTER;
|
||||
this
|
||||
->then([id](auto&& value) {
|
||||
PromiseEvent<T, E, P>(id, std::variant<T, E, P> { std::in_place_index<0>, std::forward<T>(value) }).post();
|
||||
|
|
|
@ -150,7 +150,7 @@ namespace server {
|
|||
|
||||
template <class As>
|
||||
As* find(Query const& query) {
|
||||
auto it = std::find_if(m_values.begin(), m_values.end(), [](auto const& q) {
|
||||
auto it = std::find_if(m_values.begin(), m_values.end(), [query](auto const& q) {
|
||||
return q.first == query;
|
||||
});
|
||||
if (it == m_values.end()) {
|
||||
|
@ -226,7 +226,11 @@ namespace server {
|
|||
Cache m_cache;
|
||||
|
||||
ServerPromise<Result> fetch(Query const& query) {
|
||||
return m_cache.pend(Query(query));
|
||||
return F(Query(query))
|
||||
.then([this, query = std::move(query)](auto res) {
|
||||
m_cache.add(Query(query), Result(res));
|
||||
});
|
||||
// return m_cache.pend(Query(query));
|
||||
}
|
||||
|
||||
public:
|
||||
|
|
|
@ -93,7 +93,8 @@ protected:
|
|||
this->setSprite(CCSprite::create("loadingCircle.png"));
|
||||
static_cast<CCSprite*>(m_sprite)->setBlendFunc({ GL_ONE, GL_ONE });
|
||||
m_sprite->runAction(CCRepeatForever::create(CCRotateBy::create(1.f, 360.f)));
|
||||
m_listener.setFilter(server::ServerResultCache<&server::getModLogo>::shared().get(id).listen());
|
||||
m_listener.setFilter(server::getModLogo(id).listen());
|
||||
// m_listener.setFilter(server::ServerResultCache<&server::getModLogo>::shared().get(id).listen());
|
||||
}
|
||||
|
||||
return true;
|
||||
|
|
|
@ -110,7 +110,7 @@ typename ModListSource::PagePromise ModListSource::loadPage(size_t page, bool up
|
|||
// Return a generic "Coming soon" message if there's no provider set
|
||||
if (!m_provider.get) {
|
||||
return PagePromise([this, page](auto, auto reject) {
|
||||
reject("Coming soon! ;)");
|
||||
reject(LoadPageError("Coming soon! ;)"));
|
||||
});
|
||||
}
|
||||
if (!update && m_cachedPages.contains(page)) {
|
||||
|
|
|
@ -24,7 +24,7 @@ public:
|
|||
std::optional<std::string> details;
|
||||
|
||||
LoadPageError() = default;
|
||||
LoadPageError(auto msg) : message(msg) {}
|
||||
LoadPageError(std::string const& msg) : message(msg) {}
|
||||
LoadPageError(auto msg, auto details) : message(msg), details(details) {}
|
||||
};
|
||||
|
||||
|
|
|
@ -115,7 +115,7 @@ std::string urlParamEncode(std::string_view const input) {
|
|||
WebPromise WebRequest::send(std::string_view method, std::string_view url) {
|
||||
m_impl->m_method = method;
|
||||
m_impl->m_url = url;
|
||||
return WebPromise([impl = m_impl](auto resolve, auto reject, auto progress, auto cancelled) {
|
||||
return WebPromise([impl = m_impl](auto resolve, auto reject, auto progress, auto const& cancelled) {
|
||||
// Init Curl
|
||||
auto curl = curl_easy_init();
|
||||
if (!curl) {
|
||||
|
@ -130,11 +130,13 @@ WebPromise WebRequest::send(std::string_view method, std::string_view url) {
|
|||
struct ResponseData {
|
||||
WebResponse response;
|
||||
Impl* impl;
|
||||
WebPromise::Progress progress;
|
||||
WebPromise::OnProgress progress;
|
||||
std::atomic_bool const& cancelled;
|
||||
} responseData = {
|
||||
.response = WebResponse(),
|
||||
.impl = impl.get(),
|
||||
.progress = progress,
|
||||
.cancelled = cancelled,
|
||||
};
|
||||
|
||||
// Store downloaded response data into a byte vector
|
||||
|
|
Loading…
Reference in a new issue