From 89f2169e9d2c03ed92810689563ca110886abf16 Mon Sep 17 00:00:00 2001 From: Nat Goodspeed Date: Thu, 4 Nov 2021 16:43:11 -0400 Subject: SL-16202: Add postIfOpen() methods to WorkQueue, LLThreadSafeQueue. postIfOpen() provides a no-exception alternative to post(), which blocks if full but throws if closed. postIfOpen() likewise blocks if full, but returns true if able to post and false if the queue was closed. --- indra/llcommon/llthreadsafequeue.h | 30 ++++++++++++++++++++++-------- indra/llcommon/workqueue.h | 29 ++++++++++++++++++++++++++--- 2 files changed, 48 insertions(+), 11 deletions(-) (limited to 'indra') diff --git a/indra/llcommon/llthreadsafequeue.h b/indra/llcommon/llthreadsafequeue.h index 06e8d8f609..5c934791fe 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 + bool pushIfOpen(T&& element); + // Try to add an element to the queue without blocking. Returns // true only if the element was actually added. template @@ -311,8 +316,8 @@ bool LLThreadSafeQueue::push_(lock_t& lock, T&& element) template -template -void LLThreadSafeQueue::push(T&& element) +template +bool LLThreadSafeQueue::pushIfOpen(T&& element) { lock_t lock1(mLock); while (true) @@ -321,12 +326,10 @@ void LLThreadSafeQueue::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(element))) - return; + return true; // Storage Full. Wait for signal. mCapacityCond.wait(lock1); @@ -334,6 +337,17 @@ void LLThreadSafeQueue::push(T&& element) } +template +template +void LLThreadSafeQueue::push(T&& element) +{ + if (! pushIfOpen(std::forward(element))) + { + LLTHROW(LLThreadSafeQueueInterrupt()); + } +} + + template template bool LLThreadSafeQueue::tryPush(T&& element) diff --git a/indra/llcommon/workqueue.h b/indra/llcommon/workqueue.h index 76d31f32a6..d0e3f870fe 100644 --- a/indra/llcommon/workqueue.h +++ b/indra/llcommon/workqueue.h @@ -75,9 +75,10 @@ namespace LL template void post(const TimePoint& time, CALLABLE&& callable) { - // Defer reifying an arbitrary CALLABLE until we hit this method. - // All other methods should accept CALLABLEs of arbitrary type to - // avoid multiple levels of std::function indirection. + // Defer reifying an arbitrary CALLABLE until we hit this or + // postIfOpen(). All other methods should accept CALLABLEs of + // arbitrary type to avoid multiple levels of std::function + // indirection. mQueue.push(TimedWork(time, std::move(callable))); } @@ -92,6 +93,28 @@ namespace LL post(TimePoint::clock::now(), std::move(callable)); } + /** + * post work for a particular time, unless the queue is closed before + * we can post + */ + template + bool postIfOpen(const TimePoint& time, CALLABLE&& callable) + { + // Defer reifying an arbitrary CALLABLE until we hit this or + // post(). All other methods should accept CALLABLEs of arbitrary + // type to avoid multiple levels of std::function indirection. + return mQueue.pushIfOpen(TimedWork(time, std::move(callable))); + } + + /** + * post work, unless the queue is closed before we can post + */ + template + bool postIfOpen(CALLABLE&& callable) + { + return postIfOpen(TimePoint::clock::now(), std::move(callable)); + } + /** * Post work to be run at a specified time to another WorkQueue, which * may or may not still exist and be open. Return true if we were able -- cgit v1.2.3