summaryrefslogtreecommitdiff
path: root/indra/llcommon/llthreadsafequeue.h
diff options
context:
space:
mode:
Diffstat (limited to 'indra/llcommon/llthreadsafequeue.h')
-rw-r--r--indra/llcommon/llthreadsafequeue.h48
1 files changed, 40 insertions, 8 deletions
diff --git a/indra/llcommon/llthreadsafequeue.h b/indra/llcommon/llthreadsafequeue.h
index 06e8d8f609..2806506550 100644
--- a/indra/llcommon/llthreadsafequeue.h
+++ b/indra/llcommon/llthreadsafequeue.h
@@ -85,8 +85,8 @@ public:
LLThreadSafeQueue(U32 capacity = 1024);
virtual ~LLThreadSafeQueue() {}
- // Add an element to the queue (will block if the queue has
- // reached capacity).
+ // Add an element to the queue (will block if the queue has reached
+ // capacity).
//
// This call will raise an interrupt error if the queue is closed while
// the caller is blocked.
@@ -95,6 +95,11 @@ public:
// legacy name
void pushFront(ElementT const & element) { return push(element); }
+ // Add an element to the queue (will block if the queue has reached
+ // capacity). Return false if the queue is closed before push is possible.
+ template <typename T>
+ bool pushIfOpen(T&& element);
+
// Try to add an element to the queue without blocking. Returns
// true only if the element was actually added.
template <typename T>
@@ -270,6 +275,7 @@ template <typename ElementT, typename QueueT>
template <typename CALLABLE>
bool LLThreadSafeQueue<ElementT, QueueT>::tryLock(CALLABLE&& callable)
{
+ LL_PROFILE_ZONE_SCOPED;
lock_t lock1(mLock, std::defer_lock);
if (!lock1.try_lock())
return false;
@@ -286,6 +292,7 @@ bool LLThreadSafeQueue<ElementT, QueueT>::tryLockUntil(
const std::chrono::time_point<Clock, Duration>& until,
CALLABLE&& callable)
{
+ LL_PROFILE_ZONE_SCOPED;
lock_t lock1(mLock, std::defer_lock);
if (!lock1.try_lock_until(until))
return false;
@@ -299,6 +306,7 @@ template <typename ElementT, typename QueueT>
template <typename T>
bool LLThreadSafeQueue<ElementT, QueueT>::push_(lock_t& lock, T&& element)
{
+ LL_PROFILE_ZONE_SCOPED;
if (mStorage.size() >= mCapacity)
return false;
@@ -311,9 +319,10 @@ bool LLThreadSafeQueue<ElementT, QueueT>::push_(lock_t& lock, T&& element)
template <typename ElementT, typename QueueT>
-template<typename T>
-void LLThreadSafeQueue<ElementT, QueueT>::push(T&& element)
+template <typename T>
+bool LLThreadSafeQueue<ElementT, QueueT>::pushIfOpen(T&& element)
{
+ LL_PROFILE_ZONE_SCOPED;
lock_t lock1(mLock);
while (true)
{
@@ -321,12 +330,10 @@ void LLThreadSafeQueue<ElementT, QueueT>::push(T&& element)
// drained or not: the moment either end calls close(), further push()
// operations will fail.
if (mClosed)
- {
- LLTHROW(LLThreadSafeQueueInterrupt());
- }
+ return false;
if (push_(lock1, std::forward<T>(element)))
- return;
+ return true;
// Storage Full. Wait for signal.
mCapacityCond.wait(lock1);
@@ -334,10 +341,23 @@ void LLThreadSafeQueue<ElementT, QueueT>::push(T&& element)
}
+template <typename ElementT, typename QueueT>
+template<typename T>
+void LLThreadSafeQueue<ElementT, QueueT>::push(T&& element)
+{
+ LL_PROFILE_ZONE_SCOPED;
+ if (! pushIfOpen(std::forward<T>(element)))
+ {
+ LLTHROW(LLThreadSafeQueueInterrupt());
+ }
+}
+
+
template<typename ElementT, typename QueueT>
template<typename T>
bool LLThreadSafeQueue<ElementT, QueueT>::tryPush(T&& element)
{
+ LL_PROFILE_ZONE_SCOPED;
return tryLock(
[this, element=std::move(element)](lock_t& lock)
{
@@ -354,6 +374,7 @@ bool LLThreadSafeQueue<ElementT, QueueT>::tryPushFor(
const std::chrono::duration<Rep, Period>& timeout,
T&& element)
{
+ LL_PROFILE_ZONE_SCOPED;
// Convert duration to time_point: passing the same timeout duration to
// each of multiple calls is wrong.
return tryPushUntil(std::chrono::steady_clock::now() + timeout,
@@ -367,6 +388,7 @@ bool LLThreadSafeQueue<ElementT, QueueT>::tryPushUntil(
const std::chrono::time_point<Clock, Duration>& until,
T&& element)
{
+ LL_PROFILE_ZONE_SCOPED;
return tryLockUntil(
until,
[this, until, element=std::move(element)](lock_t& lock)
@@ -399,6 +421,7 @@ template <typename ElementT, typename QueueT>
typename LLThreadSafeQueue<ElementT, QueueT>::pop_result
LLThreadSafeQueue<ElementT, QueueT>::pop_(lock_t& lock, ElementT& element)
{
+ LL_PROFILE_ZONE_SCOPED;
// If mStorage is empty, there's no head element.
if (mStorage.empty())
return mClosed? DONE : EMPTY;
@@ -420,6 +443,7 @@ LLThreadSafeQueue<ElementT, QueueT>::pop_(lock_t& lock, ElementT& element)
template<typename ElementT, typename QueueT>
ElementT LLThreadSafeQueue<ElementT, QueueT>::pop(void)
{
+ LL_PROFILE_ZONE_SCOPED;
lock_t lock1(mLock);
ElementT value;
while (true)
@@ -448,6 +472,7 @@ ElementT LLThreadSafeQueue<ElementT, QueueT>::pop(void)
template<typename ElementT, typename QueueT>
bool LLThreadSafeQueue<ElementT, QueueT>::tryPop(ElementT & element)
{
+ LL_PROFILE_ZONE_SCOPED;
return tryLock(
[this, &element](lock_t& lock)
{
@@ -465,6 +490,7 @@ bool LLThreadSafeQueue<ElementT, QueueT>::tryPopFor(
const std::chrono::duration<Rep, Period>& timeout,
ElementT& element)
{
+ LL_PROFILE_ZONE_SCOPED;
// Convert duration to time_point: passing the same timeout duration to
// each of multiple calls is wrong.
return tryPopUntil(std::chrono::steady_clock::now() + timeout, element);
@@ -477,6 +503,7 @@ bool LLThreadSafeQueue<ElementT, QueueT>::tryPopUntil(
const std::chrono::time_point<Clock, Duration>& until,
ElementT& element)
{
+ LL_PROFILE_ZONE_SCOPED;
return tryLockUntil(
until,
[this, until, &element](lock_t& lock)
@@ -496,6 +523,7 @@ LLThreadSafeQueue<ElementT, QueueT>::tryPopUntil_(
const std::chrono::time_point<Clock, Duration>& until,
ElementT& element)
{
+ LL_PROFILE_ZONE_SCOPED;
while (true)
{
pop_result popped = pop_(lock, element);
@@ -522,6 +550,7 @@ LLThreadSafeQueue<ElementT, QueueT>::tryPopUntil_(
template<typename ElementT, typename QueueT>
size_t LLThreadSafeQueue<ElementT, QueueT>::size(void)
{
+ LL_PROFILE_ZONE_SCOPED;
lock_t lock(mLock);
return mStorage.size();
}
@@ -530,6 +559,7 @@ size_t LLThreadSafeQueue<ElementT, QueueT>::size(void)
template<typename ElementT, typename QueueT>
void LLThreadSafeQueue<ElementT, QueueT>::close()
{
+ LL_PROFILE_ZONE_SCOPED;
lock_t lock(mLock);
mClosed = true;
lock.unlock();
@@ -543,6 +573,7 @@ void LLThreadSafeQueue<ElementT, QueueT>::close()
template<typename ElementT, typename QueueT>
bool LLThreadSafeQueue<ElementT, QueueT>::isClosed()
{
+ LL_PROFILE_ZONE_SCOPED;
lock_t lock(mLock);
return mClosed;
}
@@ -551,6 +582,7 @@ bool LLThreadSafeQueue<ElementT, QueueT>::isClosed()
template<typename ElementT, typename QueueT>
bool LLThreadSafeQueue<ElementT, QueueT>::done()
{
+ LL_PROFILE_ZONE_SCOPED;
lock_t lock(mLock);
return mClosed && mStorage.empty();
}