]> sigrok.org Git - pulseview.git/blobdiff - pv/data/decodesignal.cpp
DecodeSignal: Unpause reliably
[pulseview.git] / pv / data / decodesignal.cpp
index 9da7de6766c418e759ea1f02d88ba8ab8614c551..405e06e145b50ed15743af7e47892125c297613d 100644 (file)
@@ -17,6 +17,7 @@
  * along with this program; if not, see <http://www.gnu.org/licenses/>.
  */
 
+#include <forward_list>
 #include <limits>
 
 #include <QDebug>
@@ -32,6 +33,7 @@
 #include <pv/globalsettings.hpp>
 #include <pv/session.hpp>
 
+using std::forward_list;
 using std::lock_guard;
 using std::make_pair;
 using std::make_shared;
@@ -149,6 +151,8 @@ void DecodeSignal::reset_decode(bool shutting_down)
                logic_mux_thread_.join();
        }
 
+       resume_decode();  // Make sure the decode thread isn't blocked by pausing
+
        class_rows_.clear();
        current_segment_id_ = 0;
        segments_.clear();
@@ -256,6 +260,25 @@ void DecodeSignal::begin_decode()
        decode_thread_ = std::thread(&DecodeSignal::decode_proc, this);
 }
 
+void DecodeSignal::pause_decode()
+{
+       decode_paused_ = true;
+}
+
+void DecodeSignal::resume_decode()
+{
+       // Manual unlocking is done before notifying, to avoid waking up the
+       // waiting thread only to block again (see notify_one for details)
+       decode_pause_mutex_.unlock();
+       decode_pause_cond_.notify_one();
+       decode_paused_ = false;
+}
+
+bool DecodeSignal::is_paused() const
+{
+       return decode_paused_;
+}
+
 QString DecodeSignal::error_message() const
 {
        lock_guard<mutex> lock(output_mutex_);
@@ -471,6 +494,33 @@ void DecodeSignal::get_annotation_subset(
        }
 }
 
+void DecodeSignal::get_annotation_subset(
+       vector<pv::data::decode::Annotation> &dest,
+       uint32_t segment_id, uint64_t start_sample, uint64_t end_sample) const
+{
+       // Note: We put all vectors and lists on the heap, not the stack
+
+       const vector<Row> rows = visible_rows();
+
+       // Use forward_lists for faster merging
+       forward_list<Annotation> *all_ann_list = new forward_list<Annotation>();
+
+       for (const Row& row : rows) {
+               vector<Annotation> *ann_vector = new vector<Annotation>();
+               get_annotation_subset(*ann_vector, row, segment_id, start_sample, end_sample);
+
+               forward_list<Annotation> *ann_list =
+                       new forward_list<Annotation>(ann_vector->begin(), ann_vector->end());
+               delete ann_vector;
+
+               all_ann_list->merge(*ann_list);
+               delete ann_list;
+       }
+
+       move(all_ann_list->begin(), all_ann_list->end(), back_inserter(dest));
+       delete all_ann_list;
+}
+
 void DecodeSignal::save_settings(QSettings &settings) const
 {
        SignalBase::save_settings(settings);
@@ -952,6 +1002,11 @@ void DecodeSignal::decode_data(
                // Notify the frontend that we processed some data and
                // possibly have new annotations as well
                new_annotations();
+
+               if (decode_paused_) {
+                       unique_lock<mutex> pause_wait_lock(decode_pause_mutex_);
+                       decode_pause_cond_.wait(pause_wait_lock);
+               }
        }
 }
 
@@ -1225,7 +1280,7 @@ void DecodeSignal::annotation_callback(srd_proto_data *pdata, void *decode_signa
        }
 
        // Add the annotation
-       (*row_iter).second.emplace_annotation(pdata);
+       (*row_iter).second.emplace_annotation(pdata, &((*row_iter).first));
 }
 
 void DecodeSignal::on_capture_state_changed(int state)