summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRye <rye@alchemyviewer.org>2025-11-27 11:41:03 -0500
committerAndrey Kleshchev <117672381+akleshchev@users.noreply.github.com>2025-11-27 22:14:23 +0200
commit0ea816a6c26e17bf0a2ee8274363837d4bd0ef94 (patch)
tree204f2ae97a2bee4252bdd2e9ed885b654d97c73d
parent0fa5991d067304d103d8bd18702e3e8806de07e3 (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.cmake9
-rw-r--r--indra/llcorehttp/_httpservice.cpp47
-rw-r--r--indra/llcorehttp/_httpservice.h2
-rw-r--r--indra/llcorehttp/_mutex.h11
-rw-r--r--indra/llcorehttp/_refcounted.h8
-rw-r--r--indra/llcorehttp/_thread.h100
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