summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/CurlTask.cc27
-rw-r--r--src/TaskMan.cc13
2 files changed, 39 insertions, 1 deletions
diff --git a/src/CurlTask.cc b/src/CurlTask.cc
new file mode 100644
index 0000000..3dce322
--- /dev/null
+++ b/src/CurlTask.cc
@@ -0,0 +1,27 @@
+#include "CurlTask.h"
+
+Balau::CurlTask::CurlTask() {
+ m_curlHandle = curl_easy_init();
+ curl_easy_setopt(m_curlHandle, CURLOPT_WRITEFUNCTION, reinterpret_cast<curl_write_callback>(writeFunctionStatic));
+ curl_easy_setopt(m_curlHandle, CURLOPT_WRITEDATA, this);
+ curl_easy_setopt(m_curlHandle, CURLOPT_READFUNCTION, reinterpret_cast<curl_read_callback>(readFunctionStatic));
+ curl_easy_setopt(m_curlHandle, CURLOPT_READDATA, this);
+ curl_easy_setopt(m_curlHandle, CURLOPT_DEBUGFUNCTION, reinterpret_cast<curl_debug_callback>(debugFunctionStatic));
+ curl_easy_setopt(m_curlHandle, CURLOPT_DEBUGDATA, this);
+}
+
+size_t Balau::CurlTask::writeFunctionStatic(char * ptr, size_t size, size_t nmemb, void * userdata) {
+ CurlTask * curlTask = (CurlTask *) userdata;
+ return curlTask->writeFunction(ptr, size, nmemb);
+}
+
+size_t Balau::CurlTask::readFunctionStatic(void * ptr, size_t size, size_t nmemb, void * userdata) {
+ CurlTask * curlTask = (CurlTask *) userdata;
+ return curlTask->readFunction(ptr, size, nmemb);
+}
+
+int Balau::CurlTask::debugFunctionStatic(CURL * easy, curl_infotype info, char * str, size_t str_len, void * userdata) {
+ CurlTask * curlTask = (CurlTask *) userdata;
+ IAssert(easy == curlTask->m_curlHandle, "Got a debug callback for a handle that isn't our own.");
+ return curlTask->debugFunction(info, str, str_len);
+}
diff --git a/src/TaskMan.cc b/src/TaskMan.cc
index 1562c4c..5f028ae 100644
--- a/src/TaskMan.cc
+++ b/src/TaskMan.cc
@@ -71,6 +71,7 @@ class CurlSharedManager : public Balau::AtStart, Balau::AtExit {
lock->leave();
}
void doStart() {
+ curl_global_init(CURL_GLOBAL_ALL);
static SharedLocks locks;
s_curlshared = curl_share_init();
curl_share_setopt(s_curlshared, CURLSHOPT_SHARE, CURL_LOCK_DATA_COOKIE);
@@ -267,14 +268,17 @@ int Balau::TaskMan::curlSocketCallback(CURL * easy, curl_socket_t s, int what, v
evt->stop();
break;
case CURL_POLL_IN:
+ evt->stop();
evt->set(s, ev::READ);
evt->start();
break;
case CURL_POLL_OUT:
+ evt->stop();
evt->set(s, ev::WRITE);
evt->start();
break;
case CURL_POLL_INOUT:
+ evt->stop();
evt->set(s, ev::READ | ev::WRITE);
evt->start();
break;
@@ -403,11 +407,12 @@ int Balau::TaskMan::mainLoop() {
// if we begin that loop with any pending task, just don't loop, so we can add them immediately.
bool noWait = !m_pendingAdd.isEmpty() || !yielded.empty() || !stopped.empty();
+ bool curlNeedsSpin = !m_curlTimer.is_active() && m_curlStillRunning != 0;
// libev's event "loop". We always runs it once though.
m_allowedToSignal = true;
Printer::elog(E_TASK, "TaskMan at %p Going to libev main loop; stopped = %s", this, m_stopped ? "true" : "false");
- ev_run(m_loop, noWait || m_stopped ? EVRUN_NOWAIT : EVRUN_ONCE);
+ ev_run(m_loop, noWait || curlNeedsSpin || m_stopped ? EVRUN_NOWAIT : EVRUN_ONCE);
Printer::elog(E_TASK, "TaskMan at %p Getting out of libev main loop", this);
// calling async's idle
@@ -458,6 +463,8 @@ int Balau::TaskMan::mainLoop() {
yielded = yielded2;
yielded2.clear();
+ bool curlGotHandle = false;
+
// Adding tasks that were added, maybe from other threads
while (!m_pendingAdd.isEmpty()) {
Printer::elog(E_TASK, "TaskMan at %p trying to pop a task...", this);
@@ -470,10 +477,14 @@ int Balau::TaskMan::mainLoop() {
starting.insert(t);
CurlTask * curlTask = dynamic_cast<CurlTask *>(t);
if (curlTask) {
+ curlGotHandle = true;
curl_multi_add_handle(m_curlMulti, curlTask->m_curlHandle);
}
}
+ if (curlGotHandle || curlNeedsSpin)
+ curl_multi_socket_all(m_curlMulti, &m_curlStillRunning);
+
// Finally, let's destroy tasks that no longer are necessary.
bool didDelete;
do {