| Index: webrtc/modules/audio_mixer/source/memory_pool_win.h
|
| diff --git a/webrtc/modules/audio_mixer/source/memory_pool_win.h b/webrtc/modules/audio_mixer/source/memory_pool_win.h
|
| new file mode 100644
|
| index 0000000000000000000000000000000000000000..000e3c72b031b565ddbdbf0873912dfdeb1f8912
|
| --- /dev/null
|
| +++ b/webrtc/modules/audio_mixer/source/memory_pool_win.h
|
| @@ -0,0 +1,174 @@
|
| +/*
|
| + * 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 <assert.h>
|
| +#include <windows.h>
|
| +
|
| +#include "webrtc/system_wrappers/include/aligned_malloc.h"
|
| +#include "webrtc/system_wrappers/include/atomic32.h"
|
| +#include "webrtc/typedefs.h"
|
| +
|
| +namespace webrtc {
|
| +template <class MemoryType>
|
| +struct MemoryPoolItem;
|
| +
|
| +template <class MemoryType>
|
| +struct MemoryPoolItemPayload {
|
| + MemoryPoolItemPayload() : memoryType(), base(NULL) {}
|
| + MemoryType memoryType;
|
| + MemoryPoolItem<MemoryType>* base;
|
| +};
|
| +
|
| +template <class MemoryType>
|
| +struct MemoryPoolItem {
|
| + // Atomic single linked list entry header.
|
| + SLIST_ENTRY itemEntry;
|
| + // Atomic single linked list payload.
|
| + MemoryPoolItemPayload<MemoryType>* payload;
|
| +};
|
| +
|
| +template <class MemoryType>
|
| +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<MemoryType>* 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 <class MemoryType>
|
| +MemoryPoolImpl<MemoryType>::MemoryPoolImpl(int32_t /*initialPoolSize*/)
|
| + : _pListHead(NULL), _createdMemory(0), _outstandingMemory(0) {}
|
| +
|
| +template <class MemoryType>
|
| +MemoryPoolImpl<MemoryType>::~MemoryPoolImpl() {
|
| + Terminate();
|
| + if (_pListHead != NULL) {
|
| + AlignedFree(reinterpret_cast<void*>(_pListHead));
|
| + _pListHead = NULL;
|
| + }
|
| + // Trigger assert if there is outstanding memory.
|
| + assert(_createdMemory.Value() == 0);
|
| + assert(_outstandingMemory.Value() == 0);
|
| +}
|
| +
|
| +template <class MemoryType>
|
| +int32_t MemoryPoolImpl<MemoryType>::PopMemory(MemoryType*& memory) {
|
| + PSLIST_ENTRY pListEntry = InterlockedPopEntrySList(_pListHead);
|
| + if (pListEntry == NULL) {
|
| + MemoryPoolItem<MemoryType>* item = CreateMemory();
|
| + if (item == NULL) {
|
| + return -1;
|
| + }
|
| + pListEntry = &(item->itemEntry);
|
| + }
|
| + ++_outstandingMemory;
|
| + memory = &((MemoryPoolItem<MemoryType>*)pListEntry)->payload->memoryType;
|
| + return 0;
|
| +}
|
| +
|
| +template <class MemoryType>
|
| +int32_t MemoryPoolImpl<MemoryType>::PushMemory(MemoryType*& memory) {
|
| + if (memory == NULL) {
|
| + return -1;
|
| + }
|
| +
|
| + MemoryPoolItem<MemoryType>* item =
|
| + ((MemoryPoolItemPayload<MemoryType>*)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 <class MemoryType>
|
| +bool MemoryPoolImpl<MemoryType>::Initialize() {
|
| + _pListHead = (PSLIST_HEADER)AlignedMalloc(sizeof(SLIST_HEADER),
|
| + MEMORY_ALLOCATION_ALIGNMENT);
|
| + if (_pListHead == NULL) {
|
| + return false;
|
| + }
|
| + InitializeSListHead(_pListHead);
|
| + return true;
|
| +}
|
| +
|
| +template <class MemoryType>
|
| +int32_t MemoryPoolImpl<MemoryType>::Terminate() {
|
| + int32_t itemsFreed = 0;
|
| + PSLIST_ENTRY pListEntry = InterlockedPopEntrySList(_pListHead);
|
| + while (pListEntry != NULL) {
|
| + MemoryPoolItem<MemoryType>* item =
|
| + ((MemoryPoolItem<MemoryType>*)pListEntry);
|
| + delete item->payload;
|
| + AlignedFree(item);
|
| + --_createdMemory;
|
| + itemsFreed++;
|
| + pListEntry = InterlockedPopEntrySList(_pListHead);
|
| + }
|
| + return itemsFreed;
|
| +}
|
| +
|
| +template <class MemoryType>
|
| +MemoryPoolItem<MemoryType>* MemoryPoolImpl<MemoryType>::CreateMemory() {
|
| + MemoryPoolItem<MemoryType>* returnValue =
|
| + (MemoryPoolItem<MemoryType>*)AlignedMalloc(
|
| + sizeof(MemoryPoolItem<MemoryType>), MEMORY_ALLOCATION_ALIGNMENT);
|
| + if (returnValue == NULL) {
|
| + return NULL;
|
| + }
|
| +
|
| + returnValue->payload = new MemoryPoolItemPayload<MemoryType>();
|
| + 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_
|
|
|