21 Ağustos 2017 Pazartesi

circular_buffer Sınıfı

Giriş
Şu satırı dahil ederiz.
#include <boost/circular_buffer.hpp>
Açıklaması şöyle
Circular buffer API is similar to ::std::vector API. But there is a catch. First, items stored in circular buffer must be copy assignable.
Açıklaması şöyle
It's a kind of sequence similar to std::list or std::deque. It supports random access iterators, constant time insert and erase operations at the beginning or the end of the buffer and interoperability with std algorithms.

It provides fixed capacity storage: when the buffer is filled, new data is written starting at the beginning of the buffer and overwriting the old
Açıklaması şöyle. Niçin circular_buffer bellek alanı için sürekli değil ifadesi kullanılmış bilmiyorum.
Each receive buffer must be contiguous when using asio.

Since boost::circular_buffer is not contiguous it is rather inconvenient to use as a byte buffer. Still, though, you can present it to asio as 2 buffers with scatter-gather I/O.

Bu sınıfa benzer circular_buffer_space_optimized isimli bir sınıf daha var. Farkını bilmiyorum.

constructor - default
Eğer kapasite vermezsek push_back çalışmaz.
boost::circular_buffer<bool> cb;
cb.push_back(false);
cb.push_back(true);
cout << cb.size() << endl; // prints 0
Açıklaması şöyle
Now the constructor does not allocate any memory and both capacity and size are set to zero. Also note when inserting an element into a circular_buffer with zero capacity (e.g. by push_back(const_reference) or insert(iterator, value_type)) nothing will be inserted and the size (as well as capacity) remains zero.
constructor - capacity
Şöyle yaparız.
size_t const BUFFER_CAPACITY(1024); // Whatever is appropriate
boost::circular_buffer<bool> cb (BUFFER_CAPACITY);
constructor - capacity + allocator
Şöyle yaparız.
bip::managed_mapped_file mmf(bip::open_or_create, "./circ_buffer.bin", 4ul << 10);
typedef bip::allocator<message, bip::managed_mapped_file::segment_manager> allocator;
typedef boost::circular_buffer<message, allocator> circ_buf;

auto& instance = *mmf.find_or_construct<circ_buf>("named_buffer")(10, 
  mmf.get_segment_manager());
constructor - capacity + size + reference item
İmzası şöyle
circular_buffer(capacity_type buffer_capacity, size_type n,
  const_reference item, const allocator_type& alloc = allocator_type());
Örnek
Şöyle yaparız. 10 kapasitelik ve 10 tane belirtilen nesneden kopyalanmış dolu bir yapı elde ederiz.
int num_elements = 10;
Custom<T> custom;
boost::circular_buffer<Custom<T>> buffer(num_elements, num_elements, custom);
Şöyle yaparız. 10 kapasitelik ve 5 tane belirtilen nesneden kopyalanmış yarı dolu bir yapı elde ederiz.
boost::circular_buffer<Custom<T>> buffer(num_elements, num_elements/2, custom);
constructor - initializer_list
Henüz böyle bir constructor yok ancak yazması çok kolay. Şöyle yaparız.
template<typename T>
circular_buffer<T> make_circular_buffer (const std::initializer_list<T>& init)
{
  return circular_buffer<T> (init.begin(), init.end());
}

auto b = make_circular_buffer ({1,2,3,4});
back metodu
Örnek
Şöyle yaparız.
assert(cb.back() == 4);
Örnek
Şöyle yaparız.
using mybuffer = ::std::array< unsigned char, 10 >;

::boost::circular_buffer< mybuffer > cb (10);
cb.push_back();
auto & api_data_buffer{cb.back()};
begin ve end metodları
Örnek 1
Şöyle yaparız.
typedef typename circular_buffer<Foo>::iterator MyIterator;

MyIterator iter =
  std::upper_bound (cb.begin(), cb.end(), Foo{3},
    [](const Foo& a, const Foo& b) { return a.foo < b.foo; });
Örnek 2
Şöyle yaparız.
// evaluate the sum
int sum = std::accumulate(cb.begin(), cb.end(), 0);
capacity metodu
Şöyle yaparız.
assert(cb.capacity() == 3);
erase metodu
Şöyle yaparız.
unsigned int n = ...;
cb.erase (cb.begin(), cb.begin() + n); 
front metodu
Şöyle yaparız.
assert(cb.front() == 2);
full metodu
Şöyle yaparız.
assert(!cb.full());
linearize metodu
Şöyle yaparız.
auto cb_ptr = cb.linearize();
assert (cb_ptr);
Circular buffer içindeki veriyi std::copy ile başka bir yere kopyalamak için kullanıırız.

operator [] metodu
Şöyle yaparız.
// create a circular buffer of capacity 3
boost::circular_buffer<int> cb(3);

// insert some elements into the circular buffer
cb.push_back(1);
cb.push_back(2);

// assertions
assert(cb[0] == 1);
assert(cb[1] == 2);
pop_back metodu
Şöyle yaparız.
// Create a circular buffer with a capacity for 5 integers.
boost::circular_buffer<int> cb(5);

// Insert elements into the buffer.
cb.push_back(3);
cb.push_back(24);
cb.push_back(51);
cb.push_back(62);
cb.push_back(37);

int a = cb[0];  // a == 3
int b = cb[1];  // b == 24
int c = cb[2];  // c == 51

// The buffer is full now, so pushing subsequent
// elements will overwrite the front-most elements.
cb.push_back(8);   // overwrite 3 with 8
cb.push_back(12);  // overwrite 24 with 12

// The buffer now contains 51, 62, 37, 8, 12.

// Elements can be popped from either the front or the back.
cb.pop_back();  // 12 is removed
cb.pop_front(); // 51 is removed
pop_front metodu
Şöyle yaparız.
cb.pop_front(); // 51 is removed
push_back metodu
Örnek
Şöyle yaparız.
// create a circular buffer of capacity 3
boost::circular_buffer<int> cb(3);

// insert some elements into the circular buffer
cb.push_back(1);
cb.push_back(2);
Örnek
Eğer veriyapısı dolduysa baştaki elemanlar yok edilir. Elimizde loglama yapan bir sınıf olsun
struct MyObject {
  MyObject(int i) : _i(i) { std::cout << __FUNCTION__ << " _i=" << _i << "\n"; }
  ~MyObject()              { std::cout << __FUNCTION__ << " _i=" << _i << "\n"; }
  int _i;
};
5 tane ekleyerek veriyapısını dolduralım. Sonra fazladan 1 tane ekleyelim. En baştaki eleman silinir
using Ptr = std::unique_ptr<MyObject>;
boost::circular_buffer<Ptr> cBuf(5);
cb.push_back(std::make_unique<MyObject>(0)); // cBuf[0]
cb.push_back(std::make_unique<MyObject>(1)); // cBuf[1]
cb.push_back(std::make_unique<MyObject>(2)); // cBuf[2]
cb.push_back(std::make_unique<MyObject>(3)); // cBuf[3]
cb.push_back(std::make_unique<MyObject>(4)); // cBuf[4]

std::cout << "Full, pushing extra\n";

cb.push_back(std::make_unique<MyObject>(5)); // this will overwrite position 0

std::cout << "Done\n";
Çıktı olarak şunu alırız.
MyObject::MyObject _i=0
MyObject::MyObject _i=1
MyObject::MyObject _i=2
MyObject::MyObject _i=3
MyObject::MyObject _i=4
Full, pushing extra
MyObject::MyObject _i=5
MyObject::~MyObject _i=0
Done
MyObject::~MyObject _i=1
MyObject::~MyObject _i=2
MyObject::~MyObject _i=3
MyObject::~MyObject _i=4
MyObject::~MyObject _i=5
resize metodu
Şöyle yaparız.
int size = ...;
cb.resize (size);
set_capacity metodu
Şöyle yaparız.
boost::circular_buffer<bool> cb;
// ...

size_t BUFFER_SIZE(1024); // Whatever is appropriate
cb.set_capacity (BUFFER_CAPACITY);
size metodu
Şöyle yaparız.
unsigned int n = cb.size()

Hiç yorum yok:

Yorum Gönder