DS_ThreadsafeAllocatingQueue.h 4.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184
  1. /*
  2. * Copyright (c) 2014, Oculus VR, Inc.
  3. * All rights reserved.
  4. *
  5. * This source code is licensed under the BSD-style license found in the
  6. * LICENSE file in the root directory of this source tree. An additional grant
  7. * of patent rights can be found in the PATENTS file in the same directory.
  8. *
  9. */
  10. /// \file DS_ThreadsafeAllocatingQueue.h
  11. /// \internal
  12. /// A threadsafe queue, that also uses a memory pool for allocation
  13. #ifndef __THREADSAFE_ALLOCATING_QUEUE
  14. #define __THREADSAFE_ALLOCATING_QUEUE
  15. #include "DS_Queue.h"
  16. #include "SimpleMutex.h"
  17. #include "DS_MemoryPool.h"
  18. // #if defined(new)
  19. // #pragma push_macro("new")
  20. // #undef new
  21. // #define RMO_NEW_UNDEF_ALLOCATING_QUEUE
  22. // #endif
  23. namespace DataStructures
  24. {
  25. template <class structureType>
  26. class RAK_DLL_EXPORT ThreadsafeAllocatingQueue
  27. {
  28. public:
  29. // Queue operations
  30. void Push(structureType *s);
  31. structureType *PopInaccurate(void);
  32. structureType *Pop(void);
  33. void SetPageSize(int size);
  34. bool IsEmpty(void);
  35. structureType * operator[] ( unsigned int position );
  36. void RemoveAtIndex( unsigned int position );
  37. unsigned int Size( void );
  38. // Memory pool operations
  39. structureType *Allocate(const char *file, unsigned int line);
  40. void Deallocate(structureType *s, const char *file, unsigned int line);
  41. void Clear(const char *file, unsigned int line);
  42. protected:
  43. mutable MemoryPool<structureType> memoryPool;
  44. RakNet::SimpleMutex memoryPoolMutex;
  45. Queue<structureType*> queue;
  46. RakNet::SimpleMutex queueMutex;
  47. };
  48. template <class structureType>
  49. void ThreadsafeAllocatingQueue<structureType>::Push(structureType *s)
  50. {
  51. queueMutex.Lock();
  52. queue.Push(s, _FILE_AND_LINE_ );
  53. queueMutex.Unlock();
  54. }
  55. template <class structureType>
  56. structureType *ThreadsafeAllocatingQueue<structureType>::PopInaccurate(void)
  57. {
  58. structureType *s;
  59. if (queue.IsEmpty())
  60. return 0;
  61. queueMutex.Lock();
  62. if (queue.IsEmpty()==false)
  63. s=queue.Pop();
  64. else
  65. s=0;
  66. queueMutex.Unlock();
  67. return s;
  68. }
  69. template <class structureType>
  70. structureType *ThreadsafeAllocatingQueue<structureType>::Pop(void)
  71. {
  72. structureType *s;
  73. queueMutex.Lock();
  74. if (queue.IsEmpty())
  75. {
  76. queueMutex.Unlock();
  77. return 0;
  78. }
  79. s=queue.Pop();
  80. queueMutex.Unlock();
  81. return s;
  82. }
  83. template <class structureType>
  84. structureType *ThreadsafeAllocatingQueue<structureType>::Allocate(const char *file, unsigned int line)
  85. {
  86. structureType *s;
  87. memoryPoolMutex.Lock();
  88. s=memoryPool.Allocate(file, line);
  89. memoryPoolMutex.Unlock();
  90. // Call new operator, memoryPool doesn't do this
  91. s = new ((void*)s) structureType;
  92. return s;
  93. }
  94. template <class structureType>
  95. void ThreadsafeAllocatingQueue<structureType>::Deallocate(structureType *s, const char *file, unsigned int line)
  96. {
  97. // Call delete operator, memory pool doesn't do this
  98. s->~structureType();
  99. memoryPoolMutex.Lock();
  100. memoryPool.Release(s, file, line);
  101. memoryPoolMutex.Unlock();
  102. }
  103. template <class structureType>
  104. void ThreadsafeAllocatingQueue<structureType>::Clear(const char *file, unsigned int line)
  105. {
  106. memoryPoolMutex.Lock();
  107. for (unsigned int i=0; i < queue.Size(); i++)
  108. {
  109. queue[i]->~structureType();
  110. memoryPool.Release(queue[i], file, line);
  111. }
  112. queue.Clear(file, line);
  113. memoryPoolMutex.Unlock();
  114. memoryPoolMutex.Lock();
  115. memoryPool.Clear(file, line);
  116. memoryPoolMutex.Unlock();
  117. }
  118. template <class structureType>
  119. void ThreadsafeAllocatingQueue<structureType>::SetPageSize(int size)
  120. {
  121. memoryPool.SetPageSize(size);
  122. }
  123. template <class structureType>
  124. bool ThreadsafeAllocatingQueue<structureType>::IsEmpty(void)
  125. {
  126. bool isEmpty;
  127. queueMutex.Lock();
  128. isEmpty=queue.IsEmpty();
  129. queueMutex.Unlock();
  130. return isEmpty;
  131. }
  132. template <class structureType>
  133. structureType * ThreadsafeAllocatingQueue<structureType>::operator[] ( unsigned int position )
  134. {
  135. structureType *s;
  136. queueMutex.Lock();
  137. s=queue[position];
  138. queueMutex.Unlock();
  139. return s;
  140. }
  141. template <class structureType>
  142. void ThreadsafeAllocatingQueue<structureType>::RemoveAtIndex( unsigned int position )
  143. {
  144. queueMutex.Lock();
  145. queue.RemoveAtIndex(position);
  146. queueMutex.Unlock();
  147. }
  148. template <class structureType>
  149. unsigned int ThreadsafeAllocatingQueue<structureType>::Size( void )
  150. {
  151. unsigned int s;
  152. queueMutex.Lock();
  153. s=queue.Size();
  154. queueMutex.Unlock();
  155. return s;
  156. }
  157. }
  158. // #if defined(RMO_NEW_UNDEF_ALLOCATING_QUEUE)
  159. // #pragma pop_macro("new")
  160. // #undef RMO_NEW_UNDEF_ALLOCATING_QUEUE
  161. // #endif
  162. #endif
粤ICP备19079148号