Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Erasing and modifying elements in Boost MultiIndex Container

Tags:

c++

boost

I'm trying to use a Boost MultiIndex container in my simulation. My knowledge of C++ syntax is very weak, and I'm concerned I'm not properly removing an element from the container or deleting it from memory. I also need to modify elements, and I was hoping to confirm the syntax and basic philosophy here too.

// main.cpp
...
#include <boost/multi_index_container.hpp>
#include <boost/multi_index/hashed_index.hpp>
#include <boost/multi_index/member.hpp>
#include <boost/multi_index/ordered_index.hpp>
#include <boost/multi_index/mem_fun.hpp>
#include <boost/tokenizer.hpp>
#include <boost/shared_ptr.hpp>
...
#include "Host.h" // class Host, all members private, using get fxns to access

using boost::multi_index_container;
using namespace boost::multi_index;

typedef multi_index_container<
  boost::shared_ptr< Host >,
  indexed_by< 
    hashed_unique< const_mem_fun<Host,int,&Host::getID> >
    //   ordered_non_unique< BOOST_MULTI_INDEX_MEM_FUN(Host,int,&Host::getAge) >
    > // end indexed_by
  > HostContainer;

typedef HostContainer::nth_index<0>::type HostsByID;

int main() {
   ...
   HostContainer allHosts;
   Host * newHostPtr;
   newHostPtr = new Host( t, DOB, idCtr, 0, currentEvents );
   allHosts.insert( boost::shared_ptr<Host>(newHostPtr) );
   // allHosts gets filled up

   int randomHostID = 4;
   int newAge = 50;
   modifyHost( randomHostID, allHosts, newAge );
   killHost( randomHostID, allHosts );
}

void killHost( int id, HostContainer & hmap ){
  HostsByID::iterator it = hmap.find( id );
  cout << "Found host id " << (*it)->getID() << "Attempting to kill. hmap.size() before is " << hmap.size() << " and ";
  hmap.erase( it ); // Is this really erasing (freeing from mem) the underlying Host object?
  cout << hmap.size() << " after." << endl;
}

void modifyHost( int id, HostContainer & hmap, int newAge ){
  HostsByID::iterator it = hmap.find( id );
  (*it) -> setAge( newAge ); // Not actually the "modify" function for MultiIndex...
}

My questions are

  1. In the MultiIndex container allHosts of shared_ptrs to Host objects, is calling allHosts.erase( it ) on an iterator to the object's shared_ptr enough to delete the object permanently and free it from memory? It appears to be removing the shared_ptr from the container.
  2. The allhosts container currently has one functioning index that relies on the host's ID. If I introduce an ordered second index that calls on a member function (Host::getAge()), where the age changes over the course of the simulation, is the index always going to be updated when I refer to it?
  3. What is the difference between using the MultiIndex's modify to modify the age of the underlying object versus the approach I show above?
  4. I'm vaguely confused about what is assumed/required to be constant in MultiIndex.

Thanks in advance.


Update

Here's my attempt to get the modify syntax working, based on what I see in a related Boost example.

struct update_age {
  update_age():(){} // have no idea what this really does... elicits error
  void operator() (boost::shared_ptr<Host> ptr) {
    ptr->incrementAge(); // incrementAge() is a member function of class Host
  }
};

and then in modifyHost, I'd have hmap.modify(it,update_age). Even if by some miracle this turns out to be right, I'd love some kind of explanation of what's going on.

like image 803
Sarah Avatar asked Apr 16 '10 16:04

Sarah


1 Answers

shared_ptr will remove actual Host object in its destructor (if there is no other instances of shared_ptr). All objects in MultiIndex are considered constant. To modify the object you should use method modify of MultiIndex. In that case indexes will be updates if necessary.

You could use the following functor to change age field:

  struct change_age
  {
    change_age(int age) : age_(age) {}    
    void operator()(boost::shared_ptr<Host> h) // shared_ptr !!!
    {
      h->age = age_;
    }

  private:
    int age_;
  };

Then use it as follows:

  testHosts.modify( it, Host::change_age( 22 ) ); // set age to 22
like image 160
Kirill V. Lyadvinsky Avatar answered Nov 15 '22 09:11

Kirill V. Lyadvinsky