Skip to content

Instantly share code, notes, and snippets.

@qookei
Created April 3, 2020 22:58
Show Gist options
  • Save qookei/79db4dc57aa823159c37ea0c3d01d9f7 to your computer and use it in GitHub Desktop.
Save qookei/79db4dc57aa823159c37ea0c3d01d9f7 to your computer and use it in GitHub Desktop.
#include <iostream>
#include <tuple>
#include <array>
struct RecvBuffer{};
struct SendBuffer{};
struct ImbueCredentials{};
struct ExtractCredentials{};
struct RecvInline{};
struct Offer{};
struct Accept{};
struct PushDescriptor{};
struct PullDescriptor{};
struct Result { virtual ~Result() {} virtual void parse(void *&element) = 0; };
struct RecvBufferResult : public Result { int error() { return _error; } void parse(void *&element) override { _error = 1; } private: int _error; };
struct SendBufferResult : public Result { int error() { return _error; } void parse(void *&element) override { _error = 2; } private: int _error; };
struct ImbueCredentialsResult : public Result { int error() { return _error; } void parse(void *&element) override { _error = 3; } private: int _error; };
struct ExtractCredentialsResult : public Result { int error() { return _error; } void parse(void *&element) override { _error = 4; } private: int _error; };
struct RecvInlineResult : public Result { int error() { return _error; } void parse(void *&element) override { _error = 5; } private: int _error; };
struct OfferResult : public Result { int error() { return _error; } void parse(void *&element) override { _error = 6; } private: int _error; };
struct AcceptResult : public Result { int error() { return _error; } void parse(void *&element) override { _error = 7; } private: int _error; };
struct PushDescriptorResult : public Result { int error() { return _error; } void parse(void *&element) override { _error = 8; } private: int _error; };
struct PullDescriptorResult : public Result { int error() { return _error; } void parse(void *&element) override { _error = 9; } private: int _error; };
struct HelAction { int i; };
HelAction createActionFrom(const RecvBuffer &) { return HelAction{1}; }
HelAction createActionFrom(const SendBuffer &) { return HelAction{2}; }
HelAction createActionFrom(const ImbueCredentials &) { return HelAction{3}; }
HelAction createActionFrom(const ExtractCredentials &) { return HelAction{4}; }
HelAction createActionFrom(const RecvInline &) { return HelAction{5}; }
HelAction createActionFrom(const Offer &) { return HelAction{6}; }
HelAction createActionFrom(const Accept &) { return HelAction{7}; }
HelAction createActionFrom(const PushDescriptor &) { return HelAction{8}; }
HelAction createActionFrom(const PullDescriptor &) { return HelAction{9}; }
struct TransmissionError { int i; };
template <typename T>
struct ResultTypeTransformation { using type = void; };
#define AddTypeResultTransform(t)\
template <> \
struct ResultTypeTransformation<t> { using type = t##Result; }
AddTypeResultTransform(RecvBuffer);
AddTypeResultTransform(SendBuffer);
AddTypeResultTransform(ImbueCredentials);
AddTypeResultTransform(ExtractCredentials);
AddTypeResultTransform(RecvInline);
AddTypeResultTransform(Offer);
AddTypeResultTransform(Accept);
AddTypeResultTransform(PushDescriptor);
AddTypeResultTransform(PullDescriptor);
template <typename T>
using ResultTypeFor = typename ResultTypeTransformation<T>::type;
template <typename ...Args>
struct Transmission {
Transmission(std::tuple<Args...> actions)
:_results{ResultTypeFor<Args>{}...} {
[&]<std::size_t ...p>(std::index_sequence<p...>) {
((_actions[p] = createActionFrom(std::get<p>(actions))), ...);
} (std::make_index_sequence<sizeof...(Args)>{});
// submit _actions
// ...
complete(nullptr);
}
// replace with co_await stuff to return the values
auto operator *() {
return std::tuple_cat(std::make_tuple(TransmissionError{0}), _results);
}
private:
void complete(void *ptr) {
[&]<size_t ...p>(std::index_sequence<p...>) {
(std::get<p>(_results).parse(ptr), ...);
} (std::make_index_sequence<sizeof...(Args)>{});
}
std::array<HelAction, sizeof...(Args)> _actions;
std::tuple<ResultTypeFor<Args>...> _results;
};
template <typename ...Args>
auto asyncSubmit(Args &&...args) {
return Transmission{std::make_tuple(args...)};
}
void test1() {
auto [error, offer, send_buffer, recv_buffer, cred] = *asyncSubmit(Offer{}, SendBuffer{}, RecvBuffer{}, ImbueCredentials{});
std::cout << offer.error() << " " << send_buffer.error() << " " << recv_buffer.error() << " " << cred.error() << "\n";
}
void test2() {
auto [error, accept, recv_buffer, send_buffer, cred] = *asyncSubmit(Accept{}, RecvBuffer{}, SendBuffer{}, ExtractCredentials{});
std::cout << accept.error() << " " << recv_buffer.error() << " " << send_buffer.error() << " " << cred.error() << "\n";
}
void test3() {
auto [error, offer, send_req, recv_resp] = *asyncSubmit(Offer{}, SendBuffer{}, RecvBuffer{});
std::cout << offer.error() << " " << send_req.error() << " " << recv_resp.error() << "\n";
}
int main() {
test1();
test2();
test3();
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment