• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 WEBRTC_MODULES_AUDIO_CONFERENCE_MIXER_SOURCE_MEMORY_POOL_WINDOWS_H_
12 #define WEBRTC_MODULES_AUDIO_CONFERENCE_MIXER_SOURCE_MEMORY_POOL_WINDOWS_H_
13 
14 #include <assert.h>
15 #include <windows.h>
16 
17 #include "webrtc/system_wrappers/include/aligned_malloc.h"
18 #include "webrtc/system_wrappers/include/atomic32.h"
19 #include "webrtc/typedefs.h"
20 
21 namespace webrtc {
22 template<class MemoryType> struct MemoryPoolItem;
23 
24 template<class MemoryType>
25 struct MemoryPoolItemPayload
26 {
MemoryPoolItemPayloadMemoryPoolItemPayload27     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>
MemoryPoolImpl(int32_t)74 MemoryPoolImpl<MemoryType>::MemoryPoolImpl(
75     int32_t /*initialPoolSize*/)
76     : _pListHead(NULL),
77       _createdMemory(0),
78       _outstandingMemory(0)
79 {
80 }
81 
82 template<class MemoryType>
~MemoryPoolImpl()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>
PopMemory(MemoryType * & memory)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>
PushMemory(MemoryType * & memory)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>
Initialize()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>
Terminate()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>*)pListEntry);
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>
CreateMemory()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 // WEBRTC_MODULES_AUDIO_CONFERENCE_MIXER_SOURCE_MEMORY_POOL_WINDOWS_H_
200