| OLD | NEW |
| (Empty) |
| 1 /* | |
| 2 * Copyright (c) 2012 The WebRTC project authors. All Rights Reserved. | |
| 3 * | |
| 4 * Use of this source code is governed by a BSD-style license | |
| 5 * that can be found in the LICENSE file in the root of the source | |
| 6 * tree. An additional intellectual property rights grant can be found | |
| 7 * in the file PATENTS. All contributing project authors may | |
| 8 * be found in the AUTHORS file in the root of the source tree. | |
| 9 */ | |
| 10 | |
| 11 #ifndef MODULES_AUDIO_CONFERENCE_MIXER_SOURCE_MEMORY_POOL_WINDOWS_H_ | |
| 12 #define MODULES_AUDIO_CONFERENCE_MIXER_SOURCE_MEMORY_POOL_WINDOWS_H_ | |
| 13 | |
| 14 #include <assert.h> | |
| 15 #include <windows.h> | |
| 16 | |
| 17 #include "system_wrappers/include/aligned_malloc.h" | |
| 18 #include "system_wrappers/include/atomic32.h" | |
| 19 #include "typedefs.h" // NOLINT(build/include) | |
| 20 | |
| 21 namespace webrtc { | |
| 22 template<class MemoryType> struct MemoryPoolItem; | |
| 23 | |
| 24 template<class MemoryType> | |
| 25 struct MemoryPoolItemPayload | |
| 26 { | |
| 27 MemoryPoolItemPayload() | |
| 28 : memoryType(), | |
| 29 base(NULL) | |
| 30 { | |
| 31 } | |
| 32 MemoryType memoryType; | |
| 33 MemoryPoolItem<MemoryType>* base; | |
| 34 }; | |
| 35 | |
| 36 template<class MemoryType> | |
| 37 struct MemoryPoolItem | |
| 38 { | |
| 39 // Atomic single linked list entry header. | |
| 40 SLIST_ENTRY itemEntry; | |
| 41 // Atomic single linked list payload. | |
| 42 MemoryPoolItemPayload<MemoryType>* payload; | |
| 43 }; | |
| 44 | |
| 45 template<class MemoryType> | |
| 46 class MemoryPoolImpl | |
| 47 { | |
| 48 public: | |
| 49 // MemoryPool functions. | |
| 50 int32_t PopMemory(MemoryType*& memory); | |
| 51 int32_t PushMemory(MemoryType*& memory); | |
| 52 | |
| 53 MemoryPoolImpl(int32_t /*initialPoolSize*/); | |
| 54 ~MemoryPoolImpl(); | |
| 55 | |
| 56 // Atomic functions. | |
| 57 int32_t Terminate(); | |
| 58 bool Initialize(); | |
| 59 private: | |
| 60 // Non-atomic function. | |
| 61 MemoryPoolItem<MemoryType>* CreateMemory(); | |
| 62 | |
| 63 // Windows implementation of single linked atomic list, documented here: | |
| 64 // http://msdn.microsoft.com/en-us/library/ms686962(VS.85).aspx | |
| 65 | |
| 66 // Atomic single linked list head. | |
| 67 PSLIST_HEADER _pListHead; | |
| 68 | |
| 69 Atomic32 _createdMemory; | |
| 70 Atomic32 _outstandingMemory; | |
| 71 }; | |
| 72 | |
| 73 template<class MemoryType> | |
| 74 MemoryPoolImpl<MemoryType>::MemoryPoolImpl( | |
| 75 int32_t /*initialPoolSize*/) | |
| 76 : _pListHead(NULL), | |
| 77 _createdMemory(0), | |
| 78 _outstandingMemory(0) | |
| 79 { | |
| 80 } | |
| 81 | |
| 82 template<class MemoryType> | |
| 83 MemoryPoolImpl<MemoryType>::~MemoryPoolImpl() | |
| 84 { | |
| 85 Terminate(); | |
| 86 if(_pListHead != NULL) | |
| 87 { | |
| 88 AlignedFree(reinterpret_cast<void*>(_pListHead)); | |
| 89 _pListHead = NULL; | |
| 90 } | |
| 91 // Trigger assert if there is outstanding memory. | |
| 92 assert(_createdMemory.Value() == 0); | |
| 93 assert(_outstandingMemory.Value() == 0); | |
| 94 } | |
| 95 | |
| 96 template<class MemoryType> | |
| 97 int32_t MemoryPoolImpl<MemoryType>::PopMemory(MemoryType*& memory) | |
| 98 { | |
| 99 PSLIST_ENTRY pListEntry = InterlockedPopEntrySList(_pListHead); | |
| 100 if(pListEntry == NULL) | |
| 101 { | |
| 102 MemoryPoolItem<MemoryType>* item = CreateMemory(); | |
| 103 if(item == NULL) | |
| 104 { | |
| 105 return -1; | |
| 106 } | |
| 107 pListEntry = &(item->itemEntry); | |
| 108 } | |
| 109 ++_outstandingMemory; | |
| 110 memory = &((MemoryPoolItem<MemoryType>*)pListEntry)->payload->memoryType; | |
| 111 return 0; | |
| 112 } | |
| 113 | |
| 114 template<class MemoryType> | |
| 115 int32_t MemoryPoolImpl<MemoryType>::PushMemory(MemoryType*& memory) | |
| 116 { | |
| 117 if(memory == NULL) | |
| 118 { | |
| 119 return -1; | |
| 120 } | |
| 121 | |
| 122 MemoryPoolItem<MemoryType>* item = | |
| 123 ((MemoryPoolItemPayload<MemoryType>*)memory)->base; | |
| 124 | |
| 125 const int32_t usedItems = --_outstandingMemory; | |
| 126 const int32_t totalItems = _createdMemory.Value(); | |
| 127 const int32_t freeItems = totalItems - usedItems; | |
| 128 if(freeItems < 0) | |
| 129 { | |
| 130 assert(false); | |
| 131 delete item->payload; | |
| 132 AlignedFree(item); | |
| 133 return -1; | |
| 134 } | |
| 135 if(freeItems >= totalItems>>1) | |
| 136 { | |
| 137 delete item->payload; | |
| 138 AlignedFree(item); | |
| 139 --_createdMemory; | |
| 140 return 0; | |
| 141 } | |
| 142 InterlockedPushEntrySList(_pListHead,&(item->itemEntry)); | |
| 143 return 0; | |
| 144 } | |
| 145 | |
| 146 template<class MemoryType> | |
| 147 bool MemoryPoolImpl<MemoryType>::Initialize() | |
| 148 { | |
| 149 _pListHead = (PSLIST_HEADER)AlignedMalloc(sizeof(SLIST_HEADER), | |
| 150 MEMORY_ALLOCATION_ALIGNMENT); | |
| 151 if(_pListHead == NULL) | |
| 152 { | |
| 153 return false; | |
| 154 } | |
| 155 InitializeSListHead(_pListHead); | |
| 156 return true; | |
| 157 } | |
| 158 | |
| 159 template<class MemoryType> | |
| 160 int32_t MemoryPoolImpl<MemoryType>::Terminate() | |
| 161 { | |
| 162 int32_t itemsFreed = 0; | |
| 163 PSLIST_ENTRY pListEntry = InterlockedPopEntrySList(_pListHead); | |
| 164 while(pListEntry != NULL) | |
| 165 { | |
| 166 MemoryPoolItem<MemoryType>* item = ((MemoryPoolItem<MemoryType>*)pListEn
try); | |
| 167 delete item->payload; | |
| 168 AlignedFree(item); | |
| 169 --_createdMemory; | |
| 170 itemsFreed++; | |
| 171 pListEntry = InterlockedPopEntrySList(_pListHead); | |
| 172 } | |
| 173 return itemsFreed; | |
| 174 } | |
| 175 | |
| 176 template<class MemoryType> | |
| 177 MemoryPoolItem<MemoryType>* MemoryPoolImpl<MemoryType>::CreateMemory() | |
| 178 { | |
| 179 MemoryPoolItem<MemoryType>* returnValue = (MemoryPoolItem<MemoryType>*) | |
| 180 AlignedMalloc(sizeof(MemoryPoolItem<MemoryType>), | |
| 181 MEMORY_ALLOCATION_ALIGNMENT); | |
| 182 if(returnValue == NULL) | |
| 183 { | |
| 184 return NULL; | |
| 185 } | |
| 186 | |
| 187 returnValue->payload = new MemoryPoolItemPayload<MemoryType>(); | |
| 188 if(returnValue->payload == NULL) | |
| 189 { | |
| 190 delete returnValue; | |
| 191 return NULL; | |
| 192 } | |
| 193 returnValue->payload->base = returnValue; | |
| 194 ++_createdMemory; | |
| 195 return returnValue; | |
| 196 } | |
| 197 } // namespace webrtc | |
| 198 | |
| 199 #endif // MODULES_AUDIO_CONFERENCE_MIXER_SOURCE_MEMORY_POOL_WINDOWS_H_ | |
| OLD | NEW |