From c6c12209e8d9e1dacc8f483ed871933477f5f032 Mon Sep 17 00:00:00 2001 From: Thomas Harte Date: Wed, 25 Nov 2020 23:32:37 -0500 Subject: [PATCH] Corrects `end_data` thread safety; permits caller not to have reached `new_modals` before a machine starts trying to push data. --- Outputs/ScanTargets/BufferingScanTarget.cpp | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/Outputs/ScanTargets/BufferingScanTarget.cpp b/Outputs/ScanTargets/BufferingScanTarget.cpp index 6c08a2d52..f78fc4de4 100644 --- a/Outputs/ScanTargets/BufferingScanTarget.cpp +++ b/Outputs/ScanTargets/BufferingScanTarget.cpp @@ -38,8 +38,8 @@ uint8_t *BufferingScanTarget::begin_data(size_t required_length, size_t required // If allocation has already failed on this line, continue the trend. if(allocation_has_failed_) return nullptr; - // If there isn't yet a write area then mark allocation as failed and finish. - if(!write_area_) { + // If there isn't yet a write area or data size then mark allocation as failed and finish. + if(!write_area_ || !data_type_size_) { allocation_has_failed_ = true; return nullptr; } @@ -90,9 +90,6 @@ uint8_t *BufferingScanTarget::begin_data(size_t required_length, size_t required } template void BufferingScanTarget::end_data(size_t actual_length) { - // Acquire the producer lock. - std::lock_guard lock_guard(producer_mutex_); - // Do nothing if no data write is actually ongoing. if(!data_is_allocated_) return; data_is_allocated_ = false; @@ -115,9 +112,15 @@ template void BufferingScanTarget::end_data(size_t actual_le } void BufferingScanTarget::end_data(size_t actual_length) { + // Acquire the producer lock. + std::lock_guard lock_guard(producer_mutex_); + // Just dispatch appropriately. switch(data_type_size_) { - default: break; + default: assert(false); + case 0: + // This just means that modals haven't been grabbed yet. + break; case 1: end_data(actual_length); break; case 2: end_data(actual_length); break; case 4: end_data(actual_length); break; @@ -379,6 +382,7 @@ const Outputs::Display::ScanTarget::Modals *BufferingScanTarget::new_modals() { // But either way it's now appropriate to start treating the data size as implied by the data type. std::lock_guard lock_guard(producer_mutex_); data_type_size_ = Outputs::Display::size_for_data_type(modals_.input_data_type); + assert((data_type_size_ == 1) || (data_type_size_ == 2) || (data_type_size_ == 4)); return &modals_; }