#include "httplib.h"
#include "wren.h"
// A struct to hold the context for an asynchronous HTTP request
struct RequestContext {
std::string url;
WrenHandle* callback;
WrenVM* vm;
std::string response;
bool error;
};
// A class to manage asynchronous HTTP requests
class AsyncHttp {
public:
AsyncHttp(WrenVM* vm) : vm_(vm), running_(true) {
// Create a pool of worker threads
for (int i = 0; i < 4; ++i) {
threads_.emplace_back([this] {
while (running_) {
RequestContext* context = requestQueue_.pop();
if (!running_) break;
httplib::Client cli("http://example.com");
if (auto res = cli.Get(context->url.c_str())) {
context->response = res->body;
context->error = false;
} else {
context->response = "Error: " + to_string(res.error());
context->error = true;
}
completionQueue_.push(context);
}
});
}
}
~AsyncHttp() {
running_ = false;
// Add dummy requests to unblock worker threads
for (size_t i = 0; i < threads_.size(); ++i) {
requestQueue_.push(nullptr);
}
for (auto& thread : threads_) {
thread.join();
}
}
void request(const std::string& url, WrenHandle* callback) {
RequestContext* context = new RequestContext{url, callback, vm_};
requestQueue_.push(context);
}
void processCompletions() {
while (!completionQueue_.empty()) {
RequestContext* context = completionQueue_.pop();
// Create a handle for the callback function
WrenHandle* callHandle = wrenMakeCallHandle(vm_, "call(_)");
wrenEnsureSlots(vm_, 2);
wrenSetSlotHandle(vm_, 0, context->callback);
wrenSetSlotString(vm_, 1, context->response.c_str());
wrenCall(vm_, callHandle);
wrenReleaseHandle(vm_, callHandle);
wrenReleaseHandle(vm_, context->callback);
delete context;
}
}
private:
WrenVM* vm_;
bool running_;
std::vector<std::thread> threads_;
ThreadSafeQueue<RequestContext*> requestQueue_;
ThreadSafeQueue<RequestContext*> completionQueue_;
};