|
Boost Users : |
Subject: [Boost-users] Problem with Iterator passing inside an index... a little complex...
From: Rodrigo Dias Ferreira (rodrigodias_at_[hidden])
Date: 2009-02-06 10:09:27
Hi There,
I am using the Boost.MultiIndex and I am facing a problem that I am try
to resolving (debbuging) already about 20 hours...
I think I get the problem isolated, but I don't know how to solve,
and I don't know if this it is implemented.
So I decided to make a example, it is a little big, but I put it as resumed as I could and post here in order to know if anyone could help me out.
I will try to explain briefly here, I will copy the main() code right under the explanation, but the whole code of the example is in the end of the e-mail (with the classes and functions) If you want you could try to run too see what is the problem that I am talking about.)
When I try to access an pair of iterators pair<propIt,propIt>
that I stored inside a class (propertystream_h),
somehow is changing to where the iterator points, I think it could
be because the object which has originate (Graph) the index is created, stored in in a static index (which I call _graphRep) from the DynamicGraphs, passed to a handler (Graph_h), and then after the Graph goes out of scope it is destroyed. When the Graph_h._localGraph (copy of the iterator->Graph returned by the insertion in the _graphRep) access its member _globalProperties (which is an index containing the fields:
{string _key, string _value, propertystream_h _props} from the struct
globalPropSchema) through a iterator (let's call it: gpit), then it is fine. But then when I try to access through the gpit->_props._propRangeIt.first, the iterator of the propertystream_h (_propRangeIt.first), then the iterators, some how are messed up. ( -> in this example it points to last element, and then when I get next, never finds the end(). (sometimes it return some trash, sometimes I get segmentation fault).
So I would like to know why it is messing with the iterator? And how could I solve this problem?
that's it,
best regards,
Rodrigo
P.S.: I hope someone can help me...
copy of the main():
int main(){
DynamicGraphs dg;
Graph_h graph_h;
propertystream_h propS;
property_h prop_h;
GlobalPropIterator gpit;
GlobalProp_h gp_h;
propertystream_h ps_h;
property_h p_h;
graph_h = dg.createGraph("COI:0351-123-4555");
if (!graph_h)
cout << "Unsuccessful creation!"<<endl;
else
cout << "Successful creation!" <<endl;
//It works, because it takes from the _localPropRep, and it passes it as value!!!
ps_h = graph_h->lookupLocalProp("name");
while(!ps_h.end()){
cout << "LocalProperties: ";
p_h=ps_h.next();
cout << "Key: " << p_h.key() << " Value: " << p_h.value() <<endl;
}
// It does not work, because is accessing the propertystream_h from
// the _globalPropRep (index of the tuple
// {string globalkey, string value, propertystream_h props}
// the propertystream_h it has as member a pair of iterators for another index.
// -> after a lot of debugging (about 16h) OI found out that
// it seems that during the creation of a graph,
// when it passes the graph to graph_h, and goes out of scope, it keep the
// iterator reference to the first element, but just that... the next
// gives me segmentation fault. Anyone knows how to pass the graph and the its members
// the indexes-repositories as value, so it would not depend on the pointing to
// the graph that was freed from the memory?
gpit = graph_h->properties("*");
if (!gpit)
cout << "Not found any property in the globalProperties Repository."<<endl;
else{
int i=0;
while (!gpit.end())
{
gp_h = gpit.next();
cout << "While_1::Iteration_" << ++i << endl;
cout << "GlobalProperty key: " << gp_h.key() << endl;
cout << "GlobalProperty value: " << gp_h.value() << endl;
ps_h = gp_h.propertyStreamHandler();
int j = 0;
while (!ps_h.end()){
p_h = ps_h.next();
cout << "While_2::Iteration" << ++j << endl;
cout << "GlobalProperty::PropertyStream: key " << p_h.key() << endl;
cout << "GlobalProperty::PropertyStream: value " << p_h.value() << endl;
}
}
}
}
Here it is the code:
/*
* IndexProblem.cpp
*
* Created on: Feb 6, 2009
* Author: rodrigo
*/
#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/composite_key.hpp>
#include <boost/tuple/tuple.hpp>
#include <boost/tokenizer.hpp>
#include <boost/lambda/lambda.hpp>
#include <climits>
#include <iomanip>
#include <iostream>
#include <ctime>
#include <string>
#if !defined(NDEBUG)
#define BOOST_MULTI_INDEX_ENABLE_INVARIANT_CHECKING
#define BOOST_MULTI_INDEX_ENABLE_SAFE_MODE
#endif
using std::string;
using std::pair;
using std::ostream;
using std::cout;
using std::endl;
using boost::multi_index_container;
using namespace boost::multi_index;
struct property {
string _key;
string _value;
/// Default Constructor
property(){}
/// Constructor with parameters: initialize the name and graph
property(string key, string value) : _key(key), _value(value) {}
/// Copy Contructor
property(const property &pm) : _key(pm._key), _value(pm._value) {}
//For debugging TODO: delete later
friend ostream& operator<<(ostream& os, const property &p){
os << "Key: " << p._key << " value: " << p._value << endl;
return os;
}
};
/// Indexing in the data structure PropMap
typedef multi_index_container<
property,
indexed_by<
hashed_non_unique<
BOOST_MULTI_INDEX_MEMBER(property, string, _key)
>
>
> propIndex;
typedef propIndex::iterator propIt;
class property_h {
private:
/// Access to properties through the iterator
propIt _pit;
public:
/// Default Constructor
property_h(){}
/// Constructor with Parameters: for lookup of Nodes
property_h (const propIt &it) : _pit(it){}
/// Constructor with Parameters: for lookup of Nodes
property_h (const property_h &h) : _pit(h._pit){}
/// Returns the key from the property being handled
string key() const {return _pit->_key;}
/// Returns the value from the property being handled
string value() const {return _pit->_value;}
};
class propertystream_h {
/// _propRangeIt: for keeping a range in order to iterate over the graphs
pair<propIt,propIt> _propRangeIt;
/// _noMatches: true if there are no matches during the lookup function
bool _noMatches;
public:
/// Default Constructor
propertystream_h() : _noMatches(true){}
/// Constructor with parameters for local lookup
propertystream_h(pair<propIt,propIt> rangeIt, bool noMatches) :
_propRangeIt(rangeIt), _noMatches(noMatches){ }
/// Default Constructor
propertystream_h(const propertystream_h &ps) :
_propRangeIt(ps._propRangeIt), _noMatches(ps._noMatches){}
// returns null_h on end of stream ...
property_h next(){
return property_h(_propRangeIt.first++);
}
/// This function returns true whenever is the end of the stream
bool end(){
return (_propRangeIt.first == _propRangeIt.second);
}
/// Overload operator!: shows if a creation was unsuccessful
bool operator!(){ return _noMatches; }
};
struct globalPropSchema{
string _key;
string _value;
propertystream_h _props;
/// Default Constructor
globalPropSchema() : _key(""), _value(""), _props(){}
/// Parameter Constructor
globalPropSchema(string k, string value, propertystream_h props) : _key(k),
_value(value), _props(props){}
/// Copy Constructor
globalPropSchema(const globalPropSchema &gps) : _key(gps._key), _value(gps._value),
_props(gps._props){}
//TODO: Delete it: Debug
friend ostream& operator<<(ostream &os, const globalPropSchema &gps){
os << "Key: " << gps._key << " Value: "<< gps._value << " PropertyStreamAdress: "
<< &gps._props <<endl;
return os;
}
};
typedef multi_index_container<
globalPropSchema,
indexed_by<
ordered_non_unique<
composite_key<
globalPropSchema,
BOOST_MULTI_INDEX_MEMBER(globalPropSchema, string, _key),
BOOST_MULTI_INDEX_MEMBER(globalPropSchema, string, _value)
>,
composite_key_compare<
std::greater<string>,
std::less<string>
>
>
>
> grobalProperties;
/// Iterator for the data structure of the global properties index
typedef grobalProperties::iterator globalPropIt;
class GlobalProp_h{
private:
/// Access to globalPropertiest items through the iterator
globalPropIt _gpit;
public:
/// Default Constructor
GlobalProp_h(){}
/// Constructor with Parameters: for lookup of Nodes
GlobalProp_h (const globalPropIt &it) : _gpit(it){}
/// Copy Constructor
GlobalProp_h (const GlobalProp_h &gph) : _gpit(gph._gpit){}
/// Access to key of globalPropeties items
string key(){ return _gpit->_key;}
/// Access to value of globalPropeties items
string value(){return _gpit->_value;}
propertystream_h propertyStreamHandler(){
return _gpit->_props;
}
};
/// Iterator for the data structure of the global properties index
typedef grobalProperties::iterator globalPropIt;
class GlobalPropIterator{
private:
/// _propRangeIt: for keeping a range in order to iterate over the graphs
pair<globalPropIt,globalPropIt> _globalPropRangeIt;
/// _noMatches: true if there are no matches during the lookup function
bool _noMatches;
public:
/// Default Constructor
GlobalPropIterator(){}
/// Constructor with parameters for local lookup
GlobalPropIterator(pair<globalPropIt,globalPropIt> rangeIt, bool noMatches) :
_globalPropRangeIt(rangeIt), _noMatches(noMatches){}
/// Default Constructor
GlobalPropIterator(const GlobalPropIterator &gpi) :
_globalPropRangeIt(gpi._globalPropRangeIt), _noMatches(gpi._noMatches){}
// returns null_h on end of stream ...
GlobalProp_h next(){
return GlobalProp_h(_globalPropRangeIt.first++);
}
/// This function returns true whenever is the end of the stream
bool end(){
return (_globalPropRangeIt.first == _globalPropRangeIt.second);
}
/// Overload operator!: shows if a creation was unsuccessful
bool operator!(){ return _noMatches; }
};
class Graph {
private:
propIndex _localPropRep;
/// Repository for the properties of the global properties related to the graph;
grobalProperties _globalPropRep;
public:
// TODO: Really constructors
/// Default Constructor
Graph() {}
/// Copy constructors
Graph(const Graph &g) : _localPropRep(g._localPropRep),
_globalPropRep(g._globalPropRep){}
bool addProperty(string key, string value);
GlobalPropIterator properties(string pattern) const;
/// Function to lookup Local Properties
propertystream_h lookupLocalProp(string pattern);
friend class Graph_h;
};
/// GraphMap: Data Structure for setting an index in the uniqueGraphName and retrieving handler Graph_h
struct graphMap {
string _name;
Graph _graph;
/// Default Constructor
graphMap(){}
/// Constructor with parameters: initialize the name and graph
graphMap(string uniqueGraphName, Graph graph) :
_name(uniqueGraphName), _graph (graph) {}
/// Constructor with parameters: initialize the name and graph
graphMap(const graphMap &gm) : _name(gm._name), _graph (gm._graph) {}
};
///ordered_unique Index in the data structure graph_hm
typedef multi_index_container<
graphMap,
indexed_by<
ordered_unique<
BOOST_MULTI_INDEX_MEMBER(graphMap,string,_name)
>
>
> graphIndex;
/// Defing an iterator for the graphMapIndex
typedef graphIndex::iterator graphIt;
class Graph_h {
private:
/// \brief GraphIterator: Iterator pointing to the Graph
graphIt _git;
Graph _localGraph;
bool _createSuccess;
public:
/// Default Constructor
Graph_h() : _createSuccess(false) {}
/// Constructor with Parameters: for creation of Graphs
Graph_h ( pair<graphIt,bool> creation) :
_git(creation.first), _createSuccess(creation.second){
_localGraph = creation.first->_graph;
}
/// Constructor with Parameters: for lookup of Graphs
Graph_h (const graphIt &it) :
_git(it), _createSuccess(false){
_localGraph = it->_graph;
}
/// Constructor with Parameters: for lookup of Graphs
Graph_h (const Graph_h &h) :
_git(h._git), _localGraph(h._localGraph), _createSuccess(h._createSuccess){}
bool operator!(){
return !_createSuccess;
}
/// Operator-> overloading: allows access to graph members
Graph* operator->() {return &_localGraph;}
};
propertystream_h Graph::lookupLocalProp(string pattern){
pair<propIt,propIt> rangeIt;
propIt rangeItfirst = _localPropRep.find(pattern);
rangeIt.first = rangeItfirst;
rangeIt.second = _localPropRep.end();
if (rangeIt.first != _localPropRep.end())
// second parameter means that the variable noMatches, so false in case that found the key
return propertystream_h(rangeIt, false);
else
//No matches
return propertystream_h(rangeIt, true);
}
GlobalPropIterator Graph::properties(string pattern) const{
pair<globalPropIt,globalPropIt> globalRangePropIt;
bool noMatchesTmp=false;
//Whole range
if (!pattern.compare("*")){
globalRangePropIt.first = _globalPropRep.begin();
globalRangePropIt.second = _globalPropRep.end();
}
if (globalRangePropIt.first == globalRangePropIt.second)
noMatchesTmp = true;
return GlobalPropIterator(globalRangePropIt, noMatchesTmp);
}
bool Graph::addProperty(string key, string value){
bool boolLocal, boolGlobal;
pair <propIt,propIt> rangePropIt;
string globalKey = "graph:";
globalKey.append(key); // "graph:namePorperty"
boolLocal = _localPropRep.insert(property(key,value)).second;
//Defining the whole range for iterate over the local properties
rangePropIt.first = _localPropRep.begin();
rangePropIt.second = _localPropRep.end();
//Debug
propIt it = rangePropIt.first;
cout << "How it should be showed when accessing the iterator..."<<endl;
while (rangePropIt.first != rangePropIt.second){
cout << "DEBUG_at_addProperty: " << *(rangePropIt.first++);
}
cout << endl;
rangePropIt.first = it;
//Debug
boolGlobal = _globalPropRep.insert(
globalPropSchema( globalKey, value, propertystream_h(rangePropIt, false) )
).second;
return (boolLocal && boolGlobal);
}
class DynamicGraphs {
public:
/// Data member to represent the graph repository (using ordered_unique index)
static graphIndex _graphRep;
Graph_h createGraph(string uniqueGraphName);
};
graphIndex DynamicGraphs::_graphRep;
/// Creation of Graph in DynamicGraphs
Graph_h DynamicGraphs::createGraph(string uniqueGraphName){
Graph g;
g.addProperty("name", uniqueGraphName);
//Test
g.addProperty("age", "Unknown");
g.addProperty("color", "blue");
return Graph_h(
_graphRep.insert(
graphMap( uniqueGraphName, g )
)
);
}
int main(){
DynamicGraphs dg;
Graph_h graph_h;
propertystream_h propS;
property_h prop_h;
GlobalPropIterator gpit;
GlobalProp_h gp_h;
propertystream_h ps_h;
property_h p_h;
graph_h = dg.createGraph("COI:0351-123-4555");
if (!graph_h)
cout << "Unsuccessful creation!"<<endl;
else
cout << "Successful creation!" <<endl;
//It works, because it takes from the _localPropRep, and it passes it as value!!!
ps_h = graph_h->lookupLocalProp("name");
while(!ps_h.end()){
cout << "LocalProperties: ";
p_h=ps_h.next();
cout << "Key: " << p_h.key() << " Value: " << p_h.value() <<endl;
}
// It does not work, because is accessing the propertystream_h from
// the _globalPropRep (index of the tuple
// {string globalkey, string value, propertystream_h props}
// the propertystream_h it has as member a pair of iterators for another index.
// -> after a lot of debugging (about 16h) OI found out that
// it seems that during the creation of a graph,
// when it passes the graph to graph_h, and goes out of scope, it keep the
// iterator reference to the first element, but just that... the next
// gives me segmentation fault. Anyone knows how to pass the graph and the its members
// the indexes-repositories as value, so it would not depend on the pointing to
// the graph that was freed from the memory?
gpit = graph_h->properties("*");
if (!gpit)
cout << "Not found any property in the globalProperties Repository."<<endl;
else{
int i=0;
while (!gpit.end())
{
gp_h = gpit.next();
cout << "While_1::Iteration_" << ++i << endl;
cout << "GlobalProperty key: " << gp_h.key() << endl;
cout << "GlobalProperty value: " << gp_h.value() << endl;
ps_h = gp_h.propertyStreamHandler();
int j = 0;
while (!ps_h.end()){
p_h = ps_h.next();
cout << "While_2::Iteration" << ++j << endl;
cout << "GlobalProperty::PropertyStream: key " << p_h.key() << endl;
cout << "GlobalProperty::PropertyStream: value " << p_h.value() << endl;
}
}
}
}
-- ************************************************* Rodrigo Dias Ferreira Master Student of Computational Engineering Technische Universität Dresden - Germany Mobile Phone:+49 171 3158797 E-mail: rodrigodias_at_[hidden] ************************************************* Jetzt 1 Monat kostenlos! GMX FreeDSL - Telefonanschluss + DSL für nur 17,95 Euro/mtl.!* http://dsl.gmx.de/?ac=OM.AD.PD003K11308T4569a
Boost-users list run by williamkempf at hotmail.com, kalb at libertysoft.com, bjorn.karlsson at readsoft.com, gregod at cs.rpi.edu, wekempf at cox.net