diff options
| author | Rye <rye@alchemyviewer.org> | 2025-11-27 11:41:03 -0500 |
|---|---|---|
| committer | Andrey Kleshchev <117672381+akleshchev@users.noreply.github.com> | 2025-11-27 22:14:23 +0200 |
| commit | 0ea816a6c26e17bf0a2ee8274363837d4bd0ef94 (patch) | |
| tree | 204f2ae97a2bee4252bdd2e9ed885b654d97c73d | |
| parent | 0fa5991d067304d103d8bd18702e3e8806de07e3 (diff) | |
Replace dependency on boost thread with std and change HttpService to use a similar thread shutdown mechanism to LLThread
| -rw-r--r-- | indra/cmake/Boost.cmake | 9 | ||||
| -rw-r--r-- | indra/llcorehttp/_httpservice.cpp | 47 | ||||
| -rw-r--r-- | indra/llcorehttp/_httpservice.h | 2 | ||||
| -rw-r--r-- | indra/llcorehttp/_mutex.h | 11 | ||||
| -rw-r--r-- | indra/llcorehttp/_refcounted.h | 8 | ||||
| -rw-r--r-- | indra/llcorehttp/_thread.h | 100 |
6 files changed, 75 insertions, 102 deletions
diff --git a/indra/cmake/Boost.cmake b/indra/cmake/Boost.cmake index 610a4f6232..5967a96f8a 100644 --- a/indra/cmake/Boost.cmake +++ b/indra/cmake/Boost.cmake @@ -65,14 +65,6 @@ find_library(BOOST_SYSTEM_LIBRARY boost_system-mt${addrsfx} PATHS "${ARCH_PREBUILT_DIRS_RELEASE}" REQUIRED NO_DEFAULT_PATH) -find_library(BOOST_THREAD_LIBRARY - NAMES - libboost_thread-mt - libboost_thread-mt${addrsfx} - boost_thread-mt - boost_thread-mt${addrsfx} - PATHS "${ARCH_PREBUILT_DIRS_RELEASE}" REQUIRED NO_DEFAULT_PATH) - find_library(BOOST_URL_LIBRARY NAMES libboost_url-mt @@ -88,7 +80,6 @@ target_link_libraries(ll::boost INTERFACE ${BOOST_PROGRAMOPTIONS_LIBRARY} ${BOOST_REGEX_LIBRARY} ${BOOST_SYSTEM_LIBRARY} - ${BOOST_THREAD_LIBRARY} ${BOOST_URL_LIBRARY}) if (LINUX) diff --git a/indra/llcorehttp/_httpservice.cpp b/indra/llcorehttp/_httpservice.cpp index 03a2eab8e3..323a18c02a 100644 --- a/indra/llcorehttp/_httpservice.cpp +++ b/indra/llcorehttp/_httpservice.cpp @@ -71,7 +71,6 @@ volatile HttpService::EState HttpService::sState(NOT_INITIALIZED); HttpService::HttpService() : mRequestQueue(NULL), mExitRequested(0U), - mThread(NULL), mPolicy(NULL), mTransport(NULL), mLastPolicy(0) @@ -90,23 +89,30 @@ HttpService::~HttpService() { if (mRequestQueue->stopQueue()) { - // Give mRequestQueue a chance to finish - ms_sleep(10); + // Now wait a bit for the thread to exit + S32 counter = 0; + const S32 MAX_WAIT = 600; + while (counter < MAX_WAIT) + { + if (STOPPED == sState) + { + break; + } + // Sleep for a tenth of a second + ms_sleep(100); + std::this_thread::yield(); + counter++; + } } } - if (mThread) + if (mThread && RUNNING == sState) { - if (! mThread->timedJoin(250)) - { - // Failed to join, expect problems ahead so do a hard termination. - LL_WARNS(LOG_CORE) << "Destroying HttpService with running thread. Expect problems." << LL_NEWLINE - << "State: " << S32(sState) - << " Last policy: " << U32(mLastPolicy) - << LL_ENDL; + // Failed to shutdown, expect problems ahead so do a hard termination. + LL_WARNS(LOG_CORE) << "Destroying HttpService with running thread. Expect problems." << LL_NEWLINE << "State: " << S32(sState) + << " Last policy: " << U32(mLastPolicy) << LL_ENDL; - mThread->cancel(); - } + mThread->cancel(); } } @@ -122,11 +128,7 @@ HttpService::~HttpService() delete mPolicy; mPolicy = NULL; - if (mThread) - { - mThread->release(); - mThread = NULL; - } + mThread.reset(); } @@ -205,14 +207,15 @@ void HttpService::startThread() if (mThread) { - mThread->release(); + mThread.reset(); } // Push current policy definitions, enable policy & transport components mPolicy->start(); mTransport->start(mLastPolicy + 1); - mThread = new LLCoreInt::HttpThread(boost::bind(&HttpService::threadRun, this, _1)); + mThread = std::make_unique<LLCoreInt::HttpThread>(boost::bind(&HttpService::threadRun, this, _1)); + mThread->detach(); // Detach thread to let it clean its self up sState = RUNNING; } @@ -286,8 +289,6 @@ void HttpService::threadRun(LLCoreInt::HttpThread * thread) set_thread_name("HttpService"); LL_PROFILER_SET_THREAD_NAME("HttpService"); - boost::this_thread::disable_interruption di; - ELoopSpeed loop(REQUEST_SLEEP); while (! mExitRequested) { @@ -314,7 +315,7 @@ void HttpService::threadRun(LLCoreInt::HttpThread * thread) { LOG_UNHANDLED_EXCEPTION(""); } - catch (std::bad_alloc&) + catch (const std::bad_alloc&) { LLMemory::logMemoryInfo(true); diff --git a/indra/llcorehttp/_httpservice.h b/indra/llcorehttp/_httpservice.h index 13eb034f0e..bdf03f5227 100644 --- a/indra/llcorehttp/_httpservice.h +++ b/indra/llcorehttp/_httpservice.h @@ -218,7 +218,7 @@ protected: static volatile EState sState; HttpRequestQueue * mRequestQueue; // Refcounted LLAtomicU32 mExitRequested; - LLCoreInt::HttpThread * mThread; + std::unique_ptr<LLCoreInt::HttpThread> mThread; // === working-thread-only data === HttpPolicy * mPolicy; // Simple pointer, has ownership diff --git a/indra/llcorehttp/_mutex.h b/indra/llcorehttp/_mutex.h index 5e0164eb51..43782d3a37 100644 --- a/indra/llcorehttp/_mutex.h +++ b/indra/llcorehttp/_mutex.h @@ -27,9 +27,8 @@ #ifndef LLCOREINT_MUTEX_H_ #define LLCOREINT_MUTEX_H_ - -#include <boost/thread.hpp> - +#include <condition_variable> +#include <mutex> namespace LLCoreInt { @@ -37,17 +36,17 @@ namespace LLCoreInt // MUTEX TYPES // unique mutex type -typedef boost::mutex HttpMutex; +typedef std::mutex HttpMutex; // CONDITION VARIABLES // standard condition variable -typedef boost::condition_variable HttpConditionVariable; +typedef std::condition_variable HttpConditionVariable; // LOCKS AND FENCES // scoped unique lock -typedef boost::unique_lock<HttpMutex> HttpScopedLock; +typedef std::unique_lock<HttpMutex> HttpScopedLock; } diff --git a/indra/llcorehttp/_refcounted.h b/indra/llcorehttp/_refcounted.h index 7470965a7f..45fe3cb090 100644 --- a/indra/llcorehttp/_refcounted.h +++ b/indra/llcorehttp/_refcounted.h @@ -43,11 +43,11 @@ namespace LLCoreInt class RefCounted { -private: - RefCounted(); // Not defined - may not be default constructed - void operator=(const RefCounted &); // Not defined - public: + RefCounted() = delete; // Not defined - may not be default constructed + RefCounted(const RefCounted&) = delete; // Not defined - may not be copy constructed + void operator=(const RefCounted&) = delete; // Not defined + explicit RefCounted(bool const implicit) : mRefCount(implicit) {} diff --git a/indra/llcorehttp/_thread.h b/indra/llcorehttp/_thread.h index 6c0e39cf92..956a220524 100644 --- a/indra/llcorehttp/_thread.h +++ b/indra/llcorehttp/_thread.h @@ -29,92 +29,74 @@ #include "linden_common.h" -#include <boost/thread.hpp> -#include <boost/function.hpp> -#include <boost/date_time/posix_time/posix_time_types.hpp> +#include <functional> +#include <thread> -#include "apr.h" // thread-related functions #include "_refcounted.h" namespace LLCoreInt { -class HttpThread : public RefCounted +class HttpThread { -private: - HttpThread(); // Not defined - void operator=(const HttpThread &); // Not defined - - void at_exit() - { - // the thread function has exited so we need to release our reference - // to ourself so that we will be automagically cleaned up. - release(); - } +public: + HttpThread() = delete; // Not defined + void operator=(const HttpThread &) = delete; // Not defined +private: void run() - { // THREAD CONTEXT - - // Take out additional reference for the at_exit handler - addRef(); - boost::this_thread::at_thread_exit(boost::bind(&HttpThread::at_exit, this)); - - // run the thread function - mThreadFunc(this); - - } // THREAD CONTEXT - -protected: - virtual ~HttpThread() - { - delete mThread; - } + { // THREAD CONTEXT + // run the thread function + mThreadFunc(this); + } // THREAD CONTEXT public: /// Constructs a thread object for concurrent execution but does /// not start running. Caller receives on refcount on the thread /// instance. If the thread is started, another will be taken /// out for the exit handler. - explicit HttpThread(boost::function<void (HttpThread *)> threadFunc) - : RefCounted(true), // implicit reference - mThreadFunc(threadFunc) - { - // this creates a boost thread that will call HttpThread::run on this instance - // and pass it the threadfunc callable... - boost::function<void()> f = boost::bind(&HttpThread::run, this); + explicit HttpThread(std::function<void (HttpThread *)> threadFunc) + : mThreadFunc(threadFunc) + { + // this creates a std thread that will call HttpThread::run on this instance + // and pass it the threadfunc callable... + std::function<void()> f = std::bind(&HttpThread::run, this); - mThread = new boost::thread(f); - } + mThread = std::make_unique<std::thread>(f); + mNativeHandle = mThread->native_handle(); + } - inline void join() - { - mThread->join(); - } + ~HttpThread() = default; - inline bool timedJoin(S32 millis) - { - return mThread->timed_join(boost::posix_time::milliseconds(millis)); - } + inline void join() + { + mThread->join(); + } inline bool joinable() const - { - return mThread->joinable(); - } + { + return mThread->joinable(); + } + + inline void detach() + { + mThread->detach(); + } // A very hostile method to force a thread to quit inline void cancel() - { - boost::thread::native_handle_type thread(mThread->native_handle()); -#if LL_WINDOWS - TerminateThread(thread, 0); + { +#if LL_WINDOWS + TerminateThread(mNativeHandle, 0); #else - pthread_cancel(thread); + pthread_cancel(mNativeHandle); #endif - } + } private: - boost::function<void(HttpThread *)> mThreadFunc; - boost::thread * mThread; + std::function<void(HttpThread *)> mThreadFunc; + std::unique_ptr<std::thread> mThread; + std::thread::native_handle_type mNativeHandle; }; // end class HttpThread } // end namespace LLCoreInt |
