diff options
-rw-r--r-- | includes/CurlTask.h | 13 | ||||
-rw-r--r-- | src/CurlTask.cc | 27 | ||||
-rw-r--r-- | src/TaskMan.cc | 13 | ||||
-rw-r--r-- | win32/project/Balau.vcxproj | 1 | ||||
-rw-r--r-- | win32/project/Balau.vcxproj.filters | 3 |
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">
|