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