Потокобезопасный, не содержащий данных, совместно используемый контейнер без задержек (round_buffer)

Я сталкиваюсь со следующей ситуацией (которую я должен признать, что я слишком новичок, чтобы доверять себе в решении в одиночку …): у меня есть поток A, который иногда создает новые объекты cv :: Mat для потока B. Мне нужен потокобезопасный контейнер C (в этом случае boost :: round_buffer), в котором будут храниться объекты cv :: Mat, генерируемые потоком A. Затем поток B должен постоянно перебирать все элементы в C, чтобы создать анимацию. Поэтому мне нужен потокобезопасный C, который будет запрещать гонки данных, но также не будет вызывать (в идеале) или очень маленькое (если не возможно иначе) отставание анимации потока B -> Я хочу, чтобы поток B зависал, когда поток A обновляет C. Лучшее, что я мог придумать, это:

#include <boost/circular_buffer.hpp>
#include <opencv2/core.hpp>
#include <boost/core/noncopyable.hpp>
#include <memory>
#include <type_traits>
#include <algorithm>

using im_buf = boost::circular_buffer<cv::Mat>;
class ImageBuffer : private boost::noncopyable {
private:
im_buf buffer;
std::mutex mtx;
std::unique_lock<std::mutex> lock;
public:
// operator<< accepting cv::Mat, cv::Mat& and cv::Mat&&
template <class T,
class = typename std::enable_if
<std::is_same<cv::Mat, typename std::decay<T>::type>
::value>::type>
void operator<<(T&& mat) {
lock.lock();
buffer.push_back(std::forward<T>(mat));
lock.unlock();
}
template <typename Func> // excpect callable objects only
inline void iterate(Func func) {
lock.lock();
std::for_each(buffer.begin(),buffer.end(),func);
lock.unlock();
}
inline ImageBuffer():
buffer {settings::max_images_in_loop},
mtx {},
lock {mtx} {}
~ImageBuffer()=default;
ImageBuffer(const ImageBuffer&&)=delete;
ImageBuffer& operator=(const ImageBuffer&&)=delete;
};

(Обратите внимание, что даже если это не инвариант, поток B не предполагает мутировать C или любое его содержимое (я хотел бы использовать const_iterator здесь, но boost :: round_buffer не предоставляет один ..)

Тем не менее, с этим потоком кода B будет на некоторое время останавливать всю анимацию каждый раз, когда поток A добавляет новые элементы … так,
а. разве нет лучшего подхода?
б. действительно ли реализация действительно потокобезопасна?

0

Решение

Если у вас проблема с анимацией, вы беспокоитесь не о том, что нужно. Мьютексы хороши для вашей цели — не беспокойтесь о сваливании.

В идеале вам нужно создавать кадры со скоростью 60 кадров в секунду. Вы можете получить всего лишь 20 кадров в секунду в зависимости от вашего приложения. До появления цифрового кино кинотеатры показывали только 24 кадра в секунду.

60fps означает, что у вас есть 16 миллисекунд для рендеринга кадра. На 1 ГГц процессоре это 16 миллионов тактов. Чтобы избежать заикания из-за других процессов, вам нужно использовать менее половины этого, скажем, 4-8 миллионов циклов, так что от 50% до 75% процессорного времени простаивает, и вы используете только 4-8 миллисекунд процессорного времени, отрисовывая Рамка.

Ожидание других потоков, мьютексов или других ресурсов влияет только на вашу анимацию, если это заставляет вас пропустить крайний срок для следующего кадра.

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

2

Другие решения

Других решений пока нет …

По вопросам рекламы ammmcru@yandex.ru
Adblock
detector