OLD | NEW |
---|---|
1 /* | 1 /* |
2 * Copyright 2004 The WebRTC Project Authors. All rights reserved. | 2 * Copyright 2004 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 |
(...skipping 201 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
212 } | 212 } |
213 | 213 |
214 // The AppendData functions add data to the end of the buffer. They accept | 214 // The AppendData functions add data to the end of the buffer. They accept |
215 // the same input types as the constructors. | 215 // the same input types as the constructors. |
216 template <typename U, | 216 template <typename U, |
217 typename std::enable_if< | 217 typename std::enable_if< |
218 internal::BufferCompat<T, U>::value>::type* = nullptr> | 218 internal::BufferCompat<T, U>::value>::type* = nullptr> |
219 void AppendData(const U* data, size_t size) { | 219 void AppendData(const U* data, size_t size) { |
220 RTC_DCHECK(IsConsistent()); | 220 RTC_DCHECK(IsConsistent()); |
221 const size_t new_size = size_ + size; | 221 const size_t new_size = size_ + size; |
222 EnsureCapacity(new_size); | 222 EnsureCapacityWithHeadroom(new_size, true); |
223 static_assert(sizeof(T) == sizeof(U), ""); | 223 static_assert(sizeof(T) == sizeof(U), ""); |
224 std::memcpy(data_.get() + size_, data, size * sizeof(U)); | 224 std::memcpy(data_.get() + size_, data, size * sizeof(U)); |
225 size_ = new_size; | 225 size_ = new_size; |
226 RTC_DCHECK(IsConsistent()); | 226 RTC_DCHECK(IsConsistent()); |
227 } | 227 } |
228 | 228 |
229 template <typename U, | 229 template <typename U, |
230 size_t N, | 230 size_t N, |
231 typename std::enable_if< | 231 typename std::enable_if< |
232 internal::BufferCompat<T, U>::value>::type* = nullptr> | 232 internal::BufferCompat<T, U>::value>::type* = nullptr> |
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
265 size_ = old_size + written_elements; | 265 size_ = old_size + written_elements; |
266 RTC_DCHECK(IsConsistent()); | 266 RTC_DCHECK(IsConsistent()); |
267 return written_elements; | 267 return written_elements; |
268 } | 268 } |
269 | 269 |
270 // Sets the size of the buffer. If the new size is smaller than the old, the | 270 // Sets the size of the buffer. If the new size is smaller than the old, the |
271 // buffer contents will be kept but truncated; if the new size is greater, | 271 // buffer contents will be kept but truncated; if the new size is greater, |
272 // the existing contents will be kept and the new space will be | 272 // the existing contents will be kept and the new space will be |
273 // uninitialized. | 273 // uninitialized. |
274 void SetSize(size_t size) { | 274 void SetSize(size_t size) { |
275 EnsureCapacity(size); | 275 EnsureCapacityWithHeadroom(size, true); |
sprang_webrtc
2016/06/20 09:27:44
Do we really want with headroom here, as it's an e
kwiberg-webrtc
2016/06/20 09:51:31
It's an explicit *size* request, but the caller do
sprang_webrtc
2016/06/20 09:56:28
Acknowledged.
| |
276 size_ = size; | 276 size_ = size; |
277 } | 277 } |
278 | 278 |
279 // Ensure that the buffer size can be increased to at least capacity without | 279 // Ensure that the buffer size can be increased to at least capacity without |
280 // further reallocation. (Of course, this operation might need to reallocate | 280 // further reallocation. (Of course, this operation might need to reallocate |
281 // the buffer.) | 281 // the buffer.) |
282 void EnsureCapacity(size_t capacity) { | 282 void EnsureCapacity(size_t capacity) { |
283 RTC_DCHECK(IsConsistent()); | 283 // Don't allocate extra headroom, since the user is asking for a specific |
284 if (capacity <= capacity_) | 284 // capacity. |
285 return; | 285 EnsureCapacityWithHeadroom(capacity, false); |
286 std::unique_ptr<T[]> new_data(new T[capacity]); | |
287 std::memcpy(new_data.get(), data_.get(), size_ * sizeof(T)); | |
288 data_ = std::move(new_data); | |
289 capacity_ = capacity; | |
290 RTC_DCHECK(IsConsistent()); | |
291 } | 286 } |
292 | 287 |
293 // Resets the buffer to zero size without altering capacity. Works even if the | 288 // Resets the buffer to zero size without altering capacity. Works even if the |
294 // buffer has been moved from. | 289 // buffer has been moved from. |
295 void Clear() { | 290 void Clear() { |
296 size_ = 0; | 291 size_ = 0; |
297 RTC_DCHECK(IsConsistent()); | 292 RTC_DCHECK(IsConsistent()); |
298 } | 293 } |
299 | 294 |
300 // Swaps two buffers. Also works for buffers that have been moved from. | 295 // Swaps two buffers. Also works for buffers that have been moved from. |
301 friend void swap(BufferT& a, BufferT& b) { | 296 friend void swap(BufferT& a, BufferT& b) { |
302 using std::swap; | 297 using std::swap; |
303 swap(a.size_, b.size_); | 298 swap(a.size_, b.size_); |
304 swap(a.capacity_, b.capacity_); | 299 swap(a.capacity_, b.capacity_); |
305 swap(a.data_, b.data_); | 300 swap(a.data_, b.data_); |
306 } | 301 } |
307 | 302 |
308 private: | 303 private: |
304 void EnsureCapacityWithHeadroom(size_t capacity, bool extra_headroom) { | |
305 RTC_DCHECK(IsConsistent()); | |
306 if (capacity <= capacity_) | |
307 return; | |
308 | |
309 // If the caller asks for extra headroom, ensure that the new capacity is | |
310 // >= 1.5 times the old capacity. Any constant > 1 is sufficient to prevent | |
311 // quadratic behavior; as to why we pick 1.5 in particular, see | |
312 // https://github.com/facebook/folly/blob/master/folly/docs/FBVector.md and | |
313 // http://www.gahcep.com/cpp-internals-stl-vector-part-1/. | |
314 const size_t new_capacity = | |
315 extra_headroom ? std::max(capacity, capacity_ + capacity_ / 2) | |
316 : capacity; | |
sprang_webrtc
2016/06/20 09:27:44
This seems a little odd. If capacity > 1.5 * capac
kwiberg-webrtc
2016/06/20 09:51:31
capacity is the requested capacity. If that's >= 1
sprang_webrtc
2016/06/20 09:56:28
OK, fair enough.
| |
317 | |
318 std::unique_ptr<T[]> new_data(new T[new_capacity]); | |
319 std::memcpy(new_data.get(), data_.get(), size_ * sizeof(T)); | |
320 data_ = std::move(new_data); | |
321 capacity_ = new_capacity; | |
322 RTC_DCHECK(IsConsistent()); | |
323 } | |
324 | |
309 // Precondition for all methods except Clear and the destructor. | 325 // Precondition for all methods except Clear and the destructor. |
310 // Postcondition for all methods except move construction and move | 326 // Postcondition for all methods except move construction and move |
311 // assignment, which leave the moved-from object in a possibly inconsistent | 327 // assignment, which leave the moved-from object in a possibly inconsistent |
312 // state. | 328 // state. |
313 bool IsConsistent() const { | 329 bool IsConsistent() const { |
314 return (data_ || capacity_ == 0) && capacity_ >= size_; | 330 return (data_ || capacity_ == 0) && capacity_ >= size_; |
315 } | 331 } |
316 | 332 |
317 // Called when *this has been moved from. Conceptually it's a no-op, but we | 333 // Called when *this has been moved from. Conceptually it's a no-op, but we |
318 // can mutate the state slightly to help subsequent sanity checks catch bugs. | 334 // can mutate the state slightly to help subsequent sanity checks catch bugs. |
(...skipping 14 matching lines...) Expand all Loading... | |
333 size_t capacity_; | 349 size_t capacity_; |
334 std::unique_ptr<T[]> data_; | 350 std::unique_ptr<T[]> data_; |
335 }; | 351 }; |
336 | 352 |
337 // By far the most common sort of buffer. | 353 // By far the most common sort of buffer. |
338 using Buffer = BufferT<uint8_t>; | 354 using Buffer = BufferT<uint8_t>; |
339 | 355 |
340 } // namespace rtc | 356 } // namespace rtc |
341 | 357 |
342 #endif // WEBRTC_BASE_BUFFER_H_ | 358 #endif // WEBRTC_BASE_BUFFER_H_ |
OLD | NEW |