Карта сайта Kansoftware
НОВОСТИУСЛУГИРЕШЕНИЯКОНТАКТЫ
Разработка программного обеспечения

More Examples

Boost , The Boost C++ Libraries BoostBook Documentation Subset , Chapter 8. Boost.Circular Buffer

Boost C++ Libraries

...one of the most highly regarded and expertly designed C++ library projects in the world. Herb Sutter and Andrei Alexandrescu, C++ Coding Standards

PrevUpHomeNext

Summing all the values in a circular buffer

Этот пример показывает несколько функций, включая суммирование всех действительных значений.

#include <boost/circular_buffer.hpp>
#include <numeric>
#include <assert.h>
int main(int /*argc*/, char* /*argv*/[])
{
   // Create a circular buffer of capacity 3.
   boost::circular_buffer<int> cb(3);
   assert(cb.capacity() == 3);
   // Check is empty.
   assert(cb.size() == 0);
   assert(cb.empty());
   // Insert some elements into the circular buffer.
   cb.push_back(1);
   cb.push_back(2);
   // Assertions to check push_backs have expected effect.
   assert(cb[0] == 1);
   assert(cb[1] == 2);
   assert(!cb.full());
   assert(cb.size() == 2);
   assert(cb.capacity() == 3);
   // Insert some other elements.
   cb.push_back(3);
   cb.push_back(4);
   // Evaluate the sum of all elements.
   int sum = std::accumulate(cb.begin(), cb.end(), 0);
   // Assertions to check state.
   assert(sum == 9);
   assert(cb[0] == 2);
   assert(cb[1] == 3);
   assert(cb[2] == 4);
   assert(*cb.begin() == 2);
   assert(cb.front() == 2);
   assert(cb.back() == 4);
   assert(cb.full());
   assert(cb.size() == 3);
   assert(cb.capacity() == 3);
   return 0;
}

circular_buffer имеет вместимость три int. Поэтому размер буфера никогда не превысит трех. std::accumulate алгоритм оценивает сумму хранимых элементов. Семантика circular_buffer может быть выведена из утверждений.

Вы можете увидеть полный пример код на circular_buffer_sum_example.cpp.

Bounded Buffer Example

Ограниченный буфер обычно используется в режиме производителя-потребителя: потоки производителей производят товары и хранят их в контейнере, а потребительские потоки удаляют эти предметы и обрабатывают их. Ограниченный буфер должен гарантировать, что

  • производители не вставляют предметы в контейнер, когда контейнер заполнен,
  • потребители не пытаются удалить предметы, когда контейнер пуст,
  • каждый произведенный продукт потребляется ровно одним потребителем.

Этот пример показывает, как circular_buffer может быть использован в качестве основного контейнера ограниченного буфера.

#include <boost/circular_buffer.hpp>
#include <boost/thread/mutex.hpp>
#include <boost/thread/condition.hpp>
#include <boost/thread/thread.hpp>
#include <boost/call_traits.hpp>
#include <boost/bind.hpp>
#include <boost/timer/timer.hpp> // for auto_cpu_timer
template <class T>
class bounded_buffer
{
public:
  typedef boost::circular_buffer<T> container_type;
  typedef typename container_type::size_type size_type;
  typedef typename container_type::value_type value_type;
  typedef typename boost::call_traits<value_type>::param_type param_type;
  explicit bounded_buffer(size_type capacity) : m_unread(0), m_container(capacity) {}
  void push_front(typename boost::call_traits<value_type>::param_type item)
  { // `param_type` represents the "best" way to pass a parameter of type `value_type` to a method.
      boost::mutex::scoped_lock lock(m_mutex);
      m_not_full.wait(lock, boost::bind(&bounded_buffer<value_type>::is_not_full, this));
      m_container.push_front(item);
      ++m_unread;
      lock.unlock();
      m_not_empty.notify_one();
  }
  void pop_back(value_type* pItem) {
      boost::mutex::scoped_lock lock(m_mutex);
      m_not_empty.wait(lock, boost::bind(&bounded_buffer<value_type>::is_not_empty, this));
      *pItem = m_container[--m_unread];
      lock.unlock();
      m_not_full.notify_one();
  }
private:
  bounded_buffer(const bounded_buffer&);              // Disabled copy constructor.
  bounded_buffer& operator = (const bounded_buffer&); // Disabled assign operator.
  bool is_not_empty() const { return m_unread > 0; }
  bool is_not_full() const { return m_unread < m_container.capacity(); }
  size_type m_unread;
  container_type m_container;
  boost::mutex m_mutex;
  boost::condition m_not_empty;
  boost::condition m_not_full;
}; //

The bounded_buffer полагается на Boost.Thread и Boost.Bind библиотеки и Boost.call_traits .

Метод push_front() называется нитью производителя, чтобы вставить новый элемент в буфер. Метод запирает мутекс и ждет, пока не появится место для нового элемента. (Мутекс разблокирован на этапе ожидания и должен быть восстановлен, когда условие выполняется.) Если в буфере есть пространство, исполнение продолжается, и метод вставляет элемент в конце circular_buffer. Затем он увеличивает количество нечитаемых предметов и разблокирует мутекс (в случае, если исключение выбрасывается до того, как мутекс будет разблокирован, мутекс автоматически разблокируется деструктором масштабируемого_блока). Наконец, метод уведомляет одну из потребительских потоков, ожидающих включения нового элемента в буфер.

Метод pop_back() называется потребительской нитью, чтобы прочитать следующий элемент из буфера. Метод блокирует мутекс и ждет, пока в буфере не появится непрочитанный элемент. Если есть по крайней мере один непрочитанный элемент, метод сокращает количество нечитаемых предметов и читает следующий пункт из circular_buffer. Затем он открывает мутекс и уведомляет одну из потоков производителя, ожидающих, что буфер освободит пространство для следующего элемента.

bounded buffer::pop_back() метод не удаляет пункт, но элемент остается в циркулярном баффере, который затем заменяет его новым (включенным производителем) когда циркуляр_buffer заполнен. Этот метод более эффективен, чем удаление элемента явно, позвонив circular_buffer::pop_back() метод circular_buffer.

Эта претензия основана на предположении о том, что присвоение (замещение) нового элемента в старый более эффективно, чем уничтожение (удаление) старого элемента и последующее строительство (вторжение) нового элемента.

Для сравнения ограниченных буферов на основе различных контейнеров компилируются и запускаются bounded_buffer_comparison.cpp. Тест должен показать ограниченный буфер на основе circular_buffer наиболее эффективен, за которым следует std::deque на основе ограниченного буфера. (В действительности результат может отличаться иногда, потому что тест всегда зависит от внешних факторов, таких как непосредственная нагрузка процессора.)

Вы можете увидеть полный тестовый код на bounded_buffer_comparison.cpp, и пример вывода

Description: Autorun "J:\Cpp\Misc\Debug\bounded_buffer_comparison.exe"
bounded_buffer<int> 5.15 s
bounded_buffer_space_optimized<int> 5.71 s
bounded_buffer_deque_based<int> 15.57 s
bounded_buffer_list_based<int> 17.33 s
bounded_buffer<std::string> 24.49 s
bounded_buffer_space_optimized<std::string> 28.33 s
bounded_buffer_deque_based<std::string> 29.45 s
bounded_buffer_list_based<std::string> 31.29 s

...


PrevUpHomeNext

Статья More Examples раздела The Boost C++ Libraries BoostBook Documentation Subset Chapter 8. Boost.Circular Buffer может быть полезна для разработчиков на c++ и boost.




Материалы статей собраны из открытых источников, владелец сайта не претендует на авторство. Там где авторство установить не удалось, материал подаётся без имени автора. В случае если Вы считаете, что Ваши права нарушены, пожалуйста, свяжитесь с владельцем сайта.



:: Главная :: Chapter 8. Boost.Circular Buffer ::


реклама


©KANSoftWare (разработка программного обеспечения, создание программ, создание интерактивных сайтов), 2007
Top.Mail.Ru

Время компиляции файла: 2024-08-30 11:47:00
2025-05-19 17:44:20/0.0098090171813965/1