33 #include <nsArrayUtils.h>
34 #include <nsAutoLock.h>
35 #include <nsComponentManagerUtils.h>
36 #include <nsIProgrammingLanguage.h>
37 #include <nsISupportsPrimitives.h>
38 #include <nsThreadUtils.h>
41 #include <nsIMutableArray.h>
78 nsIRunnable** aEvent);
113 NS_ASSERTION(aItem,
"sbRequestThreadQueue::Batch::push_back passed null");
120 mRequestType = aItem->
GetType();
126 mRequestType = aItem->
GetType();
130 mRequestItems.push_back(aItem);
137 if ((*aIter)->GetIsCountable()) {
138 PRUint32 index = (*aIter)->GetBatchIndex();
142 while (++iter != end) {
143 if ((*iter)->GetIsCountable()) {
144 (*iter)->SetBatchIndex(index++);
152 mRequestItems.erase(aIter);
155 if (mCountableItems == 0) {
156 if (mRequestItems.empty()) {
160 mRequestType = (*mRequestItems.begin())->GetType();
174 mRequestItems.clear();
178 void sbRequestThreadQueue::Batch::RecalcBatchStats()
181 const RequestItems::const_iterator end = mRequestItems.end();
182 for (RequestItems::const_iterator iter = mRequestItems.begin();
186 if ((*iter)->GetIsCountable()) {
187 (*iter)->SetBatchIndex(index++);
211 mLock = nsAutoLock::NewLock(
"sbRequestThreadQueue::mLock");
214 nsAutoMonitor::NewMonitor(
"sbRequestThreadQueue::mStopWaitMonitor");
219 NS_ASSERTION(mRequestQueue.size() == 0,
220 "sbRequestThreadQueue destructor with items in queue");
225 nsAutoLock::DestroyLock(
mLock);
233 NS_ENSURE_STATE(
mLock);
234 nsAutoLock lock(
mLock);
244 NS_ENSURE_STATE(
mLock);
245 nsAutoLock lock(
mLock);
247 "sbRequestThreadQueue batch depth out of balance");
261 nsresult aFailureReturnValue,
263 nsIRunnable ** aRunnable)
265 NS_ENSURE_ARG_POINTER(aRunnable);
270 Runnable * runnable = nsnull;
273 rv = Runnable::New(&runnable,
278 NS_ENSURE_SUCCESS(rv, rv);
280 *aRunnable = runnable;
289 NS_ENSURE_TRUE(
mLock, NS_ERROR_OUT_OF_MEMORY);
305 NS_ENSURE_SUCCESS(rv, rv);
309 &sbRequestThreadQueue::ThreadShutdownAction,
312 getter_AddRefs(mShutdownAction));
313 NS_ENSURE_SUCCESS(rv, rv);
318 rv = NS_NewThread(getter_AddRefs(mThread), nsnull);
319 NS_ENSURE_SUCCESS(rv, rv);
322 NS_ENSURE_SUCCESS(rv, rv);
330 NS_ENSURE_STATE(
mLock);
335 nsAutoLock lock(
mLock);
339 return NS_ERROR_NOT_AVAILABLE;
357 NS_WARN_IF_FALSE(NS_SUCCEEDED(rv),
"Failed to send thread stop message");
360 rv = ProcessRequest();
361 NS_WARN_IF_FALSE(NS_SUCCEEDED(rv),
"Failed to process stop message request");
366 nsresult sbRequestThreadQueue::ThreadShutdownAction(
int)
370 NS_ENSURE_TRUE(NS_IsMainThread(), NS_ERROR_FAILURE);
379 nsresult sbRequestThreadQueue::ProcessRequest()
381 NS_ENSURE_STATE(mReqAddedEvent);
383 nsresult rv = mThread->Dispatch(mReqAddedEvent, NS_DISPATCH_NORMAL);
384 NS_ENSURE_SUCCESS(rv, rv);
389 nsresult sbRequestThreadQueue::FindDuplicateRequest(
sbRequestItem * aItem,
392 NS_ENSURE_ARG_POINTER(aItem);
396 aIsDuplicate =
false;
401 const RequestQueue::const_reverse_iterator rend = mRequestQueue.rend();
402 for (RequestQueue::const_reverse_iterator riter = mRequestQueue.rbegin();
403 riter != rend && !aIsDuplicate;
414 const PRInt32 queueItemBatchId = request->
GetBatchId();
416 if (queueItemBatchId != mCurrentBatchId) {
419 bool continueChecking =
false;
420 rv = IsDuplicateRequest(request, aItem, aIsDuplicate, continueChecking);
421 NS_ENSURE_SUCCESS(rv, rv);
423 if (!continueChecking) {
431 nsresult sbRequestThreadQueue::PushRequestInternal(
sbRequestItem * aRequestItem)
433 NS_ENSURE_ARG_POINTER(aRequestItem);
437 rv = FindDuplicateRequest(aRequestItem, isDupe);
438 NS_ENSURE_SUCCESS(rv, rv);
443 aRequestItem->mBatchId = mCurrentBatchId;
445 NS_ADDREF(aRequestItem);
446 mRequestQueue.push_back(aRequestItem);
454 NS_ENSURE_ARG_POINTER(aRequestItem);
456 NS_ENSURE_STATE(
mLock);
461 nsAutoLock lock(
mLock);
470 rv = PushRequestInternal(aRequestItem);
471 NS_ENSURE_SUCCESS(rv, rv);
475 "Batch depth out of whack in sbBaseDevice::PushRequest");
478 rv = ProcessRequest();
479 NS_ENSURE_SUCCESS(rv, rv);
487 NS_ENSURE_STATE(
mLock);
489 nsAutoLock lock(
mLock);
494 if (mRequestQueue.empty()) {
495 LOG(
"No requests found\n");
501 LOG(
"Waiting on batch to complete\n");
504 RequestQueue::iterator queueIter = mRequestQueue.begin();
510 LOG(
"Single non-batch request found\n");
512 mRequestQueue.erase(queueIter);
518 const PRUint32 requestBatchId = request->
GetBatchId();
521 const RequestQueue::const_iterator queueEnd = mRequestQueue.end();
522 while (queueIter != queueEnd &&
523 requestBatchId == (*queueIter)->GetBatchId()) {
524 request = *queueIter++;
531 mRequestQueue.erase(mRequestQueue.begin(), queueIter);
538 NS_ENSURE_STATE(
mLock);
541 std::insert_iterator<Batch> insertIter(aBatch, aBatch.
end());
542 std::copy(mRequestQueue.begin(), mRequestQueue.end(), insertIter);
548 mRequestQueue.clear();
559 NS_ENSURE_STATE(
mLock);
564 nsAutoLock lock(
mLock);
567 NS_ENSURE_SUCCESS(rv, rv);
573 rv = CleanupBatch(batch);
574 NS_ENSURE_SUCCESS(rv, rv);
590 nsAutoLock lock(
mLock);
600 NS_ENSURE_SUCCESS(rv, rv);
605 rv = CleanupBatch(batch);
606 NS_ENSURE_SUCCESS(rv, rv);
615 NS_ASSERTION(
mLock,
"mLock null");
655 mAlreadyHandlingRequests = mRTQ->StartRequests();
659 if (!mAlreadyHandlingRequests) {
665 return mAlreadyHandlingRequests;
670 bool mAlreadyHandlingRequests;
677 sbRTQAddedEvent::Run()
679 NS_ENSURE_STATE(mRTQ);
690 if (autoIsHandlingRequests.AlreadyHandlingRequests()) {
698 NS_ENSURE_SUCCESS(rv, rv);
701 while (!batch.
empty()) {
706 NS_ENSURE_STATE(mRTQ->mShutdownAction);
707 NS_DispatchToMainThread(mRTQ->mShutdownAction);
711 mRTQ->mShutdownAction = NULL;
717 rv = mRTQ->CleanupBatch(batch);
718 NS_ENSURE_SUCCESS(rv, rv);
730 rv = mRTQ->OnThreadStart();
731 NS_ENSURE_SUCCESS(rv, rv);
734 rv = mRTQ->ProcessBatch(batch);
739 nsresult rv2 = mRTQ->CleanupBatch(batch);
740 NS_ENSURE_SUCCESS(rv2, rv2);
747 NS_ENSURE_SUCCESS(rv, rv);
750 NS_ENSURE_SUCCESS(rv, rv);
767 nsIRunnable** aEvent)
769 NS_ENSURE_ARG_POINTER(aEvent);
775 NS_ENSURE_TRUE(
event, NS_ERROR_OUT_OF_MEMORY);
777 rv =
event->Initialize(aRTQ);
778 NS_ENSURE_SUCCESS(rv, rv);
780 nsCOMPtr<nsIRunnable> runnable = do_QueryInterface(
event, &rv);
781 NS_ENSURE_SUCCESS(rv, rv);
783 runnable.forget(aEvent);
NS_DECL_ISUPPORTS static NS_DECL_NSIRUNNABLE nsresult New(sbRequestThreadQueue *aRTQ, nsIRunnable **aEvent)
#define SB_PRLOG_SETUP(x)
virtual void CompleteRequests()
sbAutoRequestHandling(sbRequestThreadQueue *aRTQ)
bool AlreadyHandlingRequests() const
nsresult Initialize(sbRequestThreadQueue *aRTQ)
void erase(iterator aIter)
static sbRequestItem * New(PRUint32 aType, bool aIsCountable=false)
const_iterator end() const
NS_IMPL_THREADSAFE_RELEASE(sbRequestThreadQueue)
RequestItems::const_iterator const_iterator
virtual ~sbRequestThreadQueue()
bool CheckAndResetRequestAbort()
Songbird Thread Utilities Definitions.
nsresult PopBatch(Batch &aBatch)
#define TRACE_FUNCTION(...)
nsresult ClearRequestsNoLock(Batch &aRequests)
NS_IMPL_THREADSAFE_ADDREF(sbRequestThreadQueue)
PRMonitor * mStopWaitMonitor
bool GetIsCountable() const
PRUint32 GetBatchId() const
PRUint32 RequestType() const
NS_IMPL_THREADSAFE_ISUPPORTS1(sbRTQAddedEvent, nsIRunnable)
nsresult CancelRequests()
void ReleaseRequestItem(sbRequestItem *aItem)
nsresult PushRequest(sbRequestItem *aRequestItem)
static nsresult sbRunnableMethod(sbRequestThreadQueue &aObject, nsresult(sbRequestThreadQueue::*aMethod)(int), nsresult aFailureReturnValue, int aArg1, nsIRunnable **aRunnable)
void SetBatchIndex(PRInt32 aBatchIndex)
void push_back(sbRequestItem *aItem)
RequestItems::iterator iterator