OLD | NEW |
1 /* | 1 /* |
2 * Copyright (c) 2012 The WebRTC project authors. All Rights Reserved. | 2 * Copyright (c) 2012 The WebRTC project authors. All Rights Reserved. |
3 * | 3 * |
4 * Use of this source code is governed by a BSD-style license | 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 | 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 | 6 * tree. An additional intellectual property rights grant can be found |
7 * in the file PATENTS. All contributing project authors may | 7 * in the file PATENTS. All contributing project authors may |
8 * be found in the AUTHORS file in the root of the source tree. | 8 * be found in the AUTHORS file in the root of the source tree. |
9 */ | 9 */ |
10 | 10 |
11 #ifndef WEBRTC_MODULES_AUDIO_CONFERENCE_MIXER_SOURCE_MEMORY_POOL_WINDOWS_H_ | 11 #ifndef WEBRTC_MODULES_AUDIO_CONFERENCE_MIXER_SOURCE_MEMORY_POOL_WINDOWS_H_ |
12 #define WEBRTC_MODULES_AUDIO_CONFERENCE_MIXER_SOURCE_MEMORY_POOL_WINDOWS_H_ | 12 #define WEBRTC_MODULES_AUDIO_CONFERENCE_MIXER_SOURCE_MEMORY_POOL_WINDOWS_H_ |
13 | 13 |
14 #include <assert.h> | 14 #include <assert.h> |
15 #include <windows.h> | 15 #include <windows.h> |
16 | 16 |
| 17 #include "webrtc/base/atomicops.h" |
17 #include "webrtc/system_wrappers/interface/aligned_malloc.h" | 18 #include "webrtc/system_wrappers/interface/aligned_malloc.h" |
18 #include "webrtc/system_wrappers/interface/atomic32.h" | |
19 #include "webrtc/typedefs.h" | 19 #include "webrtc/typedefs.h" |
20 | 20 |
21 namespace webrtc { | 21 namespace webrtc { |
22 template<class MemoryType> struct MemoryPoolItem; | 22 template<class MemoryType> struct MemoryPoolItem; |
23 | 23 |
24 template<class MemoryType> | 24 template<class MemoryType> |
25 struct MemoryPoolItemPayload | 25 struct MemoryPoolItemPayload |
26 { | 26 { |
27 MemoryPoolItemPayload() | 27 MemoryPoolItemPayload() |
28 : memoryType(), | 28 : memoryType(), |
(...skipping 30 matching lines...) Expand all Loading... |
59 private: | 59 private: |
60 // Non-atomic function. | 60 // Non-atomic function. |
61 MemoryPoolItem<MemoryType>* CreateMemory(); | 61 MemoryPoolItem<MemoryType>* CreateMemory(); |
62 | 62 |
63 // Windows implementation of single linked atomic list, documented here: | 63 // Windows implementation of single linked atomic list, documented here: |
64 // http://msdn.microsoft.com/en-us/library/ms686962(VS.85).aspx | 64 // http://msdn.microsoft.com/en-us/library/ms686962(VS.85).aspx |
65 | 65 |
66 // Atomic single linked list head. | 66 // Atomic single linked list head. |
67 PSLIST_HEADER _pListHead; | 67 PSLIST_HEADER _pListHead; |
68 | 68 |
69 Atomic32 _createdMemory; | 69 volatile int _createdMemory; |
70 Atomic32 _outstandingMemory; | 70 volatile int _outstandingMemory; |
71 }; | 71 }; |
72 | 72 |
73 template<class MemoryType> | 73 template<class MemoryType> |
74 MemoryPoolImpl<MemoryType>::MemoryPoolImpl( | 74 MemoryPoolImpl<MemoryType>::MemoryPoolImpl( |
75 int32_t /*initialPoolSize*/) | 75 int32_t /*initialPoolSize*/) |
76 : _pListHead(NULL), | 76 : _pListHead(NULL), |
77 _createdMemory(0), | 77 _createdMemory(0), |
78 _outstandingMemory(0) | 78 _outstandingMemory(0) |
79 { | 79 { |
80 } | 80 } |
81 | 81 |
82 template<class MemoryType> | 82 template<class MemoryType> |
83 MemoryPoolImpl<MemoryType>::~MemoryPoolImpl() | 83 MemoryPoolImpl<MemoryType>::~MemoryPoolImpl() |
84 { | 84 { |
85 Terminate(); | 85 Terminate(); |
86 if(_pListHead != NULL) | 86 if(_pListHead != NULL) |
87 { | 87 { |
88 AlignedFree(reinterpret_cast<void*>(_pListHead)); | 88 AlignedFree(reinterpret_cast<void*>(_pListHead)); |
89 _pListHead = NULL; | 89 _pListHead = NULL; |
90 } | 90 } |
91 // Trigger assert if there is outstanding memory. | 91 // Trigger assert if there is outstanding memory. |
92 assert(_createdMemory.Value() == 0); | 92 assert(rtc::AtomicOps::AcquireLoad(&_createdMemory) == 0); |
93 assert(_outstandingMemory.Value() == 0); | 93 assert(rtc::AtomicOps::AcquireLoad(&_outstandingMemory) == 0); |
94 } | 94 } |
95 | 95 |
96 template<class MemoryType> | 96 template<class MemoryType> |
97 int32_t MemoryPoolImpl<MemoryType>::PopMemory(MemoryType*& memory) | 97 int32_t MemoryPoolImpl<MemoryType>::PopMemory(MemoryType*& memory) |
98 { | 98 { |
99 PSLIST_ENTRY pListEntry = InterlockedPopEntrySList(_pListHead); | 99 PSLIST_ENTRY pListEntry = InterlockedPopEntrySList(_pListHead); |
100 if(pListEntry == NULL) | 100 if(pListEntry == NULL) |
101 { | 101 { |
102 MemoryPoolItem<MemoryType>* item = CreateMemory(); | 102 MemoryPoolItem<MemoryType>* item = CreateMemory(); |
103 if(item == NULL) | 103 if(item == NULL) |
104 { | 104 { |
105 return -1; | 105 return -1; |
106 } | 106 } |
107 pListEntry = &(item->itemEntry); | 107 pListEntry = &(item->itemEntry); |
108 } | 108 } |
109 ++_outstandingMemory; | 109 rtc::AtomicOps::Increment(&_outstandingMemory); |
110 memory = &((MemoryPoolItem<MemoryType>*)pListEntry)->payload->memoryType; | 110 memory = &((MemoryPoolItem<MemoryType>*)pListEntry)->payload->memoryType; |
111 return 0; | 111 return 0; |
112 } | 112 } |
113 | 113 |
114 template<class MemoryType> | 114 template<class MemoryType> |
115 int32_t MemoryPoolImpl<MemoryType>::PushMemory(MemoryType*& memory) | 115 int32_t MemoryPoolImpl<MemoryType>::PushMemory(MemoryType*& memory) |
116 { | 116 { |
117 if(memory == NULL) | 117 if(memory == NULL) |
118 { | 118 { |
119 return -1; | 119 return -1; |
120 } | 120 } |
121 | 121 |
122 MemoryPoolItem<MemoryType>* item = | 122 MemoryPoolItem<MemoryType>* item = |
123 ((MemoryPoolItemPayload<MemoryType>*)memory)->base; | 123 ((MemoryPoolItemPayload<MemoryType>*)memory)->base; |
124 | 124 |
125 const int32_t usedItems = --_outstandingMemory; | 125 const int32_t usedItems = rtc::AtomicOps::Decrement(&_outstandingMemory); |
126 const int32_t totalItems = _createdMemory.Value(); | 126 const int32_t totalItems = rtc::AtomicOps::AcquireLoad(&_createdMemory); |
127 const int32_t freeItems = totalItems - usedItems; | 127 const int32_t freeItems = totalItems - usedItems; |
128 if(freeItems < 0) | 128 if(freeItems < 0) |
129 { | 129 { |
130 assert(false); | 130 assert(false); |
131 delete item->payload; | 131 delete item->payload; |
132 AlignedFree(item); | 132 AlignedFree(item); |
133 return -1; | 133 return -1; |
134 } | 134 } |
135 if(freeItems >= totalItems>>1) | 135 if(freeItems >= totalItems>>1) |
136 { | 136 { |
137 delete item->payload; | 137 delete item->payload; |
138 AlignedFree(item); | 138 AlignedFree(item); |
139 --_createdMemory; | 139 rtc::AtomicOps::Decrement(&_createdMemory); |
140 return 0; | 140 return 0; |
141 } | 141 } |
142 InterlockedPushEntrySList(_pListHead,&(item->itemEntry)); | 142 InterlockedPushEntrySList(_pListHead,&(item->itemEntry)); |
143 return 0; | 143 return 0; |
144 } | 144 } |
145 | 145 |
146 template<class MemoryType> | 146 template<class MemoryType> |
147 bool MemoryPoolImpl<MemoryType>::Initialize() | 147 bool MemoryPoolImpl<MemoryType>::Initialize() |
148 { | 148 { |
149 _pListHead = (PSLIST_HEADER)AlignedMalloc(sizeof(SLIST_HEADER), | 149 _pListHead = (PSLIST_HEADER)AlignedMalloc(sizeof(SLIST_HEADER), |
150 MEMORY_ALLOCATION_ALIGNMENT); | 150 MEMORY_ALLOCATION_ALIGNMENT); |
151 if(_pListHead == NULL) | 151 if(_pListHead == NULL) |
152 { | 152 { |
153 return false; | 153 return false; |
154 } | 154 } |
155 InitializeSListHead(_pListHead); | 155 InitializeSListHead(_pListHead); |
156 return true; | 156 return true; |
157 } | 157 } |
158 | 158 |
159 template<class MemoryType> | 159 template<class MemoryType> |
160 int32_t MemoryPoolImpl<MemoryType>::Terminate() | 160 int32_t MemoryPoolImpl<MemoryType>::Terminate() |
161 { | 161 { |
162 int32_t itemsFreed = 0; | 162 int32_t itemsFreed = 0; |
163 PSLIST_ENTRY pListEntry = InterlockedPopEntrySList(_pListHead); | 163 PSLIST_ENTRY pListEntry = InterlockedPopEntrySList(_pListHead); |
164 while(pListEntry != NULL) | 164 while(pListEntry != NULL) |
165 { | 165 { |
166 MemoryPoolItem<MemoryType>* item = ((MemoryPoolItem<MemoryType>*)pListEn
try); | 166 MemoryPoolItem<MemoryType>* item = ((MemoryPoolItem<MemoryType>*)pListEn
try); |
167 delete item->payload; | 167 delete item->payload; |
168 AlignedFree(item); | 168 AlignedFree(item); |
169 --_createdMemory; | 169 rtc::AtomicOps::Decrement(&_createdMemory); |
170 itemsFreed++; | 170 itemsFreed++; |
171 pListEntry = InterlockedPopEntrySList(_pListHead); | 171 pListEntry = InterlockedPopEntrySList(_pListHead); |
172 } | 172 } |
173 return itemsFreed; | 173 return itemsFreed; |
174 } | 174 } |
175 | 175 |
176 template<class MemoryType> | 176 template<class MemoryType> |
177 MemoryPoolItem<MemoryType>* MemoryPoolImpl<MemoryType>::CreateMemory() | 177 MemoryPoolItem<MemoryType>* MemoryPoolImpl<MemoryType>::CreateMemory() |
178 { | 178 { |
179 MemoryPoolItem<MemoryType>* returnValue = (MemoryPoolItem<MemoryType>*) | 179 MemoryPoolItem<MemoryType>* returnValue = (MemoryPoolItem<MemoryType>*) |
180 AlignedMalloc(sizeof(MemoryPoolItem<MemoryType>), | 180 AlignedMalloc(sizeof(MemoryPoolItem<MemoryType>), |
181 MEMORY_ALLOCATION_ALIGNMENT); | 181 MEMORY_ALLOCATION_ALIGNMENT); |
182 if(returnValue == NULL) | 182 if(returnValue == NULL) |
183 { | 183 { |
184 return NULL; | 184 return NULL; |
185 } | 185 } |
186 | 186 |
187 returnValue->payload = new MemoryPoolItemPayload<MemoryType>(); | 187 returnValue->payload = new MemoryPoolItemPayload<MemoryType>(); |
188 if(returnValue->payload == NULL) | 188 if(returnValue->payload == NULL) |
189 { | 189 { |
190 delete returnValue; | 190 delete returnValue; |
191 return NULL; | 191 return NULL; |
192 } | 192 } |
193 returnValue->payload->base = returnValue; | 193 returnValue->payload->base = returnValue; |
194 ++_createdMemory; | 194 rtc::AtomicOps::Increment(&_createdMemory); |
195 return returnValue; | 195 return returnValue; |
196 } | 196 } |
197 } // namespace webrtc | 197 } // namespace webrtc |
198 | 198 |
199 #endif // WEBRTC_MODULES_AUDIO_CONFERENCE_MIXER_SOURCE_MEMORY_POOL_WINDOWS_H_ | 199 #endif // WEBRTC_MODULES_AUDIO_CONFERENCE_MIXER_SOURCE_MEMORY_POOL_WINDOWS_H_ |
OLD | NEW |