|
#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_;
|
|
};
|