summaryrefslogtreecommitdiff
path: root/gnuradio-runtime/lib/buffer.cc
diff options
context:
space:
mode:
authorTom Rondeau <tom@trondeau.com>2015-08-05 15:28:43 -0400
committerTom Rondeau <tom@trondeau.com>2015-08-05 15:28:43 -0400
commit25ece6784ec06d9c2fed13d59eb9dec9c541983d (patch)
tree4df8795fa01624cf3676e68a49f4a9307dcb0722 /gnuradio-runtime/lib/buffer.cc
parentfccf4b04dac2b3cefdc4b610dea8920bfff4d08b (diff)
runtime: fixes a problem with tag pruning.
Looked like a race condition if two blocks are reading from the same buffer; one block calls prune before the other one can, and then it no longer gets its tags. This puts back in the original protections we used when pruning with vectors, only we don't have to restart the iterator at the beginning and can exit sooner because of the sort order. Likely slower than the multimap erase, so we will have to reinvestigate what kind of performance hit we take and if we can do better.
Diffstat (limited to 'gnuradio-runtime/lib/buffer.cc')
-rw-r--r--gnuradio-runtime/lib/buffer.cc37
1 files changed, 31 insertions, 6 deletions
diff --git a/gnuradio-runtime/lib/buffer.cc b/gnuradio-runtime/lib/buffer.cc
index f00e9a04bf..4840614104 100644
--- a/gnuradio-runtime/lib/buffer.cc
+++ b/gnuradio-runtime/lib/buffer.cc
@@ -248,12 +248,37 @@ namespace gr {
locks the mutex itself.
If this function is used elsewhere, remember to lock the
- buffer's mutex al la the scoped_lock line below.
- */
- std::multimap<uint64_t, tag_t>::iterator end_itr = d_item_tags.lower_bound(max_time);
- std::multimap<uint64_t, tag_t>::iterator begin_itr = d_item_tags.begin();
- d_item_tags.erase(begin_itr, end_itr);
- }
+ buffer's mutex al la the scoped_lock:
+ gr::thread::scoped_lock guard(*mutex());
+ */
+
+ /*
+ http://www.cplusplus.com/reference/map/multimap/erase/
+ "Iterators, pointers and references referring to elements removed
+ by the function are invalidated. All other iterators, pointers
+ and references keep their validity."
+
+ Store the iterator to be deleted in tmp; increment itr to the
+ next valid iterator, then erase tmp, which now becomes invalid.
+ */
+
+ uint64_t item_time;
+ std::multimap<uint64_t,tag_t>::iterator itr(d_item_tags.begin()), tmp;
+ while(itr != d_item_tags.end()) {
+ item_time = (*itr).second.offset;
+ if(item_time+d_max_reader_delay + bufsize() < max_time) {
+ tmp = itr;
+ itr++;
+ d_item_tags.erase(tmp);
+ }
+ else {
+ // d_item_tags is a map sorted by offset, so when the if
+ // condition above fails, all future tags in the map must also
+ // fail. So just break here.
+ break;
+ }
+ }
+ }
long
buffer_ncurrently_allocated()