/* * Copyright (c) 2012 The WebRTC project authors. All Rights Reserved. * * Use of this source code is governed by a BSD-style license * that can be found in the LICENSE file in the root of the source * tree. An additional intellectual property rights grant can be found * in the file PATENTS. All contributing project authors may * be found in the AUTHORS file in the root of the source tree. */ #ifndef WEBRTC_MODULES_AUDIO_CONFERENCE_MIXER_SOURCE_MEMORY_POOL_WINDOWS_H_ #define WEBRTC_MODULES_AUDIO_CONFERENCE_MIXER_SOURCE_MEMORY_POOL_WINDOWS_H_ #include #include #include "webrtc/system_wrappers/include/aligned_malloc.h" #include "webrtc/system_wrappers/include/atomic32.h" #include "webrtc/typedefs.h" namespace webrtc { template struct MemoryPoolItem; template struct MemoryPoolItemPayload { MemoryPoolItemPayload() : memoryType(), base(NULL) { } MemoryType memoryType; MemoryPoolItem* base; }; template struct MemoryPoolItem { // Atomic single linked list entry header. SLIST_ENTRY itemEntry; // Atomic single linked list payload. MemoryPoolItemPayload* payload; }; template class MemoryPoolImpl { public: // MemoryPool functions. int32_t PopMemory(MemoryType*& memory); int32_t PushMemory(MemoryType*& memory); MemoryPoolImpl(int32_t /*initialPoolSize*/); ~MemoryPoolImpl(); // Atomic functions. int32_t Terminate(); bool Initialize(); private: // Non-atomic function. MemoryPoolItem* CreateMemory(); // Windows implementation of single linked atomic list, documented here: // http://msdn.microsoft.com/en-us/library/ms686962(VS.85).aspx // Atomic single linked list head. PSLIST_HEADER _pListHead; Atomic32 _createdMemory; Atomic32 _outstandingMemory; }; template MemoryPoolImpl::MemoryPoolImpl( int32_t /*initialPoolSize*/) : _pListHead(NULL), _createdMemory(0), _outstandingMemory(0) { } template MemoryPoolImpl::~MemoryPoolImpl() { Terminate(); if(_pListHead != NULL) { AlignedFree(reinterpret_cast(_pListHead)); _pListHead = NULL; } // Trigger assert if there is outstanding memory. assert(_createdMemory.Value() == 0); assert(_outstandingMemory.Value() == 0); } template int32_t MemoryPoolImpl::PopMemory(MemoryType*& memory) { PSLIST_ENTRY pListEntry = InterlockedPopEntrySList(_pListHead); if(pListEntry == NULL) { MemoryPoolItem* item = CreateMemory(); if(item == NULL) { return -1; } pListEntry = &(item->itemEntry); } ++_outstandingMemory; memory = &((MemoryPoolItem*)pListEntry)->payload->memoryType; return 0; } template int32_t MemoryPoolImpl::PushMemory(MemoryType*& memory) { if(memory == NULL) { return -1; } MemoryPoolItem* item = ((MemoryPoolItemPayload*)memory)->base; const int32_t usedItems = --_outstandingMemory; const int32_t totalItems = _createdMemory.Value(); const int32_t freeItems = totalItems - usedItems; if(freeItems < 0) { assert(false); delete item->payload; AlignedFree(item); return -1; } if(freeItems >= totalItems>>1) { delete item->payload; AlignedFree(item); --_createdMemory; return 0; } InterlockedPushEntrySList(_pListHead,&(item->itemEntry)); return 0; } template bool MemoryPoolImpl::Initialize() { _pListHead = (PSLIST_HEADER)AlignedMalloc(sizeof(SLIST_HEADER), MEMORY_ALLOCATION_ALIGNMENT); if(_pListHead == NULL) { return false; } InitializeSListHead(_pListHead); return true; } template int32_t MemoryPoolImpl::Terminate() { int32_t itemsFreed = 0; PSLIST_ENTRY pListEntry = InterlockedPopEntrySList(_pListHead); while(pListEntry != NULL) { MemoryPoolItem* item = ((MemoryPoolItem*)pListEntry); delete item->payload; AlignedFree(item); --_createdMemory; itemsFreed++; pListEntry = InterlockedPopEntrySList(_pListHead); } return itemsFreed; } template MemoryPoolItem* MemoryPoolImpl::CreateMemory() { MemoryPoolItem* returnValue = (MemoryPoolItem*) AlignedMalloc(sizeof(MemoryPoolItem), MEMORY_ALLOCATION_ALIGNMENT); if(returnValue == NULL) { return NULL; } returnValue->payload = new MemoryPoolItemPayload(); if(returnValue->payload == NULL) { delete returnValue; return NULL; } returnValue->payload->base = returnValue; ++_createdMemory; return returnValue; } } // namespace webrtc #endif // WEBRTC_MODULES_AUDIO_CONFERENCE_MIXER_SOURCE_MEMORY_POOL_WINDOWS_H_