From 98dfba0d2f24aeb92e023df9d48b23fef8253024 Mon Sep 17 00:00:00 2001 From: Nat Goodspeed Date: Thu, 14 May 2020 14:51:52 -0400 Subject: DRTVWR-476: Wrap boost::fibers::mutex et al. with LLCoros aliases. Specifically: LLCoros::Mutex means boost::fibers::mutex LLCoros::LockType means std::unique_lock LLCoros::ConditionVariable means boost::fibers::condition_variable LLCoros::cv_status means boost::fibers::cv_status So as not to drag in all of boost::fibers::mutex.hpp or condition_variable.hpp for each consumer of llcoros.h, instead #define LLCOROS_MUTEX_HEADER and LLCOROS_CONDVAR_HEADER. Those who need them can #include the relevant macro. Update llcond.h and llthreadsafequeue.h accordingly. --- indra/llcommon/llcond.h | 27 ++++++++++++++------------- indra/llcommon/llcoros.h | 19 +++++++++++++++++++ indra/llcommon/llthreadsafequeue.h | 11 ++++++----- 3 files changed, 39 insertions(+), 18 deletions(-) (limited to 'indra/llcommon') diff --git a/indra/llcommon/llcond.h b/indra/llcommon/llcond.h index b4289528de..e31b67d893 100644 --- a/indra/llcommon/llcond.h +++ b/indra/llcommon/llcond.h @@ -15,8 +15,9 @@ #define LL_LLCOND_H #include "llunits.h" -#include -#include +#include "llcoros.h" +#include LLCOROS_MUTEX_HEADER +#include "mutex.h" #include /** @@ -32,7 +33,7 @@ * For a scalar DATA type, consider LLScalarCond instead. For specifically * bool, consider LLBoolCond. * - * Use of boost::fibers::condition_variable makes LLCond work between + * Use of LLCoros::ConditionVariable makes LLCond work between * coroutines as well as between threads. */ template @@ -45,13 +46,13 @@ private: // This is the DATA controlled by the condition_variable. value_type mData; // condition_variable must be used in conjunction with a mutex. Use - // boost::fibers::mutex instead of std::mutex because the latter blocks + // LLCoros::Mutex instead of std::mutex because the latter blocks // the entire calling thread, whereas the former blocks only the current - // coroutine within the calling thread. Yet boost::fiber::mutex is safe to + // coroutine within the calling thread. Yet LLCoros::Mutex is safe to // use across threads as well: it subsumes std::mutex functionality. - boost::fibers::mutex mMutex; - // Use boost::fibers::condition_variable for the same reason. - boost::fibers::condition_variable mCond; + LLCoros::Mutex mMutex; + // Use LLCoros::ConditionVariable for the same reason. + LLCoros::ConditionVariable mCond; public: /// LLCond can be explicitly initialized with a specific value for mData if @@ -82,7 +83,7 @@ public: void update_one(MODIFY modify) { { // scope of lock can/should end before notify_one() - std::unique_lock lk(mMutex); + LLCoros::LockType lk(mMutex); modify(mData); } mCond.notify_one(); @@ -101,7 +102,7 @@ public: void update_all(MODIFY modify) { { // scope of lock can/should end before notify_all() - std::unique_lock lk(mMutex); + LLCoros::LockType lk(mMutex); modify(mData); } mCond.notify_all(); @@ -117,7 +118,7 @@ public: template void wait(Pred pred) { - std::unique_lock lk(mMutex); + LLCoros::LockType lk(mMutex); // We must iterate explicitly since the predicate accepted by // condition_variable::wait() requires a different signature: // condition_variable::wait() calls its predicate with no arguments. @@ -204,14 +205,14 @@ private: template bool wait_until(const std::chrono::time_point& timeout_time, Pred pred) { - std::unique_lock lk(mMutex); + LLCoros::LockType lk(mMutex); // We advise the caller to pass a predicate accepting (const DATA&). // But what if they instead pass a predicate accepting non-const // (DATA&)? Such a predicate could modify mData, which would be Bad. // Forbid that. while (! pred(const_cast(mData))) { - if (boost::fibers::cv_status::timeout == mCond.wait_until(lk, timeout_time)) + if (LLCoros::cv_status::timeout == mCond.wait_until(lk, timeout_time)) { // It's possible that wait_until() timed out AND the predicate // became true more or less simultaneously. Even though diff --git a/indra/llcommon/llcoros.h b/indra/llcommon/llcoros.h index 95859198d4..d49a6e939c 100644 --- a/indra/llcommon/llcoros.h +++ b/indra/llcommon/llcoros.h @@ -33,11 +33,24 @@ #include #include #include +#include "mutex.h" #include "llsingleton.h" #include "llinstancetracker.h" #include #include +// e.g. #include LLCOROS_MUTEX_HEADER +#define LLCOROS_MUTEX_HEADER +#define LLCOROS_CONDVAR_HEADER + +namespace boost { + namespace fibers { + class mutex; + enum class cv_status; + class condition_variable; + } +} + /** * Registry of named Boost.Coroutine instances * @@ -260,6 +273,12 @@ public: template static Future getFuture(Promise& promise) { return promise.get_future(); } + // use mutex, lock, condition_variable suitable for coroutines + using Mutex = boost::fibers::mutex; + using LockType = std::unique_lock; + using cv_status = boost::fibers::cv_status; + using ConditionVariable = boost::fibers::condition_variable; + /// for data local to each running coroutine template using local_ptr = boost::fibers::fiber_specific_ptr; diff --git a/indra/llcommon/llthreadsafequeue.h b/indra/llcommon/llthreadsafequeue.h index bac536f7ee..8f5e0f3bf3 100644 --- a/indra/llcommon/llthreadsafequeue.h +++ b/indra/llcommon/llthreadsafequeue.h @@ -31,7 +31,8 @@ #include #include #include "mutex.h" -#include +#include "llcoros.h" +#include LLCOROS_CONDVAR_HEADER // // A general queue exception. @@ -119,10 +120,10 @@ private: U32 mCapacity; bool mClosed; - boost::fibers::mutex mLock; - typedef std::unique_lock lock_t; - boost::fibers::condition_variable mCapacityCond; - boost::fibers::condition_variable mEmptyCond; + LLCoros::Mutex mLock; + typedef LLCoros::LockType lock_t; + LLCoros::ConditionVariable mCapacityCond; + LLCoros::ConditionVariable mEmptyCond; }; // LLThreadSafeQueue -- cgit v1.2.3