From 5611cb6d476540e6a1c654c1f9acdce2787b3505 Mon Sep 17 00:00:00 2001 From: Monty Brandenberg Date: Mon, 23 Apr 2012 16:19:39 -0400 Subject: Okay, imported the core-http library and got it compiling suspiciously easily. The unit/integration tests don't work yet as I'm still battling cmake/autobuild as usual but first milestone passed. --- indra/llcorehttp/_httpreplyqueue.cpp | 87 ++++++++++++++++++++++++++++++++++++ 1 file changed, 87 insertions(+) create mode 100644 indra/llcorehttp/_httpreplyqueue.cpp (limited to 'indra/llcorehttp/_httpreplyqueue.cpp') diff --git a/indra/llcorehttp/_httpreplyqueue.cpp b/indra/llcorehttp/_httpreplyqueue.cpp new file mode 100644 index 0000000000..a354ed7e10 --- /dev/null +++ b/indra/llcorehttp/_httpreplyqueue.cpp @@ -0,0 +1,87 @@ +/** + * @file _httpreplyqueue.cpp + * @brief Internal definitions for the operation reply queue + * + * $LicenseInfo:firstyear=2012&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2012, Linden Research, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License only. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA + * $/LicenseInfo$ + */ + +#include "_httpreplyqueue.h" + + +#include "_mutex.h" +#include "_thread.h" +#include "_httpoperation.h" + +using namespace LLCoreInt; + + +namespace LLCore +{ + + +HttpReplyQueue::HttpReplyQueue() + : RefCounted(true) +{ +} + + +HttpReplyQueue::~HttpReplyQueue() +{ + while (! mQueue.empty()) + { + HttpOperation * op = mQueue.back(); + mQueue.pop_back(); + op->release(); + } +} + + +void HttpReplyQueue::addOp(HttpOperation * op) +{ + { + HttpScopedLock lock(mQueueMutex); + + mQueue.push_back(op); + } + mQueueCV.notify_all(); +} + + +HttpOperation * HttpReplyQueue::fetchOp() +{ + HttpOperation * result(NULL); + + { + HttpScopedLock lock(mQueueMutex); + + if (mQueue.empty()) + return NULL; + + result = mQueue.front(); + mQueue.erase(mQueue.begin()); + } + + // Caller also acquires the reference count + return result; +} + +} // end namespace LLCore -- cgit v1.3 From bc72acbfd2410e01946375bcfa29cf37a7c01c17 Mon Sep 17 00:00:00 2001 From: Monty Brandenberg Date: Tue, 10 Jul 2012 18:50:21 -0400 Subject: SH-3244 Syscall avoidance in HttpRequest::update() method Well, achieved that by doing work in bulk when needed. But turned into some additional things. Change timebase from mS to uS as, well, things are headed that way. Implement an HttpReplyQueue::fetchAll method (advertised one, hadn't implemented it). --- indra/llcorehttp/_httpreplyqueue.cpp | 20 +++++++++++ indra/llcorehttp/_httprequestqueue.cpp | 7 ++-- indra/llcorehttp/examples/http_texture_load.cpp | 2 +- indra/llcorehttp/httprequest.cpp | 40 +++++++++++++++++---- indra/llcorehttp/httprequest.h | 7 ++-- indra/llcorehttp/tests/test_httprequest.hpp | 48 ++++++++++++------------- indra/newview/llappviewer.cpp | 2 +- indra/newview/lltexturefetch.cpp | 19 ++++------ 8 files changed, 92 insertions(+), 53 deletions(-) (limited to 'indra/llcorehttp/_httpreplyqueue.cpp') diff --git a/indra/llcorehttp/_httpreplyqueue.cpp b/indra/llcorehttp/_httpreplyqueue.cpp index a354ed7e10..558b7bdee9 100644 --- a/indra/llcorehttp/_httpreplyqueue.cpp +++ b/indra/llcorehttp/_httpreplyqueue.cpp @@ -84,4 +84,24 @@ HttpOperation * HttpReplyQueue::fetchOp() return result; } + +void HttpReplyQueue::fetchAll(OpContainer & ops) +{ + // Not valid putting something back on the queue... + llassert_always(ops.empty()); + + { + HttpScopedLock lock(mQueueMutex); + + if (! mQueue.empty()) + { + mQueue.swap(ops); + } + } + + // Caller also acquires the reference counts on each op. + return; +} + + } // end namespace LLCore diff --git a/indra/llcorehttp/_httprequestqueue.cpp b/indra/llcorehttp/_httprequestqueue.cpp index 9acac665a9..c16966d078 100644 --- a/indra/llcorehttp/_httprequestqueue.cpp +++ b/indra/llcorehttp/_httprequestqueue.cpp @@ -120,10 +120,9 @@ HttpOperation * HttpRequestQueue::fetchOp(bool wait) void HttpRequestQueue::fetchAll(bool wait, OpContainer & ops) { - // Note: Should probably test whether we're empty or not here. - // A target passed in with entries is likely also carrying - // reference counts and we're going to leak something. - ops.clear(); + // Not valid putting something back on the queue... + llassert_always(ops.empty()); + { HttpScopedLock lock(mQueueMutex); diff --git a/indra/llcorehttp/examples/http_texture_load.cpp b/indra/llcorehttp/examples/http_texture_load.cpp index e5951e8415..bcb322bd5c 100644 --- a/indra/llcorehttp/examples/http_texture_load.cpp +++ b/indra/llcorehttp/examples/http_texture_load.cpp @@ -244,7 +244,7 @@ int main(int argc, char** argv) int passes(0); while (! ws.reload(hr)) { - hr->update(5000); + hr->update(5000000); ms_sleep(2); if (0 == (++passes % 200)) { diff --git a/indra/llcorehttp/httprequest.cpp b/indra/llcorehttp/httprequest.cpp index 3a55a849b9..9b739a8825 100644 --- a/indra/llcorehttp/httprequest.cpp +++ b/indra/llcorehttp/httprequest.cpp @@ -296,17 +296,43 @@ HttpHandle HttpRequest::requestNoOp(HttpHandler * user_handler) } -HttpStatus HttpRequest::update(long millis) +HttpStatus HttpRequest::update(long usecs) { - const HttpTime limit(totalTime() + (1000 * HttpTime(millis))); HttpOperation * op(NULL); - while (limit >= totalTime() && (op = mReplyQueue->fetchOp())) + + if (usecs) { - // Process operation - op->visitNotifier(this); + const HttpTime limit(totalTime() + HttpTime(usecs)); + while (limit >= totalTime() && (op = mReplyQueue->fetchOp())) + { + // Process operation + op->visitNotifier(this); - // We're done with the operation - op->release(); + // We're done with the operation + op->release(); + } + } + else + { + // Same as above, just no time limit + HttpReplyQueue::OpContainer replies; + mReplyQueue->fetchAll(replies); + if (! replies.empty()) + { + for (HttpReplyQueue::OpContainer::iterator iter(replies.begin()); + replies.end() != iter; + ++iter) + { + // Swap op pointer for NULL; + op = *iter; *iter = NULL; + + // Process operation + op->visitNotifier(this); + + // We're done with the operation + op->release(); + } + } } return HttpStatus(); diff --git a/indra/llcorehttp/httprequest.h b/indra/llcorehttp/httprequest.h index 134a61b618..9dd53f4483 100644 --- a/indra/llcorehttp/httprequest.h +++ b/indra/llcorehttp/httprequest.h @@ -341,13 +341,14 @@ public: /// are expected to return 'quickly' and do any significant processing /// outside of the notification callback to onCompleted(). /// - /// @param millis Maximum number of wallclock milliseconds to + /// @param usecs Maximum number of wallclock microseconds to /// spend in the call. As hinted at above, this /// is partly a function of application code so it's - /// a soft limit. + /// a soft limit. A '0' value will run without + /// time limit. /// /// @return Standard status code. - HttpStatus update(long millis); + HttpStatus update(long usecs); /// @} diff --git a/indra/llcorehttp/tests/test_httprequest.hpp b/indra/llcorehttp/tests/test_httprequest.hpp index 914f35ec3d..ba7c757af4 100644 --- a/indra/llcorehttp/tests/test_httprequest.hpp +++ b/indra/llcorehttp/tests/test_httprequest.hpp @@ -260,7 +260,7 @@ void HttpRequestTestObjectType::test<3>() int limit(20); while (count++ < limit && mHandlerCalls < 1) { - req->update(1000); + req->update(1000000); usleep(100000); } ensure("Request executed in reasonable time", count < limit); @@ -275,7 +275,7 @@ void HttpRequestTestObjectType::test<3>() limit = 100; while (count++ < limit && mHandlerCalls < 2) { - req->update(1000); + req->update(1000000); usleep(100000); } ensure("Second request executed in reasonable time", count < limit); @@ -358,8 +358,8 @@ void HttpRequestTestObjectType::test<4>() int limit(20); while (count++ < limit && mHandlerCalls < 2) { - req1->update(1000); - req2->update(1000); + req1->update(1000000); + req2->update(1000000); usleep(100000); } ensure("Request executed in reasonable time", count < limit); @@ -375,8 +375,8 @@ void HttpRequestTestObjectType::test<4>() limit = 100; while (count++ < limit && mHandlerCalls < 3) { - req1->update(1000); - req2->update(1000); + req1->update(1000000); + req2->update(1000000); usleep(100000); } ensure("Second request executed in reasonable time", count < limit); @@ -459,7 +459,7 @@ void HttpRequestTestObjectType::test<5>() int limit(10); while (count++ < limit && mHandlerCalls < 1) { - req->update(1000); + req->update(1000000); usleep(100000); } ensure("NoOp notification received", mHandlerCalls == 1); @@ -535,7 +535,7 @@ void HttpRequestTestObjectType::test<6>() int limit(10); while (count++ < limit && mHandlerCalls < 1) { - req->update(1000); + req->update(1000000); usleep(100000); } ensure("No notifications received", mHandlerCalls == 0); @@ -616,7 +616,7 @@ void HttpRequestTestObjectType::test<7>() int limit(50); // With one retry, should fail quickish while (count++ < limit && mHandlerCalls < 1) { - req->update(1000); + req->update(1000000); usleep(100000); } ensure("Request executed in reasonable time", count < limit); @@ -632,7 +632,7 @@ void HttpRequestTestObjectType::test<7>() limit = 100; while (count++ < limit && mHandlerCalls < 2) { - req->update(1000); + req->update(1000000); usleep(100000); } ensure("Second request executed in reasonable time", count < limit); @@ -733,7 +733,7 @@ void HttpRequestTestObjectType::test<8>() int limit(10); while (count++ < limit && mHandlerCalls < 1) { - req->update(1000); + req->update(1000000); usleep(100000); } ensure("Request executed in reasonable time", count < limit); @@ -749,7 +749,7 @@ void HttpRequestTestObjectType::test<8>() limit = 10; while (count++ < limit && mHandlerCalls < 2) { - req->update(1000); + req->update(1000000); usleep(100000); } ensure("Second request executed in reasonable time", count < limit); @@ -843,7 +843,7 @@ void HttpRequestTestObjectType::test<9>() int limit(10); while (count++ < limit && mHandlerCalls < 1) { - req->update(1000); + req->update(1000000); usleep(100000); } ensure("Request executed in reasonable time", count < limit); @@ -859,7 +859,7 @@ void HttpRequestTestObjectType::test<9>() limit = 10; while (count++ < limit && mHandlerCalls < 2) { - req->update(1000); + req->update(1000000); usleep(100000); } ensure("Second request executed in reasonable time", count < limit); @@ -955,7 +955,7 @@ void HttpRequestTestObjectType::test<10>() int limit(10); while (count++ < limit && mHandlerCalls < 1) { - req->update(1000); + req->update(1000000); usleep(100000); } ensure("Request executed in reasonable time", count < limit); @@ -971,7 +971,7 @@ void HttpRequestTestObjectType::test<10>() limit = 10; while (count++ < limit && mHandlerCalls < 2) { - req->update(1000); + req->update(1000000); usleep(100000); } ensure("Second request executed in reasonable time", count < limit); @@ -1074,7 +1074,7 @@ void HttpRequestTestObjectType::test<11>() int limit(10); while (count++ < limit && mHandlerCalls < 1) { - req->update(1000); + req->update(1000000); usleep(100000); } ensure("Request executed in reasonable time", count < limit); @@ -1090,7 +1090,7 @@ void HttpRequestTestObjectType::test<11>() limit = 10; while (count++ < limit && mHandlerCalls < 2) { - req->update(1000); + req->update(1000000); usleep(100000); } ensure("Second request executed in reasonable time", count < limit); @@ -1194,7 +1194,7 @@ void HttpRequestTestObjectType::test<12>() int limit(10); while (count++ < limit && mHandlerCalls < 1) { - req->update(1000); + req->update(1000000); usleep(100000); } ensure("Request executed in reasonable time", count < limit); @@ -1210,7 +1210,7 @@ void HttpRequestTestObjectType::test<12>() limit = 10; while (count++ < limit && mHandlerCalls < 2) { - req->update(1000); + req->update(1000000); usleep(100000); } ensure("Second request executed in reasonable time", count < limit); @@ -1316,7 +1316,7 @@ void HttpRequestTestObjectType::test<13>() int limit(10); while (count++ < limit && mHandlerCalls < 1) { - req->update(1000); + req->update(1000000); usleep(100000); } ensure("Request executed in reasonable time", count < limit); @@ -1333,7 +1333,7 @@ void HttpRequestTestObjectType::test<13>() limit = 10; while (count++ < limit && mHandlerCalls < 2) { - req->update(1000); + req->update(1000000); usleep(100000); } ensure("Second request executed in reasonable time", count < limit); @@ -1435,7 +1435,7 @@ void HttpRequestTestObjectType::test<14>() int limit(50); // With one retry, should fail quickish while (count++ < limit && mHandlerCalls < 1) { - req->update(1000); + req->update(1000000); usleep(100000); } ensure("Request executed in reasonable time", count < limit); @@ -1451,7 +1451,7 @@ void HttpRequestTestObjectType::test<14>() limit = 100; while (count++ < limit && mHandlerCalls < 2) { - req->update(1000); + req->update(1000000); usleep(100000); } ensure("Second request executed in reasonable time", count < limit); diff --git a/indra/newview/llappviewer.cpp b/indra/newview/llappviewer.cpp index 8243d4f2f3..0549a972e1 100644 --- a/indra/newview/llappviewer.cpp +++ b/indra/newview/llappviewer.cpp @@ -5398,7 +5398,7 @@ void CoreHttp::cleanup() { while (! mStopped && LLTimer::getTotalSeconds() < (mStopRequested + MAX_THREAD_WAIT_TIME)) { - mRequest->update(200); + mRequest->update(200000); ms_sleep(50); } if (! mStopped) diff --git a/indra/newview/lltexturefetch.cpp b/indra/newview/lltexturefetch.cpp index 5c39504243..8314031f14 100755 --- a/indra/newview/lltexturefetch.cpp +++ b/indra/newview/lltexturefetch.cpp @@ -2740,22 +2740,14 @@ void LLTextureFetch::commonUpdate() // Run a cross-thread command, if any. cmdDoWork(); - // Update Curl on same thread as mCurlGetRequest was constructed - LLCore::HttpStatus status = mHttpRequest->update(200); + // Deliver all completion notifications + LLCore::HttpStatus status = mHttpRequest->update(0); if (! status) { LL_INFOS_ONCE("Texture") << "Problem during HTTP servicing. Reason: " << status.toString() << LL_ENDL; } - -#if 0 - // *FIXME: maybe implement this another way... - if (processed > 0) - { - lldebugs << "processed: " << processed << " messages." << llendl; - } -#endif } @@ -2840,7 +2832,8 @@ void LLTextureFetch::endThread() void LLTextureFetch::threadedUpdate() { llassert_always(mHttpRequest); - + +#if 0 // Limit update frequency const F32 PROCESS_TIME = 0.05f; static LLFrameTimer process_timer; @@ -2849,9 +2842,10 @@ void LLTextureFetch::threadedUpdate() return; } process_timer.reset(); +#endif commonUpdate(); - + #if 0 const F32 INFO_TIME = 1.0f; static LLFrameTimer info_timer; @@ -2865,7 +2859,6 @@ void LLTextureFetch::threadedUpdate() } } #endif - } ////////////////////////////////////////////////////////////////////////////// -- cgit v1.3