1

Let's assume i have following data struct with 2 int values key_x and key_y + some additional fields.

struct data_object {
    int key_x;
    int key_y;

    //....
};

And boost multi_index_container with composite_key, including key_x and key_y members.

struct by_xy;

typedef multi_index_container<
    data_object,
    indexed_by<
        // ....
        ordered_non_unique< tag<by_xy>,
            composite_key< data_object,
               member<data_object, int, &data_object::key_x>,
               member<data_object, int, &data_object::key_y>,
            >
        >
    >
> data_object_multi_index_type;
typedef generic_index<data_object, data_object_multi_index_type> data_index;

I need to take all data_object's, whose values key_x == 0 and key_y < 100 and set key_x = 100.
So the question is whether it is correct to iterate over index and modify it using function below? Will it cause index rebuild, significant performance issues, or not expected behavior?

What is correct approach for this problem?

void foo() {
    const auto& data_idx = get_index_type<data_index>().indices().get<by_xy>();

    const auto range = data_idx.equal_range( boost::make_tuple( 0 ) );

    for( const data_object& data_obj : boost::make_iterator_range( range.first, range.second ) ) {
        if( data_obj.key_y < 100 ) {
            modify( data_obj, []( data_object& var ) { var.key_x = 100; } );
        }
    }
}

UPD: Sometimes this solution leads to memory access violation and will not work correctly, because index rebuilds and iterators in range become invalid. What is the solutions to iterate and modify?

johnbrovi
  • 82
  • 1
  • 8

1 Answers1

0

You are failing to provide a MCVE, so it's hard to say what's wrong. In particular, this modify function you're using is not part of Boost.MultiIndex's interface, so we'd need you to provide its definition here.

With this caveat in mind, what's likely happening is that modifying data_obj so that key_x==100 causes the (implicit) iterator pointing to it to jump out of the range defined by key_x==0. You need to do the traversal making sure that the next position of your range is secured before modifying, such as:

for(auto it=data_idx.lower_bound(0);it!=data_idx.end()&&it->key_y<100;) {
    data_idx.modify(it++, []( data_object& var ) { var.key_x = 100; } );
}
Joaquín M López Muñoz
  • 5,243
  • 1
  • 15
  • 20