From 9aa26648c9d49d9de348d226fdc1c134adef534f Mon Sep 17 00:00:00 2001 From: Shyotl Date: Sat, 6 Aug 2011 02:29:04 -0500 Subject: [PATCH] Added CurlUseMultipleThreads (requires restart to change) --- indra/llmessage/llcurl.cpp | 161 ++++++++++++++++-------- indra/llmessage/llcurl.h | 8 +- indra/newview/app_settings/settings.xml | 13 +- indra/newview/llappviewer.cpp | 2 +- 4 files changed, 126 insertions(+), 58 deletions(-) diff --git a/indra/llmessage/llcurl.cpp b/indra/llmessage/llcurl.cpp index 524c0ef17..8192b97a9 100644 --- a/indra/llmessage/llcurl.cpp +++ b/indra/llmessage/llcurl.cpp @@ -92,6 +92,9 @@ std::vector LLCurl::sSSLMutex; std::string LLCurl::sCAPath; std::string LLCurl::sCAFile; +bool LLCurl::sMultiThreaded = false; +static U32 sMainThreadID = 0; + void check_curl_code(CURLcode code) { if (code != CURLE_OK) @@ -250,7 +253,7 @@ public: U32 report(CURLcode); void getTransferInfo(LLCurl::TransferInfo* info); - void prepRequest(const std::string& url, const std::vector& headers, ResponderPtr, bool post = false); + void prepRequest(const std::string& url, const std::vector& headers, ResponderPtr, S32 time_out = 0, bool post = false); const char* getErrorBuffer(); @@ -549,7 +552,7 @@ size_t curlHeaderCallback(void* data, size_t size, size_t nmemb, void* user_data void LLCurl::Easy::prepRequest(const std::string& url, const std::vector& headers, - ResponderPtr responder, bool post) + ResponderPtr responder, S32 time_out, bool post) { resetState(); @@ -599,7 +602,7 @@ void LLCurl::Easy::prepRequest(const std::string& url, //don't verify host name so urls with scrubbed host names will work (improves DNS performance) setopt(CURLOPT_SSL_VERIFYHOST, 0); - setopt(CURLOPT_TIMEOUT, CURL_REQUEST_TIMEOUT); + setopt(CURLOPT_TIMEOUT, llmax(time_out, CURL_REQUEST_TIMEOUT)); setoptString(CURLOPT_URL, url); @@ -642,6 +645,7 @@ public: S32 process(); void perform(); + void doPerform(); virtual void run(); @@ -654,6 +658,7 @@ public: LLCondition* mSignal; bool mQuitting; + bool mThreaded; private: void easyFree(Easy*); @@ -675,7 +680,16 @@ LLCurl::Multi::Multi() mPerformState(PERFORM_STATE_READY) { mQuitting = false; - mSignal = new LLCondition; + + mThreaded = LLCurl::sMultiThreaded && LLThread::currentID() == sMainThreadID; + if (mThreaded) + { + mSignal = new LLCondition; + } + else + { + mSignal = NULL; + } mCurlMultiHandle = curl_multi_init(); if (!mCurlMultiHandle) @@ -722,16 +736,25 @@ CURLMsg* LLCurl::Multi::info_read(S32* msgs_in_queue) void LLCurl::Multi::perform() { - mSignal->lock(); - if (mPerformState == PERFORM_STATE_READY) + if (mThreaded) { - mSignal->signal(); + mSignal->lock(); + if (mPerformState == PERFORM_STATE_READY) + { + mSignal->signal(); + } + mSignal->unlock(); } - mSignal->unlock(); + else + { + doPerform(); + } } void LLCurl::Multi::run() { + llassert(mThreaded); + mSignal->lock(); while (!mQuitting) { @@ -739,26 +762,31 @@ void LLCurl::Multi::run() mPerformState = PERFORM_STATE_PERFORMING; if (!mQuitting) { - S32 q = 0; - for (S32 call_count = 0; - call_count < MULTI_PERFORM_CALL_REPEAT; - call_count += 1) - { - CURLMcode code = curl_multi_perform(mCurlMultiHandle, &q); - if (CURLM_CALL_MULTI_PERFORM != code || q == 0) - { - check_curl_multi_code(code); - break; - } - - } - mQueued = q; - mPerformState = PERFORM_STATE_COMPLETED; + doPerform(); } } mSignal->unlock(); } +void LLCurl::Multi::doPerform() +{ + S32 q = 0; + for (S32 call_count = 0; + call_count < MULTI_PERFORM_CALL_REPEAT; + call_count += 1) + { + CURLMcode code = curl_multi_perform(mCurlMultiHandle, &q); + if (CURLM_CALL_MULTI_PERFORM != code || q == 0) + { + check_curl_multi_code(code); + break; + } + + } + mQueued = q; + mPerformState = PERFORM_STATE_COMPLETED; +} + S32 LLCurl::Multi::process() { perform(); @@ -883,16 +911,21 @@ LLCurlRequest::~LLCurlRequest() for (curlmulti_set_t::iterator iter = mMultiSet.begin(); iter != mMultiSet.end(); ++iter) { LLCurl::Multi* multi = *iter; - multi->mSignal->lock(); - multi->mQuitting = true; - while (!multi->isStopped()) - { - multi->mSignal->signal(); - multi->mSignal->unlock(); - apr_sleep(1000); + if (multi->mThreaded) multi->mSignal->lock(); + multi->mQuitting = true; + if (multi->mThreaded) + { + while (!multi->isStopped()) + { + multi->mSignal->signal(); + multi->mSignal->unlock(); + apr_sleep(1000); + multi->mSignal->lock(); + } } - multi->mSignal->unlock(); + if (multi->mThreaded) + multi->mSignal->unlock(); } for_each(mMultiSet.begin(), mMultiSet.end(), DeletePointer()); } @@ -901,7 +934,10 @@ void LLCurlRequest::addMulti() { llassert_always(mThreadID == LLThread::currentID()); LLCurl::Multi* multi = new LLCurl::Multi(); - multi->start(); + if (multi->mThreaded) + { + multi->start(); + } mMultiSet.insert(multi); mActiveMulti = multi; mActiveRequestCount = 0; @@ -963,14 +999,14 @@ bool LLCurlRequest::getByteRange(const std::string& url, bool LLCurlRequest::post(const std::string& url, const headers_t& headers, const LLSD& data, - LLCurl::ResponderPtr responder) + LLCurl::ResponderPtr responder, S32 time_out) { LLCurl::Easy* easy = allocEasy(); if (!easy) { return false; } - easy->prepRequest(url, headers, responder); + easy->prepRequest(url, headers, responder, time_out); LLSDSerialize::toXML(data, easy->getInput()); S32 bytes = easy->getInput().str().length(); @@ -990,14 +1026,14 @@ bool LLCurlRequest::post(const std::string& url, bool LLCurlRequest::post(const std::string& url, const headers_t& headers, const std::string& data, - LLCurl::ResponderPtr responder) + LLCurl::ResponderPtr responder, S32 time_out) { LLCurl::Easy* easy = allocEasy(); if (!easy) { return false; } - easy->prepRequest(url, headers, responder); + easy->prepRequest(url, headers, responder, time_out); easy->getInput().write(data.data(), data.size()); S32 bytes = easy->getInput().str().length(); @@ -1031,16 +1067,21 @@ S32 LLCurlRequest::process() if (multi != mActiveMulti && tres == 0 && multi->mQueued == 0) { mMultiSet.erase(curiter); - multi->mSignal->lock(); + if (multi->mThreaded) + multi->mSignal->lock(); multi->mQuitting = true; - while (!multi->isStopped()) + if (multi->mThreaded) { - multi->mSignal->signal(); - multi->mSignal->unlock(); - apr_sleep(1000); - multi->mSignal->unlock(); + while (!multi->isStopped()) + { + multi->mSignal->signal(); + multi->mSignal->unlock(); + apr_sleep(1000); + multi->mSignal->unlock(); + } } - multi->mSignal->unlock(); + if (multi->mThreaded) + multi->mSignal->unlock(); delete multi; } @@ -1059,6 +1100,10 @@ S32 LLCurlRequest::getQueued() curlmulti_set_t::iterator curiter = iter++; LLCurl::Multi* multi = *curiter; queued += multi->mQueued; + if (multi->mPerformState != LLCurl::Multi::PERFORM_STATE_READY) + { + ++queued; + } } return queued; } @@ -1072,7 +1117,10 @@ LLCurlEasyRequest::LLCurlEasyRequest() mResultReturned(false) { mMulti = new LLCurl::Multi(); - mMulti->start(); + if (mMulti->mThreaded) + { + mMulti->start(); + } mEasy = mMulti->allocEasy(); if (mEasy) { @@ -1083,16 +1131,21 @@ LLCurlEasyRequest::LLCurlEasyRequest() LLCurlEasyRequest::~LLCurlEasyRequest() { - mMulti->mSignal->lock(); - mMulti->mQuitting = true; - while (!mMulti->isStopped()) - { - mMulti->mSignal->signal(); - mMulti->mSignal->unlock(); - apr_sleep(1000); + if (mMulti->mThreaded) mMulti->mSignal->lock(); + mMulti->mQuitting = true; + if (mMulti->mThreaded) + { + while (!mMulti->isStopped()) + { + mMulti->mSignal->signal(); + mMulti->mSignal->unlock(); + apr_sleep(1000); + mMulti->mSignal->lock(); + } } - mMulti->mSignal->unlock(); + if (mMulti->mThreaded) + mMulti->mSignal->unlock(); delete mMulti; } @@ -1287,8 +1340,10 @@ unsigned long LLCurl::ssl_thread_id(void) } #endif -void LLCurl::initClass() +void LLCurl::initClass(bool multi_threaded) { + sMainThreadID = LLThread::currentID(); + sMultiThreaded = multi_threaded; // Do not change this "unless you are familiar with and mean to control // internal operations of libcurl" // - http://curl.haxx.se/libcurl/c/curl_global_init.html diff --git a/indra/llmessage/llcurl.h b/indra/llmessage/llcurl.h index 02abd7400..988205921 100644 --- a/indra/llmessage/llcurl.h +++ b/indra/llmessage/llcurl.h @@ -61,6 +61,8 @@ public: class Easy; class Multi; + static bool sMultiThreaded; + struct TransferInfo { TransferInfo() : mSizeDownload(0.0), mTotalTime(0.0), mSpeedDownload(0.0) {} @@ -164,7 +166,7 @@ public: /** * @ brief Initialize LLCurl class */ - static void initClass(); + static void initClass(bool multi_threaded = false); /** * @ brief Cleanup LLCurl class @@ -206,8 +208,8 @@ public: void get(const std::string& url, LLCurl::ResponderPtr responder); bool getByteRange(const std::string& url, const headers_t& headers, S32 offset, S32 length, LLCurl::ResponderPtr responder); - bool post(const std::string& url, const headers_t& headers, const LLSD& data, LLCurl::ResponderPtr responder); - bool post(const std::string& url, const headers_t& headers, const std::string& data, LLCurl::ResponderPtr responder); + bool post(const std::string& url, const headers_t& headers, const LLSD& data, LLCurl::ResponderPtr responder, S32 time_out = 0); + bool post(const std::string& url, const headers_t& headers, const std::string& data, LLCurl::ResponderPtr responder, S32 time_out = 0); S32 process(); S32 getQueued(); diff --git a/indra/newview/app_settings/settings.xml b/indra/newview/app_settings/settings.xml index ca13e4f39..2fa47eaea 100644 --- a/indra/newview/app_settings/settings.xml +++ b/indra/newview/app_settings/settings.xml @@ -3772,10 +3772,21 @@ Value 0 + CurlUseMultipleThreads + + Comment + Use background threads for executing curl_multi_perform (requires restart) + Persist + 1 + Type + Boolean + Value + 1 + Cursor3D Comment - Tread Joystick values as absolute positions (not deltas). + Treat Joystick values as absolute positions (not deltas). Persist 1 Type diff --git a/indra/newview/llappviewer.cpp b/indra/newview/llappviewer.cpp index e8fed149a..f621e0779 100644 --- a/indra/newview/llappviewer.cpp +++ b/indra/newview/llappviewer.cpp @@ -592,7 +592,7 @@ bool LLAppViewer::init() // *NOTE:Mani - LLCurl::initClass is not thread safe. // Called before threads are created. - LLCurl::initClass(); + LLCurl::initClass(gSavedSettings.getBOOL("CurlUseMultipleThreads")); LL_INFOS("InitInfo") << "LLCurl initialized." << LL_ENDL ; initThreads();