diff options
author | Tom Rondeau <tom@trondeau.com> | 2015-08-05 15:28:43 -0400 |
---|---|---|
committer | Tom Rondeau <tom@trondeau.com> | 2015-08-05 15:28:43 -0400 |
commit | 25ece6784ec06d9c2fed13d59eb9dec9c541983d (patch) | |
tree | 4df8795fa01624cf3676e68a49f4a9307dcb0722 /gnuradio-runtime/lib/buffer.cc | |
parent | fccf4b04dac2b3cefdc4b610dea8920bfff4d08b (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.cc | 37 |
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() |