sbLocalDatabaseAsyncGUIDArray.cpp
Go to the documentation of this file.
1 /*
2 //
3 // BEGIN SONGBIRD GPL
4 //
5 // This file is part of the Songbird web player.
6 //
7 // Copyright(c) 2005-2008 POTI, Inc.
8 // http://songbirdnest.com
9 //
10 // This file may be licensed under the terms of of the
11 // GNU General Public License Version 2 (the "GPL").
12 //
13 // Software distributed under the License is distributed
14 // on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, either
15 // express or implied. See the GPL for the specific language
16 // governing rights and limitations.
17 //
18 // You should have received a copy of the GPL along with this
19 // program. If not, go to http://www.gnu.org/licenses/gpl.html
20 // or write to the Free Software Foundation, Inc.,
21 // 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
22 //
23 // END SONGBIRD GPL
24 //
25 */
26 
29 
30 #include <nsAutoLock.h>
31 #include <nsComponentManagerUtils.h>
32 #include <nsIObserverService.h>
33 #include <nsIStringEnumerator.h>
34 #include <nsIThread.h>
35 #include <nsIURI.h>
36 #include <nsThreadUtils.h>
37 #include <prlog.h>
38 #include <sbILocalDatabasePropertyCache.h>
39 #include <sbLocalDatabaseCID.h>
41 
42 /*
43  * To log this module, set the following environment variable:
44  * NSPR_LOG_MODULES=sbLocalDatabaseAsyncGUIDArray:5
45  */
46 #ifdef PR_LOGGING
47 static PRLogModuleInfo* gLocalDatabaseAsyncGUIDArrayLog = nsnull;
48 #define TRACE(args) PR_LOG(gLocalDatabaseAsyncGUIDArrayLog, PR_LOG_DEBUG, args)
49 #define LOG(args) PR_LOG(gLocalDatabaseAsyncGUIDArrayLog, PR_LOG_WARN, args)
50 #else
51 #define TRACE(args) /* nothing */
52 #define LOG(args) /* nothing */
53 #endif
54 
55 // Shut down the thread after 45 seconds of inactivity
56 #define SB_LOCALDATABASE_ASYNCGUIDARRAY_THREAD_TIMEOUT (45)
57 
58 
59 static const char kShutdownMessage[] = "xpcom-shutdown-threads";
60 
66 
68  mThreadShouldExit(PR_FALSE)
69 {
70 #ifdef PR_LOGGING
71  if (!gLocalDatabaseAsyncGUIDArrayLog) {
72  gLocalDatabaseAsyncGUIDArrayLog =
73  PR_NewLogModule("sbLocalDatabaseAsyncGUIDArray");
74  }
75 #endif
76 
77  TRACE(("sbLocalDatabaseAsyncGUIDArray[0x%x] - Created", this));
78  MOZ_COUNT_CTOR(sbLocalDatabaseAsyncGUIDArray);
79 }
80 
82 
83  TRACE(("sbLocalDatabaseAsyncGUIDArray[0x%x] - dtor", this));
84 
86 
87  if (mSyncMonitor) {
88  nsAutoMonitor::DestroyMonitor(mSyncMonitor);
89  }
90 
91  if (mQueueMonitor) {
92  nsAutoMonitor::DestroyMonitor(mQueueMonitor);
93  }
94 
95  TRACE(("sbLocalDatabaseAsyncGUIDArray[0x%x] - Destroyed", this));
96  MOZ_COUNT_DTOR(sbLocalDatabaseAsyncGUIDArray);
97 }
98 
99 nsresult
101 {
102  nsresult rv;
103 
104  mInner = new sbLocalDatabaseGUIDArray();
105  NS_ENSURE_TRUE(mInner, NS_ERROR_OUT_OF_MEMORY);
106 
107  mSyncMonitor = nsAutoMonitor::NewMonitor("sbLocalDatabaseAsyncGUIDArray::mSyncMonitor");
108  NS_ENSURE_TRUE(mSyncMonitor, NS_ERROR_OUT_OF_MEMORY);
109 
110  mQueueMonitor = nsAutoMonitor::NewMonitor("sbLocalDatabaseAsyncGUIDArray::mQueueMonitor");
111  NS_ENSURE_TRUE(mQueueMonitor, NS_ERROR_OUT_OF_MEMORY);
112 
113  nsCOMPtr<nsIObserverService> observerService =
114  do_GetService("@mozilla.org/observer-service;1", &rv);
115  NS_ENSURE_SUCCESS(rv, rv);
116 
117  rv = observerService->AddObserver(this, kShutdownMessage, PR_TRUE);
118  NS_ENSURE_SUCCESS(rv, rv);
119 
120  return NS_OK;
121 }
122 
123 nsresult
125 {
126  mThreadShouldExit = PR_FALSE;
127 
128  nsCOMPtr<nsIRunnable> runnable = new CommandProcessor(this);
129  NS_ENSURE_TRUE(runnable, NS_ERROR_OUT_OF_MEMORY);
130 
131  return NS_NewThread(getter_AddRefs(mThread), runnable);
132 }
133 
134 nsresult
136 {
137  // Note that the thread may have shut itself down due to inactivity
138 
139  if (mThread) {
140  if (mQueueMonitor) {
141  nsAutoMonitor mon(mQueueMonitor);
142  mThreadShouldExit = PR_TRUE;
143  mon.Notify();
144  }
145 
146  // Join the thead
147  mThread->Shutdown();
148  mThread = nsnull;
149  }
150 
151  return NS_OK;
152 }
153 
154 nsresult
156  PRUint32 aIndex)
157 {
158  nsresult rv;
159 
160  NS_ENSURE_STATE(mAsyncListenerArray.Length());
161 
162  TRACE(("sbLocalDatabaseAsyncGUIDArray[0x%x] - EnqueueCommand(%d, %d)",
163  this, aType, aIndex));
164 
165  {
166  nsAutoMonitor mon(mQueueMonitor);
167 
168  CommandSpec* cs = mQueue.AppendElement();
169  NS_ENSURE_TRUE(cs, NS_ERROR_OUT_OF_MEMORY);
170  cs->type = aType;
171  cs->index = aIndex;
172 
173  if (!mThread) {
174  rv = InitalizeThread();
175  NS_ENSURE_SUCCESS(rv, rv);
176  }
177 
178  mon.Notify();
179  }
180 
181  return NS_OK;
182 }
183 
184 // sbILocalDatabaseAsyncGUIDArray
185 NS_IMETHODIMP
186 sbLocalDatabaseAsyncGUIDArray::AddAsyncListener
188 {
189  TRACE(("LocalDatabaseAsyncGUIDArray[0x%.8x] - AddAsyncListener 0x%.8x",
190  this, aListener));
191 
192  NS_ENSURE_ARG_POINTER(aListener);
193 
194  /* Acquiring this spins the event loop; do it before grabbing mSyncMonitor */
195  nsresult rv;
196  nsCOMPtr<nsIProxyObjectManager> proxyObjMgr =
197  do_ProxiedGetService(NS_XPCOMPROXY_CONTRACTID, &rv);
198  NS_ENSURE_SUCCESS(rv, rv);
199 
200  nsAutoMonitor monitor(mSyncMonitor);
201 
202  // See if we have already added this listener.
203  PRUint32 length = mAsyncListenerArray.Length();
204  nsCOMPtr<nsISupports> ref = do_QueryInterface(aListener, &rv);
205  NS_ENSURE_SUCCESS(rv, rv);
206 
207  nsCOMPtr<nsIWeakReference> weak = do_GetWeakReference(aListener, &rv);
208  NS_ENSURE_SUCCESS(rv, rv);
209  for (PRUint32 i = 0; i < length; i++) {
210  if(mAsyncListenerArray[i]->mRef == weak) {
211  NS_WARNING("Attempted to add an async listener twice!");
212  return NS_OK;
213  }
214  }
215 
216  sbLocalDatabaseAsyncGUIDArrayListenerInfoAutoPtr
218  NS_ENSURE_TRUE(info, NS_ERROR_OUT_OF_MEMORY);
219 
220  rv = info->Init(proxyObjMgr, weak);
221  NS_ENSURE_SUCCESS(rv, rv);
222 
223  sbLocalDatabaseAsyncGUIDArrayListenerInfoAutoPtr* added =
224  mAsyncListenerArray.AppendElement(info.forget());
225  NS_ENSURE_TRUE(added, NS_ERROR_OUT_OF_MEMORY);
226 
227  return NS_OK;
228 }
229 
230 NS_IMETHODIMP
231 sbLocalDatabaseAsyncGUIDArray::RemoveAsyncListener
233 {
234  TRACE(("LocalDatabaseAsyncGUIDArray[0x%.8x] - RemoveAsyncListener 0x%.8x",
235  this, aListener));
236 
237  NS_ENSURE_ARG_POINTER(aListener);
238  nsAutoMonitor monitor(mSyncMonitor);
239 
240  nsresult rv;
241  PRUint32 length = mAsyncListenerArray.Length();
242 
243  nsCOMPtr<nsIWeakReference> weak = do_GetWeakReference(aListener, &rv);
244  NS_ENSURE_SUCCESS(rv, rv);
245  if (NS_SUCCEEDED(rv)) {
246  for (PRUint32 i = 0; i < length; i++) {
247  if(mAsyncListenerArray[i]->mRef == weak) {
248  mAsyncListenerArray.RemoveElementAt(i);
249  return NS_OK;
250  }
251  }
252  NS_WARNING("Attempted to remove an async listener that was never added!");
253  }
254 
255  return NS_OK;
256 }
257 
258 NS_IMETHODIMP
259 sbLocalDatabaseAsyncGUIDArray::GetLengthAsync()
260 {
261  return EnqueueCommand(eGetLength, 0);
262 }
263 
264 NS_IMETHODIMP
265 sbLocalDatabaseAsyncGUIDArray::GetGuidByIndexAsync(PRUint32 aIndex)
266 {
267  return EnqueueCommand(eGetByIndex, aIndex);
268 }
269 
270 NS_IMETHODIMP
271 sbLocalDatabaseAsyncGUIDArray::GetSortPropertyValueByIndexAsync(PRUint32 aIndex)
272 {
274 }
275 
276 NS_IMETHODIMP
277 sbLocalDatabaseAsyncGUIDArray::GetMediaItemIdByIndexAsync(PRUint32 aIndex)
278 {
279  return EnqueueCommand(eGetMediaItemIdByIndex, aIndex);
280 }
281 
282 NS_IMETHODIMP
283 sbLocalDatabaseAsyncGUIDArray::CloneAsyncArray(sbILocalDatabaseAsyncGUIDArray** _retval)
284 {
285  nsAutoMonitor monitor(mSyncMonitor);
286 
287  NS_ENSURE_ARG_POINTER(_retval);
288 
289  nsRefPtr<sbLocalDatabaseAsyncGUIDArray> newArray;
290  NS_NEWXPCOM(newArray, sbLocalDatabaseAsyncGUIDArray);
291  NS_ENSURE_TRUE(newArray, NS_ERROR_OUT_OF_MEMORY);
292 
293  nsresult rv = newArray->Init();
294  NS_ENSURE_SUCCESS(rv, rv);
295 
296  rv = mInner->CloneInto(newArray);
297  NS_ENSURE_SUCCESS(rv, rv);
298 
299  NS_ADDREF(*_retval = newArray);
300  return NS_OK;
301 }
302 
303 // nsIObserver
304 NS_IMETHODIMP
305 sbLocalDatabaseAsyncGUIDArray::Observe(nsISupports *aSubject,
306  const char *aTopic,
307  const PRUnichar *aData)
308 {
309  if (strcmp(aTopic, kShutdownMessage) == 0) {
310  TRACE(("sbLocalDatabaseAsyncGUIDArray[0x%x] - Observe", this));
311 
312  ShutdownThread();
313 
314  nsresult rv;
315  nsCOMPtr<nsIObserverService> observerService =
316  do_GetService("@mozilla.org/observer-service;1", &rv);
317  NS_ENSURE_SUCCESS(rv, rv);
318 
319  observerService->RemoveObserver(this, kShutdownMessage);
320  }
321  return NS_OK;
322 }
323 
324 // sbILocalDatabaseGUIDArray
325 NS_IMETHODIMP
326 sbLocalDatabaseAsyncGUIDArray::GetDatabaseGUID(nsAString& aDatabaseGUID)
327 {
328  nsAutoMonitor monitor(mSyncMonitor);
329 
330  return mInner->GetDatabaseGUID(aDatabaseGUID);
331 }
332 NS_IMETHODIMP
333 sbLocalDatabaseAsyncGUIDArray::SetDatabaseGUID(const nsAString& aDatabaseGUID)
334 {
335  nsAutoMonitor monitor(mSyncMonitor);
336 
337  return mInner->SetDatabaseGUID(aDatabaseGUID);
338 }
339 
340 NS_IMETHODIMP
341 sbLocalDatabaseAsyncGUIDArray::GetDatabaseLocation(nsIURI** aDatabaseLocation)
342 {
343  nsAutoMonitor monitor(mSyncMonitor);
344 
345  return mInner->GetDatabaseLocation(aDatabaseLocation);
346 }
347 NS_IMETHODIMP
348 sbLocalDatabaseAsyncGUIDArray::SetDatabaseLocation(nsIURI* aDatabaseLocation)
349 {
350  nsAutoMonitor monitor(mSyncMonitor);
351 
352  return mInner->SetDatabaseLocation(aDatabaseLocation);
353 }
354 
355 NS_IMETHODIMP
356 sbLocalDatabaseAsyncGUIDArray::GetBaseTable(nsAString& aBaseTable)
357 {
358  nsAutoMonitor monitor(mSyncMonitor);
359 
360  return mInner->GetBaseTable(aBaseTable);
361 }
362 NS_IMETHODIMP
363 sbLocalDatabaseAsyncGUIDArray::SetBaseTable(const nsAString& aBaseTable)
364 {
365  nsAutoMonitor monitor(mSyncMonitor);
366 
367  return mInner->SetBaseTable(aBaseTable);
368 }
369 
370 NS_IMETHODIMP
371 sbLocalDatabaseAsyncGUIDArray::GetBaseConstraintColumn(nsAString& aBaseConstraintColumn)
372 {
373  nsAutoMonitor monitor(mSyncMonitor);
374 
375  return mInner->GetBaseConstraintColumn(aBaseConstraintColumn);
376 }
377 NS_IMETHODIMP
378 sbLocalDatabaseAsyncGUIDArray::SetBaseConstraintColumn(const nsAString& aBaseConstraintColumn)
379 {
380  nsAutoMonitor monitor(mSyncMonitor);
381 
382  return mInner->SetBaseConstraintColumn(aBaseConstraintColumn);
383 }
384 
385 NS_IMETHODIMP
386 sbLocalDatabaseAsyncGUIDArray::GetBaseConstraintValue(PRUint32* aBaseConstraintValue)
387 {
388  nsAutoMonitor monitor(mSyncMonitor);
389 
390  return mInner->GetBaseConstraintValue(aBaseConstraintValue);
391 }
392 NS_IMETHODIMP
393 sbLocalDatabaseAsyncGUIDArray::SetBaseConstraintValue(PRUint32 aBaseConstraintValue)
394 {
395  nsAutoMonitor monitor(mSyncMonitor);
396 
397  return mInner->SetBaseConstraintValue(aBaseConstraintValue);
398 }
399 
400 NS_IMETHODIMP
401 sbLocalDatabaseAsyncGUIDArray::GetFetchSize(PRUint32* aFetchSize)
402 {
403  nsAutoMonitor monitor(mSyncMonitor);
404 
405  return mInner->GetFetchSize(aFetchSize);
406 }
407 NS_IMETHODIMP
408 sbLocalDatabaseAsyncGUIDArray::SetFetchSize(PRUint32 aFetchSize)
409 {
410  nsAutoMonitor monitor(mSyncMonitor);
411 
412  return mInner->SetFetchSize(aFetchSize);
413 }
414 
415 NS_IMETHODIMP
416 sbLocalDatabaseAsyncGUIDArray::GetIsDistinct(PRBool* aIsDistinct)
417 {
418  nsAutoMonitor monitor(mSyncMonitor);
419 
420  return mInner->GetIsDistinct(aIsDistinct);
421 }
422 NS_IMETHODIMP
423 sbLocalDatabaseAsyncGUIDArray::SetIsDistinct(PRBool aIsDistinct)
424 {
425  nsAutoMonitor monitor(mSyncMonitor);
426 
427  return mInner->SetIsDistinct(aIsDistinct);
428 }
429 
430 NS_IMETHODIMP
431 sbLocalDatabaseAsyncGUIDArray::GetIsValid(PRBool *aIsValid)
432 {
433  nsAutoMonitor monitor(mSyncMonitor);
434 
435  return mInner->GetIsValid(aIsValid);
436 }
437 
438 NS_IMETHODIMP
439 sbLocalDatabaseAsyncGUIDArray::GetDistinctWithSortableValues(PRBool *aDistinctWithSortableValues)
440 {
441  nsAutoMonitor monitor(mSyncMonitor);
442 
443  return mInner->GetDistinctWithSortableValues(aDistinctWithSortableValues);
444 }
445 NS_IMETHODIMP
446 sbLocalDatabaseAsyncGUIDArray::SetDistinctWithSortableValues(PRBool aDistinctWithSortableValues)
447 {
448  nsAutoMonitor monitor(mSyncMonitor);
449 
450  return mInner->SetDistinctWithSortableValues(aDistinctWithSortableValues);
451 }
452 
453 NS_IMETHODIMP
454 sbLocalDatabaseAsyncGUIDArray::GetLength(PRUint32* aLength)
455 {
456  nsAutoMonitor monitor(mSyncMonitor);
457 
458  return mInner->GetLength(aLength);
459 }
460 
461 NS_IMETHODIMP
462 sbLocalDatabaseAsyncGUIDArray::GetListener(sbILocalDatabaseGUIDArrayListener** aListener)
463 {
464  nsAutoMonitor monitor(mSyncMonitor);
465 
466  return mInner->GetListener(aListener);
467 }
468 NS_IMETHODIMP
469 sbLocalDatabaseAsyncGUIDArray::SetListener(sbILocalDatabaseGUIDArrayListener* aListener)
470 {
471  nsAutoMonitor monitor(mSyncMonitor);
472 
473  return mInner->SetListener(aListener);
474 }
475 
476 NS_IMETHODIMP
477 sbLocalDatabaseAsyncGUIDArray::GetPropertyCache(sbILocalDatabasePropertyCache** aPropertyCache)
478 {
479  nsAutoMonitor monitor(mSyncMonitor);
480 
481  return mInner->GetPropertyCache(aPropertyCache);
482 }
483 NS_IMETHODIMP
484 sbLocalDatabaseAsyncGUIDArray::SetPropertyCache(sbILocalDatabasePropertyCache* aPropertyCache)
485 {
486  nsAutoMonitor monitor(mSyncMonitor);
487 
488  return mInner->SetPropertyCache(aPropertyCache);
489 }
490 
491 NS_IMETHODIMP
492 sbLocalDatabaseAsyncGUIDArray::SetLengthCache(
494 {
495  nsAutoMonitor monitor(mSyncMonitor);
496 
497  return mInner->SetLengthCache(aLengthCache);
498 }
499 
500 NS_IMETHODIMP
501 sbLocalDatabaseAsyncGUIDArray::GetLengthCache(
503 {
504  nsAutoMonitor monitor(mSyncMonitor);
505 
506  return mInner->GetLengthCache(aLengthCache);
507 }
508 
509 NS_IMETHODIMP
510 sbLocalDatabaseAsyncGUIDArray::MayInvalidate(PRUint32 * aDirtyPropIDs,
511  PRUint32 aCount)
512 {
513  nsAutoMonitor monitor(mSyncMonitor);
514 
515  return mInner->MayInvalidate(aDirtyPropIDs, aCount);
516 }
517 
518 NS_IMETHODIMP
519 sbLocalDatabaseAsyncGUIDArray::AddSort(const nsAString& aProperty,
520  PRBool aAscending)
521 {
522  nsAutoMonitor monitor(mSyncMonitor);
523 
524  return mInner->AddSort(aProperty, aAscending);
525 }
526 
527 NS_IMETHODIMP
528 sbLocalDatabaseAsyncGUIDArray::ClearSorts()
529 {
530  nsAutoMonitor monitor(mSyncMonitor);
531 
532  return mInner->ClearSorts();
533 }
534 
535 NS_IMETHODIMP
536 sbLocalDatabaseAsyncGUIDArray::GetCurrentSort(sbIPropertyArray** aCurrentSort)
537 {
538  nsAutoMonitor monitor(mSyncMonitor);
539 
540  return mInner->GetCurrentSort(aCurrentSort);
541 }
542 
543 NS_IMETHODIMP
544 sbLocalDatabaseAsyncGUIDArray::AddFilter(const nsAString& aProperty,
545  nsIStringEnumerator* aValues,
546  PRBool aIsSearch)
547 {
548  nsAutoMonitor monitor(mSyncMonitor);
549 
550  return mInner->AddFilter(aProperty, aValues, aIsSearch);
551 }
552 
553 NS_IMETHODIMP
554 sbLocalDatabaseAsyncGUIDArray::ClearFilters()
555 {
556  nsAutoMonitor monitor(mSyncMonitor);
557 
558  return mInner->ClearFilters();
559 }
560 
561 NS_IMETHODIMP
562 sbLocalDatabaseAsyncGUIDArray::IsIndexCached(PRUint32 aIndex,
563  PRBool* _retval)
564 {
565  nsAutoMonitor monitor(mSyncMonitor);
566 
567  return mInner->IsIndexCached(aIndex, _retval);
568 }
569 
570 NS_IMETHODIMP
571 sbLocalDatabaseAsyncGUIDArray::GetSortPropertyValueByIndex(PRUint32 aIndex,
572  nsAString& _retval)
573 {
574  nsAutoMonitor monitor(mSyncMonitor);
575 
576  return mInner->GetSortPropertyValueByIndex(aIndex, _retval);
577 }
578 
579 NS_IMETHODIMP
580 sbLocalDatabaseAsyncGUIDArray::GetMediaItemIdByIndex(PRUint32 aIndex,
581  PRUint32* _retval)
582 {
583  nsAutoMonitor monitor(mSyncMonitor);
584 
585  return mInner->GetMediaItemIdByIndex(aIndex, _retval);
586 }
587 
588 NS_IMETHODIMP
589 sbLocalDatabaseAsyncGUIDArray::GetOrdinalByIndex(PRUint32 aIndex,
590  nsAString& _retval)
591 {
592  nsAutoMonitor monitor(mSyncMonitor);
593 
594  return mInner->GetOrdinalByIndex(aIndex, _retval);
595 }
596 
597 NS_IMETHODIMP
598 sbLocalDatabaseAsyncGUIDArray::GetGuidByIndex(PRUint32 aIndex,
599  nsAString& _retval)
600 {
601  nsAutoMonitor monitor(mSyncMonitor);
602 
603  return mInner->GetGuidByIndex(aIndex, _retval);
604 }
605 
606 NS_IMETHODIMP
607 sbLocalDatabaseAsyncGUIDArray::GetRowidByIndex(PRUint32 aIndex,
608  PRUint64* _retval)
609 {
610  nsAutoMonitor monitor(mSyncMonitor);
611 
612  return mInner->GetRowidByIndex(aIndex, _retval);
613 }
614 
615 NS_IMETHODIMP
616 sbLocalDatabaseAsyncGUIDArray::GetViewItemUIDByIndex(PRUint32 aIndex,
617  nsAString& _retval)
618 {
619  nsAutoMonitor monitor(mSyncMonitor);
620 
621  return mInner->GetViewItemUIDByIndex(aIndex, _retval);
622 }
623 
624 NS_IMETHODIMP
625 sbLocalDatabaseAsyncGUIDArray::Invalidate(PRBool aInvalidateLength)
626 {
627  nsAutoMonitor monitor(mSyncMonitor);
628 
629  return mInner->Invalidate(aInvalidateLength);
630 }
631 
632 NS_IMETHODIMP
633 sbLocalDatabaseAsyncGUIDArray::Clone(sbILocalDatabaseGUIDArray** _retval)
634 {
635  nsAutoMonitor monitor(mSyncMonitor);
636 
637  return mInner->Clone(_retval);
638 }
639 
640 NS_IMETHODIMP
641 sbLocalDatabaseAsyncGUIDArray::CloneInto(sbILocalDatabaseGUIDArray* aDest)
642 {
643  nsAutoMonitor monitor(mSyncMonitor);
644 
645  return mInner->CloneInto(aDest);
646 }
647 
648 NS_IMETHODIMP
649 sbLocalDatabaseAsyncGUIDArray::GetFirstIndexByPrefix(const nsAString& aValue,
650  PRUint32* _retval)
651 {
652  nsAutoMonitor monitor(mSyncMonitor);
653 
654  return mInner->GetFirstIndexByPrefix(aValue, _retval);
655 }
656 
657 NS_IMETHODIMP
658 sbLocalDatabaseAsyncGUIDArray::GetFirstIndexByGuid(const nsAString& aGuid,
659  PRUint32* _retval)
660 {
661  nsAutoMonitor monitor(mSyncMonitor);
662 
663  return mInner->GetFirstIndexByGuid(aGuid, _retval);
664 }
665 
666 NS_IMETHODIMP
667 sbLocalDatabaseAsyncGUIDArray::GetIndexByViewItemUID
668  (const nsAString& aViewItemUID,
669  PRUint32* _retval)
670 {
671  nsAutoMonitor monitor(mSyncMonitor);
672 
673  return mInner->GetIndexByViewItemUID(aViewItemUID, _retval);
674 }
675 
676 NS_IMETHODIMP
677 sbLocalDatabaseAsyncGUIDArray::ContainsGuid(const nsAString& aGuid,
678  PRBool* _retval)
679 {
680  nsAutoMonitor monitor(mSyncMonitor);
681 
682  return mInner->ContainsGuid(aGuid, _retval);
683 }
684 
685 NS_IMETHODIMP
686 sbLocalDatabaseAsyncGUIDArray::SuppressInvalidation(PRBool aSuppress)
687 {
688  nsAutoMonitor monitor(mSyncMonitor);
689 
690  return mInner->SuppressInvalidation(aSuppress);
691 }
692 
693 NS_IMETHODIMP
694 sbLocalDatabaseAsyncGUIDArray::RemoveByIndex(PRUint32 aIndex)
695 {
696  nsAutoMonitor monitor(mSyncMonitor);
697 
698  return mInner->RemoveByIndex(aIndex);
699 }
700 
701 nsresult
702 sbLocalDatabaseAsyncGUIDArray::SendOnGetLength(PRUint32 aLength,
703  nsresult aResult)
704 {
705  nsresult rv;
706  PRBool listenSucceeded = PR_TRUE;
707 
708  PRUint32 length = mAsyncListenerArray.Length();
709  for (PRUint32 i = 0; i < length; i++) {
710  rv = mAsyncListenerArray[i]->mProxiedListener->OnGetLength(aLength,
711  aResult);
712  if (NS_FAILED(rv))
713  listenSucceeded = PR_FALSE;
714  }
715  NS_WARN_IF_FALSE(listenSucceeded, "Listener notification failed");
716 
717  return NS_OK;
718 }
719 
720 nsresult
721 sbLocalDatabaseAsyncGUIDArray::SendOnGetGuidByIndex(PRUint32 aIndex,
722  const nsAString& aGUID,
723  nsresult aResult)
724 {
725  nsresult rv;
726  PRBool listenSucceeded = PR_TRUE;
727 
728  PRUint32 length = mAsyncListenerArray.Length();
729  for (PRUint32 i = 0; i < length; i++) {
730  rv = mAsyncListenerArray[i]->mProxiedListener->OnGetGuidByIndex(aIndex,
731  aGUID,
732  aResult);
733  if (NS_FAILED(rv))
734  listenSucceeded = PR_FALSE;
735  }
736  NS_WARN_IF_FALSE(listenSucceeded, "Listener notification failed");
737 
738  return NS_OK;
739 }
740 
741 nsresult
742 sbLocalDatabaseAsyncGUIDArray::SendOnGetSortPropertyValueByIndex
743  (PRUint32 aIndex,
744  const nsAString& aGUID,
745  nsresult aResult)
746 {
747  nsresult rv;
748  PRBool listenSucceeded = PR_TRUE;
749 
750  PRUint32 length = mAsyncListenerArray.Length();
751  for (PRUint32 i = 0; i < length; i++) {
752  rv = mAsyncListenerArray[i]->mProxiedListener->
753  OnGetSortPropertyValueByIndex(aIndex, aGUID, aResult);
754  if (NS_FAILED(rv))
755  listenSucceeded = PR_FALSE;
756  }
757  NS_WARN_IF_FALSE(listenSucceeded, "Listener notification failed");
758 
759  return NS_OK;
760 }
761 
762 nsresult
763 sbLocalDatabaseAsyncGUIDArray::SendOnGetMediaItemIdByIndex
764  (PRUint32 aIndex,
765  PRUint32 aMediaItemId,
766  nsresult aResult)
767 {
768  nsresult rv;
769  PRBool listenSucceeded = PR_TRUE;
770 
771  PRUint32 length = mAsyncListenerArray.Length();
772  for (PRUint32 i = 0; i < length; i++) {
773  rv = mAsyncListenerArray[i]->mProxiedListener->
774  OnGetMediaItemIdByIndex(aIndex, aMediaItemId, aResult);
775  if (NS_FAILED(rv))
776  listenSucceeded = PR_FALSE;
777  }
778  NS_WARN_IF_FALSE(listenSucceeded, "Listener notification failed");
779 
780  return NS_OK;
781 }
782 
783 nsresult
784 sbLocalDatabaseAsyncGUIDArray::SendOnStateChange(PRUint32 aState)
785 {
786  nsresult rv;
787  PRBool listenSucceeded = PR_TRUE;
788 
789  PRUint32 length = mAsyncListenerArray.Length();
790  for (PRUint32 i = 0; i < length; i++) {
791  rv = mAsyncListenerArray[i]->mProxiedListener->OnStateChange(aState);
792  if (NS_FAILED(rv))
793  listenSucceeded = PR_FALSE;
794  }
795  NS_WARN_IF_FALSE(listenSucceeded, "Listener notification failed");
796 
797  return NS_OK;
798 }
799 
801 
803  mFriendArray(aFriendArray)
804 {
805  TRACE(("sbLocalDatabaseAsyncGUIDArray[0x%x] - CommandProcessor ctor", this));
806 }
807 
809 {
810  TRACE(("sbLocalDatabaseAsyncGUIDArray[0x%x] - CommandProcessor dtor", this));
811 }
812 
813 NS_IMETHODIMP
814 CommandProcessor::Run()
815 {
816  nsresult rv;
817 
818  const PRIntervalTime timeout =
820 
821 
822  TRACE(("sbLocalDatabaseAsyncGUIDArray[0x%x] - Background Thread Start", mFriendArray));
823 
824  while (PR_TRUE) {
825 
826  CommandSpec cs;
827 
828  // Enter the monitor and wait for something to either appear on the queue
829  // or for a request to exit. When something shows up on the queue, pop
830  // it off the top and exit the monitor. If we time out without getting
831  // any work, shut down.
832  {
833  NS_ENSURE_TRUE(mFriendArray->mQueueMonitor, NS_ERROR_FAILURE);
834  nsAutoMonitor mon(mFriendArray->mQueueMonitor);
835 
836  while (mFriendArray->mQueue.Length() == 0 &&
837  !mFriendArray->mThreadShouldExit) {
838  rv = mon.Wait(timeout);
839 
840  if (NS_FAILED(rv)) {
841  // Another thread had the monitor when we timed out, so
842  // just go back and try again.
843  continue;
844  }
845 
846  if (mFriendArray->mQueue.Length() == 0 &&
847  !mFriendArray->mThreadShouldExit) {
848  // We timed out, and there is nothing in the queue,
849  // so might as well shut down.
850  nsCOMPtr<nsIThread> doomed;
851  // Try proxying to thread
852  do_GetProxyForObject(NS_PROXY_TO_MAIN_THREAD, NS_GET_IID(nsIThread),
853  mFriendArray->mThread, NS_PROXY_ASYNC, getter_AddRefs(doomed));
854  if (doomed) {
855  TRACE(("sbLocalDatabaseAsyncGUIDArray[0x%x] - Background Thread End Due To Timeout", mFriendArray));
856 
857  mFriendArray->mThread = nsnull;
858  mFriendArray->mThreadShouldExit = PR_TRUE;
859  doomed->Shutdown();
860 
861  // Return early to make sure nothing bad happens
862  return NS_OK;
863  } else {
864  NS_WARNING("failed to construct proxy to main thread");
865  }
866  }
867  }
868 
869  if (mFriendArray->mThreadShouldExit) {
870 
871  nsAutoMonitor monitor(mFriendArray->mSyncMonitor);
872 
873  // For each remaining item on the queue, send errors
874  for (PRUint32 i = 0; i < mFriendArray->mQueue.Length(); i++) {
875  const CommandSpec& command = mFriendArray->mQueue[i];
876  switch(command.type) {
877  case eGetLength:
878  rv = mFriendArray->SendOnGetLength(0, NS_ERROR_ABORT);
879  break;
880 
881  case eGetByIndex:
882  rv = mFriendArray->SendOnGetGuidByIndex(0,
883  EmptyString(),
885  break;
886 
888  rv = mFriendArray->SendOnGetSortPropertyValueByIndex(0,
889  EmptyString(),
891  break;
892 
894  rv = mFriendArray->SendOnGetMediaItemIdByIndex(0,
895  0,
897  break;
898 
899  default:
900  NS_NOTREACHED("Invalid command type");
901  rv = NS_ERROR_UNEXPECTED;
902  break;
903  }
904  NS_WARN_IF_FALSE(NS_SUCCEEDED(rv), "Listener notification failed");
905  }
906 
907  // Break out of the loop
908  break;
909  }
910 
911  // Pop the next command off the top of the queue
912  const CommandSpec& top = mFriendArray->mQueue[0];
913  cs.type = top.type;
914  cs.index = top.index;
915  mFriendArray->mQueue.RemoveElementAt(0);
916  }
917 
918  // Sync lock here so we don't run over synchronous usage of the array
919  {
920  nsAutoMonitor monitor(mFriendArray->mSyncMonitor);
921 
922  // Just for convenience
923  nsCOMPtr<sbILocalDatabaseGUIDArray> inner(mFriendArray->mInner);
924 
925  rv = mFriendArray->SendOnStateChange
927  NS_WARN_IF_FALSE(NS_SUCCEEDED(rv), "Listener notification failed");
928 
929  switch (cs.type) {
930  case eGetLength:
931  {
932  TRACE(("sbLocalDatabaseAsyncGUIDArray[0x%x] - "
933  "Background GetLength", mFriendArray));
934 
935  PRUint32 length;
936  nsresult innerResult = inner->GetLength(&length);
937  rv = mFriendArray->SendOnGetLength(length, innerResult);
938  }
939  break;
940 
941  case eGetByIndex:
942  {
943  TRACE(("sbLocalDatabaseAsyncGUIDArray[0x%x] - "
944  "Background GetGuidByIndex", mFriendArray));
945 
946  nsAutoString guid;
947  nsresult innerResult = inner->GetGuidByIndex(cs.index, guid);
948  rv = mFriendArray->SendOnGetGuidByIndex(cs.index,
949  guid,
950  innerResult);
951  }
952  break;
953 
955  {
956  TRACE(("sbLocalDatabaseAsyncGUIDArray[0x%x] - "
957  "Background GetSortPropertyValueByIndex", mFriendArray));
958 
959  nsAutoString value;
960  nsresult innerResult = inner->GetSortPropertyValueByIndex(cs.index,
961  value);
962  rv = mFriendArray->SendOnGetSortPropertyValueByIndex(cs.index,
963  value,
964  innerResult);
965  }
966  break;
967 
969  {
970  TRACE(("sbLocalDatabaseAsyncGUIDArray[0x%x] - "
971  "Background GetMediaItemIdByIndex", mFriendArray));
972 
973  PRUint32 mediaItemId;
974  nsresult innerResult = inner->GetMediaItemIdByIndex(cs.index,
975  &mediaItemId);
976  rv = mFriendArray->SendOnGetMediaItemIdByIndex(cs.index,
977  mediaItemId,
978  innerResult);
979  }
980  break;
981 
982  default:
983  NS_NOTREACHED("Invalid command type");
984  rv = NS_ERROR_UNEXPECTED;
985  break;
986  }
987  NS_WARN_IF_FALSE(NS_SUCCEEDED(rv), "Listener notification failed");
988 
989  rv = mFriendArray->SendOnStateChange
991  NS_WARN_IF_FALSE(NS_SUCCEEDED(rv), "Listener notification failed");
992  }
993  }
994 
995  TRACE(("sbLocalDatabaseAsyncGUIDArray[0x%x] - Background Thread End", mFriendArray));
996 
997  return NS_OK;
998 }
999 
1002 
1003 sbWeakAsyncListenerWrapper::sbWeakAsyncListenerWrapper(nsIWeakReference* aWeakReference) :
1004  mWeakListener(aWeakReference)
1005 {
1006  NS_ASSERTION(mWeakListener, "aWeakReference is null");
1007  MOZ_COUNT_CTOR(sbWeakAsyncListenerWrapper);
1008 }
1009 
1011 {
1012  MOZ_COUNT_DTOR(sbWeakAsyncListenerWrapper);
1013 }
1014 
1015 already_AddRefed<sbILocalDatabaseAsyncGUIDArrayListener>
1017 {
1018  nsCOMPtr<sbILocalDatabaseAsyncGUIDArrayListener> strongListener =
1019  do_QueryReferent(mWeakListener);
1020  if (!strongListener) {
1021  return nsnull;
1022  }
1023 
1024  sbILocalDatabaseAsyncGUIDArrayListener* listenerPtr = strongListener;
1025  NS_ADDREF(listenerPtr);
1026  return listenerPtr;
1027 }
1028 
1029 #define SB_TRY_NOTIFY(call) \
1030  nsCOMPtr<sbILocalDatabaseAsyncGUIDArrayListener> listener = \
1031  GetListener(); \
1032  if (listener) { \
1033  return listener->call; \
1034  } \
1035  return NS_OK;
1036 
1037 NS_IMETHODIMP
1038 sbWeakAsyncListenerWrapper::OnGetLength(PRUint32 aLength,
1039  nsresult aResult)
1040 {
1041  SB_TRY_NOTIFY(OnGetLength(aLength, aResult))
1042 }
1043 
1044 NS_IMETHODIMP
1045 sbWeakAsyncListenerWrapper::OnGetGuidByIndex(PRUint32 aIndex,
1046  const nsAString& aGUID,
1047  nsresult aResult)
1048 {
1049  SB_TRY_NOTIFY(OnGetGuidByIndex(aIndex, aGUID, aResult))
1050 }
1051 
1052 NS_IMETHODIMP
1053 sbWeakAsyncListenerWrapper::OnGetSortPropertyValueByIndex(PRUint32 aIndex,
1054  const nsAString& aPropertySortValue,
1055  nsresult aResult)
1056 {
1057  SB_TRY_NOTIFY(OnGetSortPropertyValueByIndex(aIndex, aPropertySortValue, aResult))
1058 }
1059 
1060 NS_IMETHODIMP
1061 sbWeakAsyncListenerWrapper::OnGetMediaItemIdByIndex(PRUint32 aIndex,
1062  PRUint32 aMediaItemId,
1063  nsresult aResult)
1064 {
1065  SB_TRY_NOTIFY(OnGetMediaItemIdByIndex(aIndex, aMediaItemId, aResult))
1066 }
1067 
1068 NS_IMETHODIMP
1069 sbWeakAsyncListenerWrapper::OnStateChange(PRUint32 aState)
1070 {
1071  SB_TRY_NOTIFY(OnStateChange(aState))
1072 }
1073 
1076 {
1078 }
1079 
1082 {
1084 }
1085 
1086 nsresult
1088  nsIProxyObjectManager *aProxyObjMgr,
1089  nsIWeakReference* aWeakListener)
1090 {
1091  NS_ENSURE_ARG_POINTER(aProxyObjMgr);
1092  NS_ASSERTION(aWeakListener, "aWeakListener is null");
1093  nsresult rv;
1094 
1095  mRef = do_QueryInterface(aWeakListener, &rv);
1096  NS_ENSURE_SUCCESS(rv, rv);
1097 
1098  mWeakListenerWrapper = new sbWeakAsyncListenerWrapper(aWeakListener);
1099  NS_ENSURE_TRUE(mWeakListenerWrapper, NS_ERROR_OUT_OF_MEMORY);
1100 
1101  /* Must not spin the event loop here - this is called with a lock held */
1102  rv = do_GetProxyForObjectWithManager(aProxyObjMgr,
1103  NS_PROXY_TO_CURRENT_THREAD,
1104  NS_GET_IID(
1106  mWeakListenerWrapper,
1107  NS_PROXY_ASYNC | NS_PROXY_ALWAYS,
1108  getter_AddRefs(mProxiedListener));
1109  NS_ENSURE_SUCCESS(rv, rv);
1110 
1111  return NS_OK;
1112 }
1113 
return NS_OK
[USER CODE SHOULD NOT REFERENCE THIS CLASS]
static nsCOMPtr< nsIObserverService > observerService
Definition: UnityProxy.cpp:6
[USER CODE SHOULD NOT REFERENCE THIS CLASS]
#define SB_LOCALDATABASE_ASYNCGUIDARRAY_THREAD_TIMEOUT
onPageChanged aValue
Definition: FeedWriter.js:1395
[USER CODE SHOULD NOT REFERENCE THIS CLASS]
sbLocalDatabaseAsyncGUIDArray * mFriendArray
#define SB_TRY_NOTIFY(call)
[USER CODE SHOULD NOT REFERENCE THIS CLASS]
const NS_ERROR_ABORT
nsresult do_GetProxyForObject(nsIEventTarget *aTarget, REFNSIID aIID, nsISupports *aObj, PRInt32 aProxyType, void **aProxyObject)
nsresult EnqueueCommand(CommandType aType, PRUint32 aIndex)
already_AddRefed< sbILocalDatabaseAsyncGUIDArrayListener > GetListener()
nsresult Init(nsIProxyObjectManager *aProxyObjMgr, nsIWeakReference *aWeakListener)
const sbCreateProxiedComponent do_ProxiedGetService(const nsCID &aCID, nsresult *error=0)
static const char kShutdownMessage[]
#define TRACE(args)
NS_DECL_ISUPPORTS NS_DECL_SBILOCALDATABASEGUIDARRAY NS_DECL_SBILOCALDATABASEASYNCGUIDARRAY NS_DECL_NSIOBSERVER nsresult Init()
readonly attribute unsigned long length
NS_IMPL_THREADSAFE_ISUPPORTS4(sbLocalDatabaseAsyncGUIDArray, sbILocalDatabaseGUIDArray, sbILocalDatabaseAsyncGUIDArray, nsIObserver, nsISupportsWeakReference) sbLocalDatabaseAsyncGUIDArray
[USER CODE SHOULD NOT REFERENCE THIS CLASS]
countRef value
Definition: FeedWriter.js:1423
restoreHistoryPrecursor aCount
[USER CODE SHOULD NOT REFERENCE THIS CLASS]
nsresult do_GetProxyForObjectWithManager(nsIProxyObjectManager *aProxyObjMgr, nsIEventTarget *aTarget, REFNSIID aIID, nsISupports *aObj, PRInt32 aProxyType, void **aProxyObject)
restoreWindow aState
An interface to carry around arrays of nsIProperty instances. Users of this interface should only QI ...
_getSelectedPageStyle s i
_updateTextAndScrollDataForFrame aData
NS_IMPL_THREADSAFE_ISUPPORTS1(sbWeakAsyncListenerWrapper, sbILocalDatabaseAsyncGUIDArrayListener) sbWeakAsyncListenerWrapper