From 355b14dcc0616606486da9f3b56651b5e3a8677a Mon Sep 17 00:00:00 2001 From: Helge Norberg Date: Thu, 23 Feb 2017 14:33:29 +0100 Subject: [PATCH] [decklink_consumer] #539 #285 #521 Fixed serious deadlock in decklink_consumer where a race condition between pop and acquisition of mutex left a window where an other thread could acquire the lock. Rewrote the whole thing in a better way. --- .../decklink/consumer/decklink_consumer.cpp | 30 +++++-------------- 1 file changed, 7 insertions(+), 23 deletions(-) diff --git a/modules/decklink/consumer/decklink_consumer.cpp b/modules/decklink/consumer/decklink_consumer.cpp index 39dcde7f4..2e494577e 100644 --- a/modules/decklink/consumer/decklink_consumer.cpp +++ b/modules/decklink/consumer/decklink_consumer.cpp @@ -395,11 +395,10 @@ struct decklink_consumer : public IDeckLinkVideoOutputCallback, boost::noncopyab boost::circular_buffer> audio_container_ { buffer_size_ + 1 }; tbb::concurrent_bounded_queue frame_buffer_; + caspar::semaphore ready_for_new_frames_ { 0 }; spl::shared_ptr graph_; caspar::timer tick_timer_; - boost::mutex send_completion_mutex_; - std::packaged_task send_completion_; reference_signal_detector reference_signal_detector_ { output_ }; tbb::atomic current_presentation_delay_; tbb::atomic scheduled_frames_completed_; @@ -574,16 +573,7 @@ public: auto frame = core::const_frame::empty(); frame_buffer_.pop(frame); - - { - boost::lock_guard lock(send_completion_mutex_); - - if (send_completion_.valid()) - { - send_completion_(); - send_completion_ = std::packaged_task(); - } - } + ready_for_new_frames_.release(); if (!is_running_) return E_FAIL; @@ -647,22 +637,16 @@ public: if(!is_running_) CASPAR_THROW_EXCEPTION(caspar_exception() << msg_info(print() + L" Is not running.")); - boost::lock_guard lock(send_completion_mutex_); + frame_buffer_.push(frame); - if (frame_buffer_.try_push(frame)) - { - send_completion_ = std::packaged_task(); - return make_ready_future(true); - } + auto send_completion = spl::make_shared>(); - send_completion_ = std::packaged_task([frame, this] () mutable -> bool + ready_for_new_frames_.acquire(1, [send_completion] { - frame_buffer_.push(frame); - - return true; + send_completion->set_value(true); }); - return send_completion_.get_future(); + return send_completion->get_future(); } std::wstring print() const -- 2.39.2