From: Soeren Apel Date: Tue, 18 Aug 2020 06:38:33 +0000 (+0200) Subject: Better segment handling in math signal and lock avoidance X-Git-Url: https://sigrok.org/gitweb/?p=pulseview.git;a=commitdiff_plain;h=bee54d9ec103a35c86fa9e80fbdd2a07f8fb762d Better segment handling in math signal and lock avoidance --- diff --git a/pv/data/analog.cpp b/pv/data/analog.cpp index 02cb83e4..0b5c3772 100644 --- a/pv/data/analog.cpp +++ b/pv/data/analog.cpp @@ -39,6 +39,8 @@ Analog::Analog() : void Analog::push_segment(shared_ptr &segment) { segments_.push_back(segment); + + connect(segment.get(), SIGNAL(completed()), this, SLOT(on_segment_completed())); } const deque< shared_ptr >& Analog::analog_segments() const @@ -95,5 +97,10 @@ void Analog::notify_min_max_changed(float min, float max) min_max_changed(min, max); } +void Analog::on_segment_completed() +{ + segment_completed(); +} + } // namespace data } // namespace pv diff --git a/pv/data/analog.hpp b/pv/data/analog.hpp index 630075da..630dc9db 100644 --- a/pv/data/analog.hpp +++ b/pv/data/analog.hpp @@ -73,6 +73,11 @@ Q_SIGNALS: void min_max_changed(float min, float max); + void segment_completed(); + +private Q_SLOTS: + void on_segment_completed(); + private: double samplerate_; deque< shared_ptr > segments_; diff --git a/pv/data/logicsegment.cpp b/pv/data/logicsegment.cpp index a7df235a..22f1d38a 100644 --- a/pv/data/logicsegment.cpp +++ b/pv/data/logicsegment.cpp @@ -328,6 +328,7 @@ void LogicSegment::append_payload(shared_ptr logic) void LogicSegment::append_payload(void *data, uint64_t data_size) { + assert(unit_size_ > 0); assert((data_size % unit_size_) == 0); lock_guard lock(mutex_); diff --git a/pv/data/mathsignal.cpp b/pv/data/mathsignal.cpp index d9ba5bc3..24df0e71 100644 --- a/pv/data/mathsignal.cpp +++ b/pv/data/mathsignal.cpp @@ -101,8 +101,6 @@ MathSignal::MathSignal(pv::Session &session) : this, SLOT(on_capture_state_changed(int))); connect(&session_, SIGNAL(data_received()), this, SLOT(on_data_received())); - - expression_ = "sin(2 * pi * t) + cos(t / 2 * pi)"; } MathSignal::~MathSignal() @@ -182,10 +180,18 @@ uint64_t MathSignal::get_working_sample_count(uint32_t segment_id) const const shared_ptr& sb = input_signal.second.sb; shared_ptr a = sb->analog_data(); - const uint32_t last_segment = (a->analog_segments().size() - 1); - if (segment_id > last_segment) + auto analog_segments = a->analog_segments(); + + if (analog_segments.size() == 0) { + result = 0; + continue; + } + + const uint32_t highest_segment_id = (analog_segments.size() - 1); + if (segment_id > highest_segment_id) continue; - const shared_ptr segment = a->analog_segments()[segment_id]; + + const shared_ptr segment = analog_segments.at(segment_id); result = min(result, (int64_t)segment->get_sample_count()); } } else @@ -195,6 +201,38 @@ uint64_t MathSignal::get_working_sample_count(uint32_t segment_id) const return result; } +void MathSignal::update_completeness(uint32_t segment_id) +{ + bool output_complete = true; + + if (input_signals_.size() > 0) { + for (auto input_signal : input_signals_) { + const shared_ptr& sb = input_signal.second.sb; + + shared_ptr a = sb->analog_data(); + auto analog_segments = a->analog_segments(); + + if (analog_segments.size() == 0) { + output_complete = false; + continue; + } + + const uint32_t highest_segment_id = (analog_segments.size() - 1); + if (segment_id > highest_segment_id) { + output_complete = false; + continue; + } + + const shared_ptr segment = analog_segments.at(segment_id); + if (!segment->is_complete()) + output_complete = false; + } + } + + if (output_complete) + analog_data()->analog_segments().at(segment_id)->set_complete(); +} + void MathSignal::reset_generation() { if (gen_thread_.joinable()) { @@ -274,7 +312,7 @@ void MathSignal::begin_generation() signal_data* sig_data = signal_from_name(unknown); const shared_ptr signal = (sig_data) ? (sig_data->sb) : nullptr; if (!signal || (!signal->analog_data())) { - set_error_message(QString(tr("%1 isn't a valid signal")).arg( + set_error_message(QString(tr("%1 isn't a valid analog signal")).arg( QString::fromStdString(unknown))); } else sig_data->ref = &(exprtk_unknown_symbol_table_->variable_ref(unknown)); @@ -376,9 +414,9 @@ void MathSignal::generation_proc() } if (samples_to_process == 0) { - if (segment_id < session_.get_highest_segment_id()) { - analog->analog_segments().back()->set_complete(); + update_completeness(segment_id); + if (segment_id < session_.get_highest_segment_id()) { // Process next segment segment_id++; @@ -408,8 +446,15 @@ signal_data* MathSignal::signal_from_name(const std::string& name) const QString sig_name = QString::fromStdString(name); for (const shared_ptr& sb : signalbases) - if (sb->name() == sig_name) + if (sb->name() == sig_name) { + if (!sb->analog_data()) + continue; + + connect(sb->analog_data().get(), SIGNAL(segment_completed()), + this, SLOT(on_data_received())); + return &(input_signals_.insert({name, signal_data(sb)}).first->second); + } } return nullptr; @@ -446,8 +491,12 @@ void MathSignal::on_capture_state_changed(int state) begin_generation(); if (state == Session::Stopped) { - shared_ptr analog = analog_data(); - analog->analog_segments().back()->set_complete(); + // If we have input signals, we use those as the indicators + if (input_signals_.empty()) { + shared_ptr analog = analog_data(); + if (!analog->analog_segments().empty()) + analog->analog_segments().back()->set_complete(); + } } } diff --git a/pv/data/mathsignal.hpp b/pv/data/mathsignal.hpp index b9bd6ee4..a1fb9ffb 100644 --- a/pv/data/mathsignal.hpp +++ b/pv/data/mathsignal.hpp @@ -89,6 +89,8 @@ private: */ uint64_t get_working_sample_count(uint32_t segment_id) const; + void update_completeness(uint32_t segment_id); + void reset_generation(); void begin_generation(); diff --git a/pv/data/segment.cpp b/pv/data/segment.cpp index 1dfdefd4..18aabedb 100644 --- a/pv/data/segment.cpp +++ b/pv/data/segment.cpp @@ -70,7 +70,6 @@ Segment::~Segment() uint64_t Segment::get_sample_count() const { - lock_guard lock(mutex_); return sample_count_; } @@ -102,6 +101,8 @@ uint32_t Segment::segment_id() const void Segment::set_complete() { is_complete_ = true; + + completed(); } bool Segment::is_complete() const @@ -225,8 +226,7 @@ const uint8_t* Segment::get_raw_sample(uint64_t sample_num) const return chunk + chunk_offs; } -void Segment::get_raw_samples(uint64_t start, uint64_t count, - uint8_t* dest) const +void Segment::get_raw_samples(uint64_t start, uint64_t count, uint8_t* dest) const { assert(start < sample_count_); assert(start + count <= sample_count_); diff --git a/pv/data/segment.hpp b/pv/data/segment.hpp index 9bdc17dd..66085faf 100644 --- a/pv/data/segment.hpp +++ b/pv/data/segment.hpp @@ -23,12 +23,14 @@ #include "pv/util.hpp" +#include #include #include #include #include +using std::atomic; using std::recursive_mutex; using std::deque; @@ -81,6 +83,9 @@ public: void free_unused_memory(); +Q_SIGNALS: + void completed(); + protected: void append_single_sample(void *data); void append_samples(void *data, uint64_t samples); @@ -98,7 +103,7 @@ protected: deque data_chunks_; uint8_t* current_chunk_; uint64_t used_samples_, unused_samples_; - uint64_t sample_count_; + atomic sample_count_; pv::util::Timestamp start_time_; double samplerate_; uint64_t chunk_size_;