Chromium Code Reviews| 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 |