Windows should animate when they are about to get docked at screen edges.
[chromium-blink-merge.git] / net / tools / flip_server / ring_buffer.cc
blob81e9e9ee48129ecace4c4646cfa4d698b80117eb
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) {
18 RingBuffer::~RingBuffer() {}
20 ////////////////////////////////////////////////////////////////////////////////
22 int RingBuffer::ReadableBytes() const {
23 return bytes_used_;
26 ////////////////////////////////////////////////////////////////////////////////
28 int RingBuffer::BufferSize() const {
29 return buffer_size_;
32 ////////////////////////////////////////////////////////////////////////////////
34 int RingBuffer::BytesFree() const {
35 return BufferSize() - ReadableBytes();
38 ////////////////////////////////////////////////////////////////////////////////
40 bool RingBuffer::Empty() const {
41 return ReadableBytes() == 0;
44 ////////////////////////////////////////////////////////////////////////////////
46 bool RingBuffer::Full() const {
47 return ReadableBytes() == BufferSize();
50 ////////////////////////////////////////////////////////////////////////////////
52 // Returns the number of characters written.
53 // Appends up-to-'size' bytes to the ringbuffer.
54 int RingBuffer::Write(const char* bytes, int size) {
55 CHECK_GE(size, 0);
56 #if 1
57 char* wptr;
58 int wsize;
59 GetWritablePtr(&wptr, &wsize);
60 int bytes_remaining = size;
61 int bytes_written = 0;
63 while (wsize && bytes_remaining) {
64 if (wsize > bytes_remaining) {
65 wsize = bytes_remaining;
67 memcpy(wptr, bytes + bytes_written, wsize);
68 bytes_written += wsize;
69 bytes_remaining -= wsize;
70 AdvanceWritablePtr(wsize);
71 GetWritablePtr(&wptr, &wsize);
73 return bytes_written;
74 #else
75 const char* p = bytes;
77 int bytes_to_write = size;
78 int bytes_available = BytesFree();
79 if (bytes_available < bytes_to_write) {
80 bytes_to_write = bytes_available;
82 const char* end = bytes + bytes_to_write;
84 while (p != end) {
85 this->buffer_[this->write_idx_] = *p;
86 ++p;
87 ++this->write_idx_;
88 if (this->write_idx_ >= this->buffer_size_) {
89 this->write_idx_ = 0;
92 bytes_used_ += bytes_to_write;
93 return bytes_to_write;
94 #endif
97 ////////////////////////////////////////////////////////////////////////////////
99 // Sets *ptr to the beginning of writable memory, and sets *size to the size
100 // available for writing using this pointer.
101 void RingBuffer::GetWritablePtr(char** ptr, int* size) const {
102 *ptr = buffer_.get() + write_idx_;
104 if (bytes_used_ == buffer_size_) {
105 *size = 0;
106 } else if (read_idx_ > write_idx_) {
107 *size = read_idx_ - write_idx_;
108 } else {
109 *size = buffer_size_ - write_idx_;
113 ////////////////////////////////////////////////////////////////////////////////
115 // Sets *ptr to the beginning of readable memory, and sets *size to the size
116 // available for reading using this pointer.
117 void RingBuffer::GetReadablePtr(char** ptr, int* size) const {
118 *ptr = buffer_.get() + read_idx_;
120 if (bytes_used_ == 0) {
121 *size = 0;
122 } else if (write_idx_ > read_idx_) {
123 *size = write_idx_ - read_idx_;
124 } else {
125 *size = buffer_size_ - read_idx_;
129 ////////////////////////////////////////////////////////////////////////////////
131 // returns the number of bytes read into
132 int RingBuffer::Read(char* bytes, int size) {
133 CHECK_GE(size, 0);
134 #if 1
135 char* rptr;
136 int rsize;
137 GetReadablePtr(&rptr, &rsize);
138 int bytes_remaining = size;
139 int bytes_read = 0;
141 while (rsize && bytes_remaining) {
142 if (rsize > bytes_remaining) {
143 rsize = bytes_remaining;
145 memcpy(bytes + bytes_read, rptr, rsize);
146 bytes_read += rsize;
147 bytes_remaining -= rsize;
148 AdvanceReadablePtr(rsize);
149 GetReadablePtr(&rptr, &rsize);
151 return bytes_read;
152 #else
153 char* p = bytes;
154 int bytes_to_read = size;
155 int bytes_used = ReadableBytes();
156 if (bytes_used < bytes_to_read) {
157 bytes_to_read = bytes_used;
159 char* end = bytes + bytes_to_read;
161 while (p != end) {
162 *p = this->buffer_[this->read_idx_];
163 ++p;
164 ++this->read_idx_;
165 if (this->read_idx_ >= this->buffer_size_) {
166 this->read_idx_ = 0;
169 this->bytes_used_ -= bytes_to_read;
170 return bytes_to_read;
171 #endif
174 ////////////////////////////////////////////////////////////////////////////////
176 void RingBuffer::Clear() {
177 bytes_used_ = 0;
178 write_idx_ = 0;
179 read_idx_ = 0;
182 ////////////////////////////////////////////////////////////////////////////////
184 bool RingBuffer::Reserve(int size) {
185 DCHECK(size > 0);
186 char* write_ptr = NULL;
187 int write_size = 0;
188 GetWritablePtr(&write_ptr, &write_size);
190 if (write_size < size) {
191 char* read_ptr = NULL;
192 int read_size = 0;
193 GetReadablePtr(&read_ptr, &read_size);
194 if (size <= BytesFree()) {
195 // The fact that the total Free size is big enough but writable size is
196 // not means that the writeable region is broken into two pieces: only
197 // possible if the read_idx < write_idx. If write_idx < read_idx, then
198 // the writeable region must be contiguous: [write_idx, read_idx). There
199 // is no work to be done for the latter.
200 DCHECK(read_idx_ <= write_idx_);
201 DCHECK(read_size == ReadableBytes());
202 if (read_idx_ < write_idx_) {
203 // Writeable area fragmented, consolidate it.
204 memmove(buffer_.get(), read_ptr, read_size);
205 read_idx_ = 0;
206 write_idx_ = read_size;
207 } else if (read_idx_ == write_idx_) {
208 // No unconsumed data in the buffer, simply reset the indexes.
209 DCHECK(ReadableBytes() == 0);
210 read_idx_ = 0;
211 write_idx_ = 0;
213 } else {
214 Resize(ReadableBytes() + size);
217 DCHECK_LE(size, buffer_size_ - write_idx_);
218 return true;
221 ////////////////////////////////////////////////////////////////////////////////
223 void RingBuffer::AdvanceReadablePtr(int amount_to_consume) {
224 CHECK_GE(amount_to_consume, 0);
225 if (amount_to_consume >= bytes_used_) {
226 Clear();
227 return;
229 read_idx_ += amount_to_consume;
230 read_idx_ %= buffer_size_;
231 bytes_used_ -= amount_to_consume;
234 ////////////////////////////////////////////////////////////////////////////////
236 void RingBuffer::AdvanceWritablePtr(int amount_to_produce) {
237 CHECK_GE(amount_to_produce, 0);
238 CHECK_LE(amount_to_produce, BytesFree());
239 write_idx_ += amount_to_produce;
240 write_idx_ %= buffer_size_;
241 bytes_used_ += amount_to_produce;
244 ////////////////////////////////////////////////////////////////////////////////
246 void RingBuffer::Resize(int buffer_size) {
247 CHECK_GE(buffer_size, 0);
248 if (buffer_size == buffer_size_) return;
250 char* new_buffer = new char[buffer_size];
251 if (buffer_size < bytes_used_) {
252 // consume the oldest data.
253 AdvanceReadablePtr(bytes_used_ - buffer_size);
256 int bytes_written = 0;
257 int bytes_used = bytes_used_;
258 while (true) {
259 int size;
260 char* ptr;
261 GetReadablePtr(&ptr, &size);
262 if (size == 0) break;
263 if (size > buffer_size) {
264 size = buffer_size;
266 memcpy(new_buffer + bytes_written, ptr, size);
267 bytes_written += size;
268 AdvanceReadablePtr(size);
270 buffer_.reset(new_buffer);
272 buffer_size_ = buffer_size;
273 bytes_used_ = bytes_used;
274 read_idx_ = 0;
275 write_idx_ = bytes_used_ % buffer_size_;
278 } // namespace net