Queue.h 3.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203
  1. /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
  2. /* This Source Code Form is subject to the terms of the Mozilla Public
  3. * License, v. 2.0. If a copy of the MPL was not distributed with this
  4. * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
  5. #ifndef mozilla_dom_workers_queue_h__
  6. #define mozilla_dom_workers_queue_h__
  7. #include "Workers.h"
  8. #include "mozilla/Mutex.h"
  9. #include "nsTArray.h"
  10. BEGIN_WORKERS_NAMESPACE
  11. template <typename T, int TCount>
  12. struct StorageWithTArray
  13. {
  14. typedef AutoTArray<T, TCount> StorageType;
  15. static void Reverse(StorageType& aStorage)
  16. {
  17. uint32_t length = aStorage.Length();
  18. for (uint32_t index = 0; index < length / 2; index++) {
  19. uint32_t reverseIndex = length - 1 - index;
  20. T t1 = aStorage.ElementAt(index);
  21. T t2 = aStorage.ElementAt(reverseIndex);
  22. aStorage.ReplaceElementsAt(index, 1, t2);
  23. aStorage.ReplaceElementsAt(reverseIndex, 1, t1);
  24. }
  25. }
  26. static bool IsEmpty(const StorageType& aStorage)
  27. {
  28. return !!aStorage.IsEmpty();
  29. }
  30. static bool Push(StorageType& aStorage, const T& aEntry)
  31. {
  32. return !!aStorage.AppendElement(aEntry);
  33. }
  34. static bool Pop(StorageType& aStorage, T& aEntry)
  35. {
  36. if (IsEmpty(aStorage)) {
  37. return false;
  38. }
  39. uint32_t index = aStorage.Length() - 1;
  40. aEntry = aStorage.ElementAt(index);
  41. aStorage.RemoveElementAt(index);
  42. return true;
  43. }
  44. static void Clear(StorageType& aStorage)
  45. {
  46. aStorage.Clear();
  47. }
  48. static void Compact(StorageType& aStorage)
  49. {
  50. aStorage.Compact();
  51. }
  52. };
  53. class LockingWithMutex
  54. {
  55. mozilla::Mutex mMutex;
  56. protected:
  57. LockingWithMutex()
  58. : mMutex("LockingWithMutex::mMutex")
  59. { }
  60. void Lock()
  61. {
  62. mMutex.Lock();
  63. }
  64. void Unlock()
  65. {
  66. mMutex.Unlock();
  67. }
  68. class AutoLock
  69. {
  70. LockingWithMutex& mHost;
  71. public:
  72. explicit AutoLock(LockingWithMutex& aHost)
  73. : mHost(aHost)
  74. {
  75. mHost.Lock();
  76. }
  77. ~AutoLock()
  78. {
  79. mHost.Unlock();
  80. }
  81. };
  82. friend class AutoLock;
  83. };
  84. class NoLocking
  85. {
  86. protected:
  87. void Lock()
  88. { }
  89. void Unlock()
  90. { }
  91. class AutoLock
  92. {
  93. public:
  94. explicit AutoLock(NoLocking& aHost)
  95. { }
  96. ~AutoLock()
  97. { }
  98. };
  99. };
  100. template <typename T,
  101. int TCount = 256,
  102. class LockingPolicy = NoLocking,
  103. class StoragePolicy = StorageWithTArray<T, TCount % 2 ?
  104. TCount / 2 + 1 :
  105. TCount / 2> >
  106. class Queue : public LockingPolicy
  107. {
  108. typedef typename StoragePolicy::StorageType StorageType;
  109. typedef typename LockingPolicy::AutoLock AutoLock;
  110. StorageType mStorage1;
  111. StorageType mStorage2;
  112. StorageType* mFront;
  113. StorageType* mBack;
  114. public:
  115. Queue()
  116. : mFront(&mStorage1), mBack(&mStorage2)
  117. { }
  118. bool IsEmpty()
  119. {
  120. AutoLock lock(*this);
  121. return StoragePolicy::IsEmpty(*mFront) &&
  122. StoragePolicy::IsEmpty(*mBack);
  123. }
  124. bool Push(const T& aEntry)
  125. {
  126. AutoLock lock(*this);
  127. return StoragePolicy::Push(*mBack, aEntry);
  128. }
  129. bool Pop(T& aEntry)
  130. {
  131. AutoLock lock(*this);
  132. if (StoragePolicy::IsEmpty(*mFront)) {
  133. StoragePolicy::Compact(*mFront);
  134. StoragePolicy::Reverse(*mBack);
  135. StorageType* tmp = mFront;
  136. mFront = mBack;
  137. mBack = tmp;
  138. }
  139. return StoragePolicy::Pop(*mFront, aEntry);
  140. }
  141. void Clear()
  142. {
  143. AutoLock lock(*this);
  144. StoragePolicy::Clear(*mFront);
  145. StoragePolicy::Clear(*mBack);
  146. }
  147. // XXX Do we need this?
  148. void Lock()
  149. {
  150. LockingPolicy::Lock();
  151. }
  152. // XXX Do we need this?
  153. void Unlock()
  154. {
  155. LockingPolicy::Unlock();
  156. }
  157. private:
  158. // Queue is not copyable.
  159. Queue(const Queue&);
  160. Queue & operator=(const Queue&);
  161. };
  162. END_WORKERS_NAMESPACE
  163. #endif /* mozilla_dom_workers_queue_h__ */