diff --git a/indra/llcommon/llthreadsafequeue.h b/indra/llcommon/llthreadsafequeue.h
index 8f5e0f3bf3afd21d809bb9150addbfcf80392075..30dd507f73acac5aaa29c8c9fa30f80d5921e6ca 100644
--- a/indra/llcommon/llthreadsafequeue.h
+++ b/indra/llcommon/llthreadsafequeue.h
@@ -30,8 +30,11 @@
 #include "llexception.h"
 #include <deque>
 #include <string>
+#include <chrono>
 #include "mutex.h"
 #include "llcoros.h"
+#include LLCOROS_MUTEX_HEADER
+#include <boost/fiber/timed_mutex.hpp>
 #include LLCOROS_CONDVAR_HEADER
 
 //
@@ -83,10 +86,20 @@ class LLThreadSafeQueue
 	// the caller is blocked.
 	void pushFront(ElementT const & element);
 	
-	// Try to add an element to the front ofqueue without blocking. Returns
+	// Try to add an element to the front of queue without blocking. Returns
 	// true only if the element was actually added.
 	bool tryPushFront(ElementT const & element);
-	
+
+	// Try to add an element to the front of queue, blocking if full but with
+	// timeout. Returns true if the element was added.
+	// There are potentially two different timeouts involved: how long to try
+	// to lock the mutex, versus how long to wait for the queue to stop being
+	// full. Careful settings for each timeout might be orders of magnitude
+	// apart. However, this method conflates them.
+	template <typename Rep, typename Period>
+	bool tryPushFrontFor(const std::chrono::duration<Rep, Period>& timeout,
+						 ElementT const & element);
+
 	// Pop the element at the end of the queue (will block if the queue is
 	// empty).
 	//
@@ -120,10 +133,10 @@ class LLThreadSafeQueue
 	U32 mCapacity;
 	bool mClosed;
 
-	LLCoros::Mutex mLock;
-	typedef LLCoros::LockType lock_t;
-	LLCoros::ConditionVariable mCapacityCond;
-	LLCoros::ConditionVariable mEmptyCond;
+	boost::fibers::timed_mutex mLock;
+	typedef std::unique_lock<decltype(mLock)> lock_t;
+	boost::fibers::condition_variable_any mCapacityCond;
+	boost::fibers::condition_variable_any mEmptyCond;
 };
 
 // LLThreadSafeQueue
@@ -162,6 +175,46 @@ void LLThreadSafeQueue<ElementT>::pushFront(ElementT const & element)
 }
 
 
+template <typename ElementT>
+template <typename Rep, typename Period>
+bool LLThreadSafeQueue<ElementT>::tryPushFrontFor(const std::chrono::duration<Rep, Period>& timeout,
+                                                  ElementT const & element)
+{
+    // Convert duration to time_point: passing the same timeout duration to
+    // each of multiple calls is wrong.
+    auto endpoint = std::chrono::steady_clock::now() + timeout;
+
+    lock_t lock1(mLock, std::defer_lock);
+    if (!lock1.try_lock_until(endpoint))
+        return false;
+
+    while (true)
+    {
+        if (mClosed)
+        {
+            return false;
+        }
+
+        if (mStorage.size() < mCapacity)
+        {
+            mStorage.push_front(element);
+            lock1.unlock();
+            mEmptyCond.notify_one();
+            return true;
+        }
+
+        // Storage Full. Wait for signal.
+        if (LLCoros::cv_status::timeout == mCapacityCond.wait_until(lock1, endpoint))
+        {
+            // timed out -- formally we might recheck both conditions above
+            return false;
+        }
+        // If we didn't time out, we were notified for some reason. Loop back
+        // to check.
+    }
+}
+
+
 template<typename ElementT>
 bool LLThreadSafeQueue<ElementT>::tryPushFront(ElementT const & element)
 {