blob: d7b364ab0d79a4716efac8378dddea79ab61f5b0 [file] [log] [blame]
// Copyright (c) 2014 Google Inc. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef BASE_CIRCULAR_BUFFER_SHELL_H_
#define BASE_CIRCULAR_BUFFER_SHELL_H_
#include "base/base_export.h"
#include "base/synchronization/lock.h"
namespace base {
// A thread-safe circular buffer implementation.
// TODO: Returns the size in Read(), Peek(), and Skip() as a return
// value.
class BASE_EXPORT CircularBufferShell {
public:
enum ReserveType { kDoNotReserve, kReserve };
explicit CircularBufferShell(size_t max_capacity,
ReserveType reserve_type = kDoNotReserve);
~CircularBufferShell();
// Clears out all data in the buffer, releasing any allocated memory.
// Idempotent.
void Clear();
// Reads the requested amount of data into the given buffer, writing the
// number of bytes actually read into the bytes_read paramter. If there is
// less data then requested, then the remaining data will be consumed.
void Read(void* destination, size_t length, size_t* bytes_read);
// It works the same as Read() except:
// 1. It doesn't modify the buffer in any way.
// 2. It allows the caller to specify an offset inside the buffer where the
// peek starts.
void Peek(void* destination,
size_t length,
size_t source_offset,
size_t* bytes_peeked) const;
// Advance the buffer cursor without reading any data.
void Skip(size_t length, size_t* bytes_skipped);
// Writes the given data into the circular buffer. Returns false if the buffer
// could not be expanded to hold the new data. If returning false,
// bytes_written will not be set, and the buffer will remain unchanged.
// TODO: Remove bytes_written. Because Write returns false when
// the buffer cannot hold all data, bytes_written isn't useful here unless we
// allow partial write.
bool Write(const void* source, size_t length, size_t* bytes_written);
// Returns the length of the data left in the buffer to read.
size_t GetLength() const;
// Returns the maximum capacity this circular buffer can grow to.
size_t GetMaxCapacity() const;
// Increase the max capacity to |new_max_capacity| which has to be greater
// than the previous one. The content of the class will be kept.
void IncreaseMaxCapacityTo(size_t new_max_capacity);
private:
// Ensures that there is enough capacity to write length bytes to the
// buffer. Returns false if it was unable to ensure that capacity due to an
// allocation error, or if it would surpass the configured maximum capacity.
bool EnsureCapacityToWrite_Locked(size_t length);
// Increases the capacity to the given absolute size in bytes. Returns false
// if there was an allocation error, or it would surpass the configured
// maximum capacity.
bool IncreaseCapacityTo_Locked(size_t capacity);
// Private workhorse for Read without the parameter validation or locking.
// When |destination| is NULL, it purely calculates the the bytes that would
// have been read.
// Note that the function doesn't advance the read cursor or modify the
// length. It is caller's responsibility to adjust |read_position_| and
// |length_| according to the return value, which is the actual number of
// bytes read.
void ReadUnchecked_Locked(void* destination,
size_t destination_length,
size_t source_offset,
size_t* bytes_read) const;
// The same the as above functions except that it also advance the
// |read_position_| and adjust the |length_| accordingly.
void ReadAndAdvanceUnchecked_Locked(void* destination,
size_t destination_length,
size_t* bytes_read);
// Gets a pointer to the current write position.
void* GetWritePointer_Locked() const;
// Gets the current write position.
size_t GetWritePosition_Locked() const;
size_t max_capacity_;
void* buffer_;
size_t capacity_;
size_t length_;
size_t read_position_;
mutable base::Lock lock_;
};
} // namespace base
#endif // BASE_CIRCULAR_BUFFER_SHELL_H_