DRTVWR-476: Wrap boost::fibers::mutex et al. with LLCoros aliases.
Specifically: LLCoros::Mutex means boost::fibers::mutex LLCoros::LockType means std::unique_lock<boost::fibers::mutex> 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.meow-7.2.2
parent
a83da3a452
commit
98dfba0d2f
|
|
@ -15,8 +15,9 @@
|
|||
#define LL_LLCOND_H
|
||||
|
||||
#include "llunits.h"
|
||||
#include <boost/fiber/condition_variable.hpp>
|
||||
#include <mutex>
|
||||
#include "llcoros.h"
|
||||
#include LLCOROS_MUTEX_HEADER
|
||||
#include "mutex.h"
|
||||
#include <chrono>
|
||||
|
||||
/**
|
||||
|
|
@ -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 <typename DATA>
|
||||
|
|
@ -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<boost::fibers::mutex> 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<boost::fibers::mutex> lk(mMutex);
|
||||
LLCoros::LockType lk(mMutex);
|
||||
modify(mData);
|
||||
}
|
||||
mCond.notify_all();
|
||||
|
|
@ -117,7 +118,7 @@ public:
|
|||
template <typename Pred>
|
||||
void wait(Pred pred)
|
||||
{
|
||||
std::unique_lock<boost::fibers::mutex> 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 <typename Clock, typename Duration, typename Pred>
|
||||
bool wait_until(const std::chrono::time_point<Clock, Duration>& timeout_time, Pred pred)
|
||||
{
|
||||
std::unique_lock<boost::fibers::mutex> 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<const value_type&>(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
|
||||
|
|
|
|||
|
|
@ -33,11 +33,24 @@
|
|||
#include <boost/fiber/fss.hpp>
|
||||
#include <boost/fiber/future/promise.hpp>
|
||||
#include <boost/fiber/future/future.hpp>
|
||||
#include "mutex.h"
|
||||
#include "llsingleton.h"
|
||||
#include "llinstancetracker.h"
|
||||
#include <boost/function.hpp>
|
||||
#include <string>
|
||||
|
||||
// e.g. #include LLCOROS_MUTEX_HEADER
|
||||
#define LLCOROS_MUTEX_HEADER <boost/fiber/mutex.hpp>
|
||||
#define LLCOROS_CONDVAR_HEADER <boost/fiber/condition_variable.hpp>
|
||||
|
||||
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 <typename T>
|
||||
static Future<T> getFuture(Promise<T>& promise) { return promise.get_future(); }
|
||||
|
||||
// use mutex, lock, condition_variable suitable for coroutines
|
||||
using Mutex = boost::fibers::mutex;
|
||||
using LockType = std::unique_lock<Mutex>;
|
||||
using cv_status = boost::fibers::cv_status;
|
||||
using ConditionVariable = boost::fibers::condition_variable;
|
||||
|
||||
/// for data local to each running coroutine
|
||||
template <typename T>
|
||||
using local_ptr = boost::fibers::fiber_specific_ptr<T>;
|
||||
|
|
|
|||
|
|
@ -31,7 +31,8 @@
|
|||
#include <deque>
|
||||
#include <string>
|
||||
#include "mutex.h"
|
||||
#include <boost/fiber/condition_variable.hpp>
|
||||
#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<decltype(mLock)> 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
|
||||
|
|
|
|||
Loading…
Reference in New Issue