| OLD | NEW |
| (Empty) |
| 1 // Copyright (c) 2009 The Chromium Authors. All rights reserved. | |
| 2 // Use of this source code is governed by a BSD-style license that can be | |
| 3 // found in the LICENSE file. | |
| 4 | |
| 5 #include "net/tools/flip_server/ring_buffer.h" | |
| 6 #include "base/logging.h" | |
| 7 | |
| 8 namespace net { | |
| 9 | |
| 10 RingBuffer::RingBuffer(int buffer_size) | |
| 11 : buffer_(new char[buffer_size]), | |
| 12 buffer_size_(buffer_size), | |
| 13 bytes_used_(0), | |
| 14 read_idx_(0), | |
| 15 write_idx_(0) {} | |
| 16 | |
| 17 RingBuffer::~RingBuffer() {} | |
| 18 | |
| 19 int RingBuffer::ReadableBytes() const { return bytes_used_; } | |
| 20 | |
| 21 int RingBuffer::BufferSize() const { return buffer_size_; } | |
| 22 | |
| 23 int RingBuffer::BytesFree() const { return BufferSize() - ReadableBytes(); } | |
| 24 | |
| 25 bool RingBuffer::Empty() const { return ReadableBytes() == 0; } | |
| 26 | |
| 27 bool RingBuffer::Full() const { return ReadableBytes() == BufferSize(); } | |
| 28 | |
| 29 // Returns the number of characters written. | |
| 30 // Appends up-to-'size' bytes to the ringbuffer. | |
| 31 int RingBuffer::Write(const char* bytes, int size) { | |
| 32 CHECK_GE(size, 0); | |
| 33 #if 1 | |
| 34 char* wptr; | |
| 35 int wsize; | |
| 36 GetWritablePtr(&wptr, &wsize); | |
| 37 int bytes_remaining = size; | |
| 38 int bytes_written = 0; | |
| 39 | |
| 40 while (wsize && bytes_remaining) { | |
| 41 if (wsize > bytes_remaining) { | |
| 42 wsize = bytes_remaining; | |
| 43 } | |
| 44 memcpy(wptr, bytes + bytes_written, wsize); | |
| 45 bytes_written += wsize; | |
| 46 bytes_remaining -= wsize; | |
| 47 AdvanceWritablePtr(wsize); | |
| 48 GetWritablePtr(&wptr, &wsize); | |
| 49 } | |
| 50 return bytes_written; | |
| 51 #else | |
| 52 const char* p = bytes; | |
| 53 | |
| 54 int bytes_to_write = size; | |
| 55 int bytes_available = BytesFree(); | |
| 56 if (bytes_available < bytes_to_write) { | |
| 57 bytes_to_write = bytes_available; | |
| 58 } | |
| 59 const char* end = bytes + bytes_to_write; | |
| 60 | |
| 61 while (p != end) { | |
| 62 this->buffer_[this->write_idx_] = *p; | |
| 63 ++p; | |
| 64 ++this->write_idx_; | |
| 65 if (this->write_idx_ >= this->buffer_size_) { | |
| 66 this->write_idx_ = 0; | |
| 67 } | |
| 68 } | |
| 69 bytes_used_ += bytes_to_write; | |
| 70 return bytes_to_write; | |
| 71 #endif | |
| 72 } | |
| 73 | |
| 74 // Sets *ptr to the beginning of writable memory, and sets *size to the size | |
| 75 // available for writing using this pointer. | |
| 76 void RingBuffer::GetWritablePtr(char** ptr, int* size) const { | |
| 77 *ptr = buffer_.get() + write_idx_; | |
| 78 | |
| 79 if (bytes_used_ == buffer_size_) { | |
| 80 *size = 0; | |
| 81 } else if (read_idx_ > write_idx_) { | |
| 82 *size = read_idx_ - write_idx_; | |
| 83 } else { | |
| 84 *size = buffer_size_ - write_idx_; | |
| 85 } | |
| 86 } | |
| 87 | |
| 88 // Sets *ptr to the beginning of readable memory, and sets *size to the size | |
| 89 // available for reading using this pointer. | |
| 90 void RingBuffer::GetReadablePtr(char** ptr, int* size) const { | |
| 91 *ptr = buffer_.get() + read_idx_; | |
| 92 | |
| 93 if (bytes_used_ == 0) { | |
| 94 *size = 0; | |
| 95 } else if (write_idx_ > read_idx_) { | |
| 96 *size = write_idx_ - read_idx_; | |
| 97 } else { | |
| 98 *size = buffer_size_ - read_idx_; | |
| 99 } | |
| 100 } | |
| 101 | |
| 102 // returns the number of bytes read into | |
| 103 int RingBuffer::Read(char* bytes, int size) { | |
| 104 CHECK_GE(size, 0); | |
| 105 #if 1 | |
| 106 char* rptr; | |
| 107 int rsize; | |
| 108 GetReadablePtr(&rptr, &rsize); | |
| 109 int bytes_remaining = size; | |
| 110 int bytes_read = 0; | |
| 111 | |
| 112 while (rsize && bytes_remaining) { | |
| 113 if (rsize > bytes_remaining) { | |
| 114 rsize = bytes_remaining; | |
| 115 } | |
| 116 memcpy(bytes + bytes_read, rptr, rsize); | |
| 117 bytes_read += rsize; | |
| 118 bytes_remaining -= rsize; | |
| 119 AdvanceReadablePtr(rsize); | |
| 120 GetReadablePtr(&rptr, &rsize); | |
| 121 } | |
| 122 return bytes_read; | |
| 123 #else | |
| 124 char* p = bytes; | |
| 125 int bytes_to_read = size; | |
| 126 int bytes_used = ReadableBytes(); | |
| 127 if (bytes_used < bytes_to_read) { | |
| 128 bytes_to_read = bytes_used; | |
| 129 } | |
| 130 char* end = bytes + bytes_to_read; | |
| 131 | |
| 132 while (p != end) { | |
| 133 *p = this->buffer_[this->read_idx_]; | |
| 134 ++p; | |
| 135 ++this->read_idx_; | |
| 136 if (this->read_idx_ >= this->buffer_size_) { | |
| 137 this->read_idx_ = 0; | |
| 138 } | |
| 139 } | |
| 140 this->bytes_used_ -= bytes_to_read; | |
| 141 return bytes_to_read; | |
| 142 #endif | |
| 143 } | |
| 144 | |
| 145 void RingBuffer::Clear() { | |
| 146 bytes_used_ = 0; | |
| 147 write_idx_ = 0; | |
| 148 read_idx_ = 0; | |
| 149 } | |
| 150 | |
| 151 bool RingBuffer::Reserve(int size) { | |
| 152 DCHECK_GT(size, 0); | |
| 153 char* write_ptr = NULL; | |
| 154 int write_size = 0; | |
| 155 GetWritablePtr(&write_ptr, &write_size); | |
| 156 | |
| 157 if (write_size < size) { | |
| 158 char* read_ptr = NULL; | |
| 159 int read_size = 0; | |
| 160 GetReadablePtr(&read_ptr, &read_size); | |
| 161 if (size <= BytesFree()) { | |
| 162 // The fact that the total Free size is big enough but writable size is | |
| 163 // not means that the writeable region is broken into two pieces: only | |
| 164 // possible if the read_idx < write_idx. If write_idx < read_idx, then | |
| 165 // the writeable region must be contiguous: [write_idx, read_idx). There | |
| 166 // is no work to be done for the latter. | |
| 167 DCHECK_LE(read_idx_, write_idx_); | |
| 168 DCHECK_EQ(read_size, ReadableBytes()); | |
| 169 if (read_idx_ < write_idx_) { | |
| 170 // Writeable area fragmented, consolidate it. | |
| 171 memmove(buffer_.get(), read_ptr, read_size); | |
| 172 read_idx_ = 0; | |
| 173 write_idx_ = read_size; | |
| 174 } else if (read_idx_ == write_idx_) { | |
| 175 // No unconsumed data in the buffer, simply reset the indexes. | |
| 176 DCHECK_EQ(ReadableBytes(), 0); | |
| 177 read_idx_ = 0; | |
| 178 write_idx_ = 0; | |
| 179 } | |
| 180 } else { | |
| 181 Resize(ReadableBytes() + size); | |
| 182 } | |
| 183 } | |
| 184 DCHECK_LE(size, buffer_size_ - write_idx_); | |
| 185 return true; | |
| 186 } | |
| 187 | |
| 188 void RingBuffer::AdvanceReadablePtr(int amount_to_consume) { | |
| 189 CHECK_GE(amount_to_consume, 0); | |
| 190 if (amount_to_consume >= bytes_used_) { | |
| 191 Clear(); | |
| 192 return; | |
| 193 } | |
| 194 read_idx_ += amount_to_consume; | |
| 195 read_idx_ %= buffer_size_; | |
| 196 bytes_used_ -= amount_to_consume; | |
| 197 } | |
| 198 | |
| 199 void RingBuffer::AdvanceWritablePtr(int amount_to_produce) { | |
| 200 CHECK_GE(amount_to_produce, 0); | |
| 201 CHECK_LE(amount_to_produce, BytesFree()); | |
| 202 write_idx_ += amount_to_produce; | |
| 203 write_idx_ %= buffer_size_; | |
| 204 bytes_used_ += amount_to_produce; | |
| 205 } | |
| 206 | |
| 207 void RingBuffer::Resize(int buffer_size) { | |
| 208 CHECK_GE(buffer_size, 0); | |
| 209 if (buffer_size == buffer_size_) | |
| 210 return; | |
| 211 | |
| 212 char* new_buffer = new char[buffer_size]; | |
| 213 if (buffer_size < bytes_used_) { | |
| 214 // consume the oldest data. | |
| 215 AdvanceReadablePtr(bytes_used_ - buffer_size); | |
| 216 } | |
| 217 | |
| 218 int bytes_written = 0; | |
| 219 int bytes_used = bytes_used_; | |
| 220 while (true) { | |
| 221 int size; | |
| 222 char* ptr; | |
| 223 GetReadablePtr(&ptr, &size); | |
| 224 if (size == 0) | |
| 225 break; | |
| 226 if (size > buffer_size) { | |
| 227 size = buffer_size; | |
| 228 } | |
| 229 memcpy(new_buffer + bytes_written, ptr, size); | |
| 230 bytes_written += size; | |
| 231 AdvanceReadablePtr(size); | |
| 232 } | |
| 233 buffer_.reset(new_buffer); | |
| 234 | |
| 235 buffer_size_ = buffer_size; | |
| 236 bytes_used_ = bytes_used; | |
| 237 read_idx_ = 0; | |
| 238 write_idx_ = bytes_used_ % buffer_size_; | |
| 239 } | |
| 240 | |
| 241 } // namespace net | |
| OLD | NEW |