OLD | NEW |
| (Empty) |
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 MODULES_AUDIO_CONFERENCE_MIXER_SOURCE_MEMORY_POOL_WINDOWS_H_ | |
12 #define MODULES_AUDIO_CONFERENCE_MIXER_SOURCE_MEMORY_POOL_WINDOWS_H_ | |
13 | |
14 #include <assert.h> | |
15 #include <windows.h> | |
16 | |
17 #include "system_wrappers/include/aligned_malloc.h" | |
18 #include "system_wrappers/include/atomic32.h" | |
19 #include "typedefs.h" // NOLINT(build/include) | |
20 | |
21 namespace webrtc { | |
22 template<class MemoryType> struct MemoryPoolItem; | |
23 | |
24 template<class MemoryType> | |
25 struct MemoryPoolItemPayload | |
26 { | |
27 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> | |
74 MemoryPoolImpl<MemoryType>::MemoryPoolImpl( | |
75 int32_t /*initialPoolSize*/) | |
76 : _pListHead(NULL), | |
77 _createdMemory(0), | |
78 _outstandingMemory(0) | |
79 { | |
80 } | |
81 | |
82 template<class MemoryType> | |
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> | |
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> | |
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> | |
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> | |
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>*)pListEn
try); | |
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> | |
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 // MODULES_AUDIO_CONFERENCE_MIXER_SOURCE_MEMORY_POOL_WINDOWS_H_ | |
OLD | NEW |