blob: 3ec9187492f8ee24ec9133c6609138f1f96d7bea [file] [log] [blame]
/*
* 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_