17 #include <curl/curl.h> 18 #include <sys/select.h> 30 constexpr
const long kSmallDelayMs = 100;
31 constexpr
const long kMaxDelayMs = 500;
36 : mutex_(
"NetworkThread"),
37 cond_(
"Networking new request"),
38 multi_handle_(curl_multi_init()),
45 CHECK(!thread_.
joinable()) <<
"Need to call Stop() before destroying";
46 DCHECK(requests_.empty());
47 curl_multi_cleanup(multi_handle_);
51 shutdown_.store(
true, std::memory_order_release);
57 std::unique_lock<Mutex> lock(mutex_);
62 std::unique_lock<Mutex> lock(mutex_);
63 DCHECK(!shutdown_.load(std::memory_order_acquire));
65 requests_.push_back(request);
66 CHECK_EQ(curl_multi_add_handle(multi_handle_, request->curl_), CURLM_OK);
71 std::unique_lock<Mutex> lock(mutex_);
72 for (
auto it = requests_.begin(); it != requests_.end(); it++) {
74 CHECK_EQ(curl_multi_remove_handle(multi_handle_, request->curl_),
82 void NetworkThread::ThreadMain() {
83 while (!shutdown_.load(std::memory_order_acquire)) {
91 std::unique_lock<Mutex> lock(mutex_);
95 CHECK_EQ(curl_multi_perform(multi_handle_, &handles), CURLM_OK);
96 no_handles = handles == 0;
100 while (CURLMsg* msg = curl_multi_info_read(multi_handle_, &msg_count)) {
101 if (msg->msg == CURLMSG_DONE) {
102 for (
auto it = requests_.begin(); it != requests_.end(); it++) {
103 if ((*it)->curl_ == msg->easy_handle) {
104 (*it)->OnRequestComplete(msg->data.result);
109 CHECK_EQ(curl_multi_remove_handle(multi_handle_, msg->easy_handle),
113 LOG(DFATAL) <<
"Unknown message type: " << msg->msg;
117 if (curl_multi_fdset(multi_handle_, &fdread, &fdwrite, &fdexc, &maxfd) !=
119 LOG(ERROR) <<
"Error getting file descriptors from CURL";
121 if (curl_multi_timeout(multi_handle_, &timeout_ms) != CURLM_OK) {
122 LOG(ERROR) <<
"Error getting timeout from CURL";
126 timeout_ms = kSmallDelayMs;
128 timeout_ms = std::min(timeout_ms, kMaxDelayMs);
133 std::unique_lock<Mutex> lock(mutex_);
136 timeval timeout = {.tv_sec = timeout_ms / 1000,
137 .tv_usec = (timeout_ms % 1000) * 1000};
138 if (select(maxfd + 1, &fdread, &fdwrite, &fdexc, &timeout) < 0) {
139 if (errno == EBADF) {
143 PLOG(ERROR) <<
"Error waiting for network handles";
bool ContainsRequest(RefPtr< js::XMLHttpRequest > request) const
bool contains(const std::vector< T > &vec, U &&elem)
void AbortRequest(RefPtr< js::XMLHttpRequest > request)
T ResetAndWaitWhileUnlocked(std::unique_lock< _Mutex > &lock)
void AddRequest(RefPtr< js::XMLHttpRequest > request)