Множественная переменная условия, вызывающая функцию друг друга - PullRequest
1 голос
/ 18 октября 2019

Я наткнулся на учебник здесь Пример Bounding 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/progress.hpp>
   #include <boost/bind.hpp>

   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(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;
   };

Когда я пытаюсь нажать первый элемент (push_front). Функция «push_front ()» достигает условной переменной и ждет, пока не получит уведомление, как только получит уведомление, она проверит функцию «is_not_full ()» и затем продолжит работу. Но так как это первый элемент, который пытается нажать, он никогда не получит уведомление, так как функция «pop_back ()» не завершит выполнение, потому что буфер пуст.

Правильно ли я думаю? Могу ли я когда-нибудь вставить элемент в этот кусок кода?

Спасибо

1 Ответ

1 голос
/ 19 октября 2019

Когда я пытаюсь нажать первый элемент (push_front). Функция «push_front ()» достигает условной переменной и переходит в ожидание получения уведомления [...]

Это неверно. Внимательно прочитайте документацию этого API. То, что вы описываете, это поведение

template<typename L> void wait(L & lock);

, которое является номером 3 в списке открытых функций-членов. Тем не менее, вызов wait в вашем коде имеет два аргумента;Ваш код звонит

template<typename L, typename Pr> void wait(L & lock, Pr pred);

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

while ( !pred() )
    wait(lock);  // <-- This is where the thread waits for a notification

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

...