Pin Chrome's shortcut to the Win10 Start menu on install and OS upgrade.
[chromium-blink-merge.git] / net / tools / flip_server / ring_buffer.cc
blob16c278bcdefa8773188242a5e8f47cc76fb9a0e0
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.
5 #include "net/tools/flip_server/ring_buffer.h"
6 #include "base/logging.h"
8 namespace net {
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) {}
17 RingBuffer::~RingBuffer() {}
19 int RingBuffer::ReadableBytes() const { return bytes_used_; }
21 int RingBuffer::BufferSize() const { return buffer_size_; }
23 int RingBuffer::BytesFree() const { return BufferSize() - ReadableBytes(); }
25 bool RingBuffer::Empty() const { return ReadableBytes() == 0; }
27 bool RingBuffer::Full() const { return ReadableBytes() == BufferSize(); }
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;
40 while (wsize && bytes_remaining) {
41 if (wsize > bytes_remaining) {
42 wsize = bytes_remaining;
44 memcpy(wptr, bytes + bytes_written, wsize);
45 bytes_written += wsize;
46 bytes_remaining -= wsize;
47 AdvanceWritablePtr(wsize);
48 GetWritablePtr(&wptr, &wsize);
50 return bytes_written;
51 #else
52 const char* p = bytes;
54 int bytes_to_write = size;
55 int bytes_available = BytesFree();
56 if (bytes_available < bytes_to_write) {
57 bytes_to_write = bytes_available;
59 const char* end = bytes + bytes_to_write;
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;
69 bytes_used_ += bytes_to_write;
70 return bytes_to_write;
71 #endif
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_;
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_;
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_;
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_;
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;
112 while (rsize && bytes_remaining) {
113 if (rsize > bytes_remaining) {
114 rsize = bytes_remaining;
116 memcpy(bytes + bytes_read, rptr, rsize);
117 bytes_read += rsize;
118 bytes_remaining -= rsize;
119 AdvanceReadablePtr(rsize);
120 GetReadablePtr(&rptr, &rsize);
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;
130 char* end = bytes + bytes_to_read;
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;
140 this->bytes_used_ -= bytes_to_read;
141 return bytes_to_read;
142 #endif
145 void RingBuffer::Clear() {
146 bytes_used_ = 0;
147 write_idx_ = 0;
148 read_idx_ = 0;
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);
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;
180 } else {
181 Resize(ReadableBytes() + size);
184 DCHECK_LE(size, buffer_size_ - write_idx_);
185 return true;
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;
194 read_idx_ += amount_to_consume;
195 read_idx_ %= buffer_size_;
196 bytes_used_ -= amount_to_consume;
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;
207 void RingBuffer::Resize(int buffer_size) {
208 CHECK_GE(buffer_size, 0);
209 if (buffer_size == buffer_size_)
210 return;
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);
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;
229 memcpy(new_buffer + bytes_written, ptr, size);
230 bytes_written += size;
231 AdvanceReadablePtr(size);
233 buffer_.reset(new_buffer);
235 buffer_size_ = buffer_size;
236 bytes_used_ = bytes_used;
237 read_idx_ = 0;
238 write_idx_ = bytes_used_ % buffer_size_;
241 } // namespace net