OLD | NEW |
1 /* | 1 /* |
2 * Copyright 2016 The WebRTC Project Authors. All rights reserved. | 2 * Copyright 2016 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 105 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
116 return *this; | 116 return *this; |
117 } | 117 } |
118 | 118 |
119 CopyOnWriteBuffer& operator=(CopyOnWriteBuffer&& buf) { | 119 CopyOnWriteBuffer& operator=(CopyOnWriteBuffer&& buf) { |
120 RTC_DCHECK(IsConsistent()); | 120 RTC_DCHECK(IsConsistent()); |
121 RTC_DCHECK(buf.IsConsistent()); | 121 RTC_DCHECK(buf.IsConsistent()); |
122 buffer_ = std::move(buf.buffer_); | 122 buffer_ = std::move(buf.buffer_); |
123 return *this; | 123 return *this; |
124 } | 124 } |
125 | 125 |
126 bool operator==(const CopyOnWriteBuffer& buf) const { | 126 bool operator==(const CopyOnWriteBuffer& buf) const; |
127 // Must either use the same buffer internally or have the same contents. | |
128 RTC_DCHECK(IsConsistent()); | |
129 RTC_DCHECK(buf.IsConsistent()); | |
130 return buffer_.get() == buf.buffer_.get() || | |
131 (buffer_.get() && buf.buffer_.get() && | |
132 *buffer_.get() == *buf.buffer_.get()); | |
133 } | |
134 | 127 |
135 bool operator!=(const CopyOnWriteBuffer& buf) const { | 128 bool operator!=(const CopyOnWriteBuffer& buf) const { |
136 return !(*this == buf); | 129 return !(*this == buf); |
137 } | 130 } |
138 | 131 |
139 uint8_t& operator[](size_t index) { | 132 uint8_t& operator[](size_t index) { |
140 RTC_DCHECK_LT(index, size()); | 133 RTC_DCHECK_LT(index, size()); |
141 return data()[index]; | 134 return data()[index]; |
142 } | 135 } |
143 | 136 |
(...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
206 } | 199 } |
207 | 200 |
208 void AppendData(const CopyOnWriteBuffer& buf) { | 201 void AppendData(const CopyOnWriteBuffer& buf) { |
209 AppendData(buf.data(), buf.size()); | 202 AppendData(buf.data(), buf.size()); |
210 } | 203 } |
211 | 204 |
212 // Sets the size of the buffer. If the new size is smaller than the old, the | 205 // Sets the size of the buffer. If the new size is smaller than the old, the |
213 // buffer contents will be kept but truncated; if the new size is greater, | 206 // buffer contents will be kept but truncated; if the new size is greater, |
214 // the existing contents will be kept and the new space will be | 207 // the existing contents will be kept and the new space will be |
215 // uninitialized. | 208 // uninitialized. |
216 void SetSize(size_t size) { | 209 void SetSize(size_t size); |
217 RTC_DCHECK(IsConsistent()); | |
218 if (!buffer_) { | |
219 if (size > 0) { | |
220 buffer_ = new RefCountedObject<Buffer>(size); | |
221 } | |
222 RTC_DCHECK(IsConsistent()); | |
223 return; | |
224 } | |
225 | |
226 // Clone data if referenced. | |
227 if (!buffer_->HasOneRef()) { | |
228 buffer_ = new RefCountedObject<Buffer>( | |
229 buffer_->data(), | |
230 std::min(buffer_->size(), size), | |
231 std::max(buffer_->capacity(), size)); | |
232 } | |
233 buffer_->SetSize(size); | |
234 RTC_DCHECK(IsConsistent()); | |
235 } | |
236 | 210 |
237 // Ensure that the buffer size can be increased to at least capacity without | 211 // Ensure that the buffer size can be increased to at least capacity without |
238 // further reallocation. (Of course, this operation might need to reallocate | 212 // further reallocation. (Of course, this operation might need to reallocate |
239 // the buffer.) | 213 // the buffer.) |
240 void EnsureCapacity(size_t capacity) { | 214 void EnsureCapacity(size_t capacity); |
241 RTC_DCHECK(IsConsistent()); | |
242 if (!buffer_) { | |
243 if (capacity > 0) { | |
244 buffer_ = new RefCountedObject<Buffer>(0, capacity); | |
245 } | |
246 RTC_DCHECK(IsConsistent()); | |
247 return; | |
248 } else if (capacity <= buffer_->capacity()) { | |
249 return; | |
250 } | |
251 | |
252 CloneDataIfReferenced(std::max(buffer_->capacity(), capacity)); | |
253 buffer_->EnsureCapacity(capacity); | |
254 RTC_DCHECK(IsConsistent()); | |
255 } | |
256 | 215 |
257 // Resets the buffer to zero size without altering capacity. Works even if the | 216 // Resets the buffer to zero size without altering capacity. Works even if the |
258 // buffer has been moved from. | 217 // buffer has been moved from. |
259 void Clear() { | 218 void Clear(); |
260 if (!buffer_) | |
261 return; | |
262 | |
263 if (buffer_->HasOneRef()) { | |
264 buffer_->Clear(); | |
265 } else { | |
266 buffer_ = new RefCountedObject<Buffer>(0, buffer_->capacity()); | |
267 } | |
268 RTC_DCHECK(IsConsistent()); | |
269 } | |
270 | 219 |
271 // Swaps two buffers. | 220 // Swaps two buffers. |
272 friend void swap(CopyOnWriteBuffer& a, CopyOnWriteBuffer& b) { | 221 friend void swap(CopyOnWriteBuffer& a, CopyOnWriteBuffer& b) { |
273 std::swap(a.buffer_, b.buffer_); | 222 std::swap(a.buffer_, b.buffer_); |
274 } | 223 } |
275 | 224 |
276 private: | 225 private: |
277 // Create a copy of the underlying data if it is referenced from other Buffer | 226 // Create a copy of the underlying data if it is referenced from other Buffer |
278 // objects. | 227 // objects. |
279 void CloneDataIfReferenced(size_t new_capacity) { | 228 void CloneDataIfReferenced(size_t new_capacity); |
280 if (buffer_->HasOneRef()) { | |
281 return; | |
282 } | |
283 | |
284 buffer_ = new RefCountedObject<Buffer>(buffer_->data(), buffer_->size(), | |
285 new_capacity); | |
286 RTC_DCHECK(IsConsistent()); | |
287 } | |
288 | 229 |
289 // Pre- and postcondition of all methods. | 230 // Pre- and postcondition of all methods. |
290 bool IsConsistent() const { | 231 bool IsConsistent() const { |
291 return (!buffer_ || buffer_->capacity() > 0); | 232 return (!buffer_ || buffer_->capacity() > 0); |
292 } | 233 } |
293 | 234 |
294 // buffer_ is either null, or points to an rtc::Buffer with capacity > 0. | 235 // buffer_ is either null, or points to an rtc::Buffer with capacity > 0. |
295 scoped_refptr<RefCountedObject<Buffer>> buffer_; | 236 scoped_refptr<RefCountedObject<Buffer>> buffer_; |
296 }; | 237 }; |
297 | 238 |
298 } // namespace rtc | 239 } // namespace rtc |
299 | 240 |
300 #endif // WEBRTC_BASE_COPYONWRITEBUFFER_H_ | 241 #endif // WEBRTC_BASE_COPYONWRITEBUFFER_H_ |
OLD | NEW |