summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--includes/CurlTask.h13
-rw-r--r--src/CurlTask.cc27
-rw-r--r--src/TaskMan.cc13
-rw-r--r--win32/project/Balau.vcxproj1
-rw-r--r--win32/project/Balau.vcxproj.filters3
5 files changed, 54 insertions, 3 deletions
diff --git a/includes/CurlTask.h b/includes/CurlTask.h
index f9ac492..0d67aa4 100644
--- a/includes/CurlTask.h
+++ b/includes/CurlTask.h
@@ -1,15 +1,24 @@
#pragma once
#include <curl/curl.h>
-#include <Task.h>
+#include <StacklessTask.h>
#include <TaskMan.h>
namespace Balau {
-class CurlTask : public Task {
+class CurlTask : public StacklessTask {
+public:
+ CurlTask();
friend class TaskMan;
protected:
CURL * m_curlHandle;
+private:
+ static size_t writeFunctionStatic(char * ptr, size_t size, size_t nmemb, void * userdata);
+ virtual size_t writeFunction(char * ptr, size_t size, size_t nmemb) { return size * nmemb; }
+ static size_t readFunctionStatic(void * ptr, size_t size, size_t nmemb, void * userdata);
+ virtual size_t readFunction(void * ptr, size_t size, size_t nmemb) { return CURL_READFUNC_ABORT; }
+ static int debugFunctionStatic(CURL * easy, curl_infotype info, char * str, size_t str_len, void * userdata);
+ virtual int debugFunction(curl_infotype info, char * str, size_t str_len) { return 0; }
};
};
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 {
diff --git a/win32/project/Balau.vcxproj b/win32/project/Balau.vcxproj
index f50aac4..2f0d740 100644
--- a/win32/project/Balau.vcxproj
+++ b/win32/project/Balau.vcxproj
@@ -224,6 +224,7 @@
<ClCompile Include="..\..\src\BString.cc" />
<ClCompile Include="..\..\src\Buffer.cc" />
<ClCompile Include="..\..\src\BWebSocket.cc" />
+ <ClCompile Include="..\..\src\CurlTask.cc" />
<ClCompile Include="..\..\src\Exceptions.cc" />
<ClCompile Include="..\..\src\Handle.cc" />
<ClCompile Include="..\..\src\HelperTasks.cc" />
diff --git a/win32/project/Balau.vcxproj.filters b/win32/project/Balau.vcxproj.filters
index 2742441..c9b12a4 100644
--- a/win32/project/Balau.vcxproj.filters
+++ b/win32/project/Balau.vcxproj.filters
@@ -171,6 +171,9 @@
<ClCompile Include="..\..\src\MMap.cc">
<Filter>Source</Filter>
</ClCompile>
+ <ClCompile Include="..\..\src\CurlTask.cc">
+ <Filter>Source</Filter>
+ </ClCompile>
</ItemGroup>
<ItemGroup>
<ClInclude Include="..\..\includes\Async.h">