Modifying all matching elements in a Boost.MultiIndex Container
Hi, I am trying to modify members of all elements matching value for a given index in a boost.multiindex container index.modify( index.find(value), [](T& element) { ... } ) seems to update a singular element(first match) On the other hand, std::pair<index::iterator, index::iterator> iter = index.equal_range(value); while(iter.first != iter.second) { index.modify( iter.first, [](T& element) { ... } ); iter.first++; } leads to segfaults and unexpected behavior. What would be right way to approach this?
Amit Prakash Ambasta <amit.prakash.ambasta <at> gmail.com> writes:
std::pair<index::iterator, index::iterator> iter = index.equal_range(value);
while(iter.first != iter.second) {
index.modify( iter.first, [](T& element) { ... } );
iter.first++; }
leads to segfaults and unexpected behavior.
What would be right way to approach this?
This is a classic, please follow these links for further info: http://stackoverflow.com/questions/29013600/ modifying-key-ranges-in-a-boost-multi-index-map-having-hashed-non-unique-keys http://lists.boost.org/boost-users/2006/03/18048.php Joaquín M López Munoz Telefónica
Hey Joaquin First of all, thank you so much for your repeated help. In line with the example provided, I've written a generic find_and_modify function as: template <typename T, typename F> Segment* find_and_modify(T& iterable, F filters, State s, double a_arr=-1, Comment rmk=Comment::INFO_SEGMENT_PREDICTED) { auto iter = iterable.find(filters); if (iter == iterable.end()) return nullptr; std::pair<typename T::iterator, typename T::iterator> iter_main = iterable.equal_range(filters); while (iter_main.first != iter_main.second) { auto it = boost::multi_index::project<aux>(segment, iter_main.first); segment.get<aux>().modify( it, [&s, &a_arr, &rmk](Segment& seg) { seg.state = s; if (a_arr != -1) seg.a_arr = a_arr; if (rmk != +Comment::INFO_SEGMENT_PREDICTED) { seg.comment = rmk; } } ); iter_main.first++; } return (Segment *)(&(*iter)); } where T is an index on container instance segment as segment.get<sometag>(); This seems to work well for the most part but it still segfaults. Any ideas what I'm doing wrong. As specified in the SO answer, I've created an aux index and projected the current iterator to it so as to not modify the current iterator, and yet on debugging the function, I've found that iter_main.first evaluates to garbage at some point as: (gdb) p (*iter_main.first) $7 = (const boost::multi_index::detail::index_node_base<Segment, std::allocator<Segment> >::value_type &) @0x6b3c10: { index = " \252\355\000\000\000\000\000\020\376u\000\000\000\000\000\060\355u\000\000\000\000\000\020\376u\000\000\000\000\000\320\361j\000\000\000\000\000\360:r\000\000\000\000\000\270۾\366\377\177\000\000\270۾\366\377\177\000\000\310۾\366\377\177\000\000\310۾\366\377\177\000\000\330۾\366\377\177\000\000\330۾\366\377\177\000\000\260\363u\000\000\000\000\000\260\363u\000\000\000\000\000`;k\000\000\000\000\000`;k\000\000\000\000\000\200\227j\000\000\000\000\000\200\227j\000\000\000\000\000\030ܾ\366\377\177\000\000\030ܾ\366\377\177\000\000(ܾ\366\377\177\000\000(ܾ\366\377\177\000\000\070ܾ\366\377\177\000\000\070ܾ\366\377\177\000\000Hܾ\366\377\177\000\000"..., code = "OP", cname = "34283", p_arr = 1450614300, p_dep = 1450667229, a_arr = 3, a_dep = inf, t_inb_proc = 3600, t_agg_proc = 0, t_out_proc = 18000, cost = 0, state = {static _size_constant = 5, _value = 3 '\003'}, comment = {static _size_constant = 9, _value = 2 '\002'}, parent = 0x75ed70} On Fri, Jan 1, 2016 at 1:03 AM Joaquín M Lopez Munoz <joaquin@tid.es> wrote:
Amit Prakash Ambasta <amit.prakash.ambasta <at> gmail.com> writes:
std::pair<index::iterator, index::iterator> iter =
index.equal_range(value);
while(iter.first != iter.second) {
index.modify( iter.first, [](T& element) { ... } );
iter.first++; }
leads to segfaults and unexpected behavior.
What would be right way to approach this?
This is a classic, please follow these links for further info:
http://stackoverflow.com/questions/29013600/
modifying-key-ranges-in-a-boost-multi-index-map-having-hashed-non-unique-keys http://lists.boost.org/boost-users/2006/03/18048.php
Joaquín M López Munoz Telefónica _______________________________________________ Boost-users mailing list Boost-users@lists.boost.org http://lists.boost.org/mailman/listinfo.cgi/boost-users
Amit Prakash Ambasta <amit.prakash.ambasta <at> gmail.com> writes:
Hey Joaquin First of all, thank you so much for your repeated help.
You're welcome. Please don't top post, as suggested by Boost mailing lists guidelines: http://www.boost.org/community/policy.html
In line with the example provided, I've written a generic find_and_modify function as:
template <typename T, typename F> Segment* find_and_modify(T& iterable, F filters, State s, double a_arr=-1, Comment rmk=Comment::INFO_SEGMENT_PREDICTED) { auto iter = iterable.find(filters);
if (iter == iterable.end()) return nullptr;
std::pair<typename T::iterator, typename T::iterator> iter_main = iterable.equal_range(filters);
while (iter_main.first != iter_main.second) { auto it = boost::multi_index::project<aux>( segment, iter_main.first); segment.get<aux>().modify( it, [&s, &a_arr, &rmk](Segment& seg) { seg.state = s; if (a_arr != -1) seg.a_arr = a_arr;
if (rmk != +Comment::INFO_SEGMENT_PREDICTED) { seg.comment = rmk; } } ); iter_main.first++; }
return (Segment *)(&(*iter)); }
where T is an index on container instance segment as segment.get<sometag>();
This seems to work well for the most part but it still segfaults. Any ideas what I'm doing wrong. As specified in the SO answer, I've created an aux index and projected the current iterator to it so as to not modify the current iterator, and yet [...]
This is not helping at all because modify (no matter through which iterator is done) still can change the order of T so that your [iter_main.first,iter_main.second) loop fails. Put another way, the code auto it = boost::multi_index::project<aux>(segment, iter_main.first); segment.get<aux>().modify(it, ...); does exactly the same as T.modify(iter_main.first, ...); The answer in SO works because the loop is over the entire sequence [aux.begin(),aux.end()) (with aux=information_map_.get<idx_auxiliary>()), which is stable under modifications of the elements (it's a random-access index). This does not translate well to your scenario, where you need to loop over a subrange [a,b) of the sequence: for it to work [a,b) would have to project to a range [a',b') in the aux index, which of course is not the case (traversal orders are different).
I'd also like to point out that your approach via modify_unstable_range as per the boost mailing list works correctly though (however you've commented that it would be a slower approach)
Measure and if performance's OK stick to the modify_unstable_range approach. The aux index technique can be made to work with a little more effort (basically, by rearranging the index with rearrange()) but you might not need to anyway if modify_unstable_range is good enough (and there's no guarantee it's going to be faster to begin with). Joaquín M López Muñoz Telefónica
I'd also like to point out that your approach via modify_unstable_range as per the boost mailing list works correctly though (however you've commented that it would be a slower approach) On Fri, Jan 1, 2016 at 1:03 AM Joaquín M Lopez Munoz <joaquin@tid.es> wrote:
Amit Prakash Ambasta <amit.prakash.ambasta <at> gmail.com> writes:
std::pair<index::iterator, index::iterator> iter =
index.equal_range(value);
while(iter.first != iter.second) {
index.modify( iter.first, [](T& element) { ... } );
iter.first++; }
leads to segfaults and unexpected behavior.
What would be right way to approach this?
This is a classic, please follow these links for further info:
http://stackoverflow.com/questions/29013600/
modifying-key-ranges-in-a-boost-multi-index-map-having-hashed-non-unique-keys http://lists.boost.org/boost-users/2006/03/18048.php
Joaquín M López Munoz Telefónica _______________________________________________ Boost-users mailing list Boost-users@lists.boost.org http://lists.boost.org/mailman/listinfo.cgi/boost-users
participants (3)
-
Amit Prakash Ambasta
-
Joaquin M Lopez Munoz
-
Joaquín M Lopez Munoz