Commit e92b8eaa authored by Tiago Peixoto's avatar Tiago Peixoto
Browse files

Replace shared_ptr by weak_ptr in Python descriptors and iterators

parent b7785f2d
...@@ -378,6 +378,12 @@ string get_graph_type(GraphInterface& g) ...@@ -378,6 +378,12 @@ string get_graph_type(GraphInterface& g)
return name; return name;
} }
size_t get_ptr(std::shared_ptr<GraphInterface::multigraph_t>& p)
{
return size_t(p.get());
};
// numpy array interface weirdness // numpy array interface weirdness
void* do_import_array() void* do_import_array()
{ {
...@@ -484,7 +490,8 @@ BOOST_PYTHON_MODULE(libgraph_tool_core) ...@@ -484,7 +490,8 @@ BOOST_PYTHON_MODULE(libgraph_tool_core)
.def("shrink_to_fit", &GraphInterface::shrink_to_fit) .def("shrink_to_fit", &GraphInterface::shrink_to_fit)
.def("get_graph_index", &GraphInterface::get_graph_index) .def("get_graph_index", &GraphInterface::get_graph_index)
.def("copy_vertex_property", &GraphInterface::copy_vertex_property) .def("copy_vertex_property", &GraphInterface::copy_vertex_property)
.def("copy_edge_property", &GraphInterface::copy_edge_property); .def("copy_edge_property", &GraphInterface::copy_edge_property)
.def("get_graph_ptr", &GraphInterface::get_graph_ptr);
class_<GraphInterface::vertex_index_map_t>("vertex_index_map", no_init); class_<GraphInterface::vertex_index_map_t>("vertex_index_map", no_init);
class_<GraphInterface::edge_index_map_t>("edge_index_map", no_init); class_<GraphInterface::edge_index_map_t>("edge_index_map", no_init);
...@@ -513,6 +520,10 @@ BOOST_PYTHON_MODULE(libgraph_tool_core) ...@@ -513,6 +520,10 @@ BOOST_PYTHON_MODULE(libgraph_tool_core)
float_from_convertible<double>(); float_from_convertible<double>();
float_from_convertible<long double>(); float_from_convertible<long double>();
class_<std::shared_ptr<GraphInterface::multigraph_t>>
("shared_ptr<multigraph_t>", no_init)
.def("get", &get_ptr);
#ifdef HAVE_SCIPY #ifdef HAVE_SCIPY
to_python_converter<py::object, scxx_to_python<py::object> >(); to_python_converter<py::object, scxx_to_python<py::object> >();
to_python_converter<py::tuple, scxx_to_python<py::tuple> >(); to_python_converter<py::tuple, scxx_to_python<py::tuple> >();
......
...@@ -38,7 +38,7 @@ struct get_vertex_iterator ...@@ -38,7 +38,7 @@ struct get_vertex_iterator
void operator()(Graph& g, GraphInterface& gi, void operator()(Graph& g, GraphInterface& gi,
python::object& iter) const python::object& iter) const
{ {
std::shared_ptr<Graph> gp = retrieve_graph_view<Graph>(gi, g); auto gp = retrieve_graph_view<Graph>(gi, g);
typedef typename graph_traits<Graph>::vertex_iterator vertex_iterator; typedef typename graph_traits<Graph>::vertex_iterator vertex_iterator;
iter = python::object(PythonIterator<Graph, PythonVertex<Graph>, iter = python::object(PythonIterator<Graph, PythonVertex<Graph>,
vertex_iterator>(gp, vertices(g))); vertex_iterator>(gp, vertices(g)));
...@@ -60,7 +60,7 @@ struct get_vertex_soft ...@@ -60,7 +60,7 @@ struct get_vertex_soft
template <class Graph> template <class Graph>
void operator()(Graph& g, GraphInterface& gi, size_t i, python::object& v) const void operator()(Graph& g, GraphInterface& gi, size_t i, python::object& v) const
{ {
std::shared_ptr<Graph> gp = retrieve_graph_view<Graph>(gi, g); auto gp = retrieve_graph_view<Graph>(gi, g);
if (i < num_vertices(g)) if (i < num_vertices(g))
v = python::object(PythonVertex<Graph>(gp, vertex(i, g))); v = python::object(PythonVertex<Graph>(gp, vertex(i, g)));
else else
...@@ -74,7 +74,7 @@ struct get_vertex_hard ...@@ -74,7 +74,7 @@ struct get_vertex_hard
template <class Graph> template <class Graph>
void operator()(Graph& g, GraphInterface& gi, size_t i, python::object& v) const void operator()(Graph& g, GraphInterface& gi, size_t i, python::object& v) const
{ {
std::shared_ptr<Graph> gp = retrieve_graph_view<Graph>(gi, g); auto gp = retrieve_graph_view<Graph>(gi, g);
size_t c = 0; size_t c = 0;
for (auto vi : vertices_range(g)) for (auto vi : vertices_range(g))
{ {
...@@ -110,7 +110,7 @@ struct get_edge_iterator ...@@ -110,7 +110,7 @@ struct get_edge_iterator
void operator()(Graph& g, GraphInterface& gi, python::object& iter) void operator()(Graph& g, GraphInterface& gi, python::object& iter)
const const
{ {
std::shared_ptr<Graph> gp = retrieve_graph_view<Graph>(gi, g); auto gp = retrieve_graph_view<Graph>(gi, g);
typedef typename graph_traits<Graph>::edge_iterator edge_iterator; typedef typename graph_traits<Graph>::edge_iterator edge_iterator;
iter = python::object(PythonIterator<Graph, PythonEdge<Graph>, iter = python::object(PythonIterator<Graph, PythonEdge<Graph>,
edge_iterator>(gp, edges(g))); edge_iterator>(gp, edges(g)));
...@@ -131,7 +131,7 @@ struct add_new_vertex ...@@ -131,7 +131,7 @@ struct add_new_vertex
void operator()(Graph& g, GraphInterface& gi, size_t n, void operator()(Graph& g, GraphInterface& gi, size_t n,
python::object& new_v) const python::object& new_v) const
{ {
std::shared_ptr<Graph> gp = retrieve_graph_view<Graph>(gi, g); auto gp = retrieve_graph_view<Graph>(gi, g);
if (n != 1) if (n != 1)
{ {
for (size_t i = 0; i < n; ++i) for (size_t i = 0; i < n; ++i)
...@@ -204,7 +204,7 @@ struct add_new_edge ...@@ -204,7 +204,7 @@ struct add_new_edge
void operator()(Graph& g, GraphInterface& gi, size_t s, size_t t, void operator()(Graph& g, GraphInterface& gi, size_t s, size_t t,
python::object& new_e) const python::object& new_e) const
{ {
std::shared_ptr<Graph> gp = retrieve_graph_view<Graph>(gi, g); auto gp = retrieve_graph_view<Graph>(gi, g);
auto e = add_edge(vertex(s, g), vertex(t, g), g).first; auto e = add_edge(vertex(s, g), vertex(t, g), g).first;
new_e = python::object(PythonEdge<Graph>(gp, e)); new_e = python::object(PythonEdge<Graph>(gp, e));
} }
...@@ -249,7 +249,7 @@ struct get_edge_dispatch ...@@ -249,7 +249,7 @@ struct get_edge_dispatch
void operator()(Graph& g, GraphInterface& gi, size_t s, size_t t, void operator()(Graph& g, GraphInterface& gi, size_t s, size_t t,
bool all_edges, boost::python::list& es) const bool all_edges, boost::python::list& es) const
{ {
std::shared_ptr<Graph> gp = retrieve_graph_view<Graph>(gi, g); auto gp = retrieve_graph_view<Graph>(gi, g);
size_t k_t = is_directed::apply<Graph>::type::value ? size_t k_t = is_directed::apply<Graph>::type::value ?
in_degreeS()(t, g) : out_degree(t, g); in_degreeS()(t, g) : out_degree(t, g);
if (out_degree(s, g) <= k_t) if (out_degree(s, g) <= k_t)
...@@ -396,8 +396,8 @@ struct export_python_interface ...@@ -396,8 +396,8 @@ struct export_python_interface
"Return the target vertex.") "Return the target vertex.")
.def("is_valid", &PythonEdge<Graph>::is_valid, .def("is_valid", &PythonEdge<Graph>::is_valid,
"Return whether the edge is valid.") "Return whether the edge is valid.")
.def("graph_ptr", &PythonVertex<Graph>::get_graph_ptr) .def("graph_ptr", &PythonEdge<Graph>::get_graph_ptr)
.def("graph_type", &PythonVertex<Graph>::get_graph_type) .def("graph_type", &PythonEdge<Graph>::get_graph_type)
.def("__str__", &PythonEdge<Graph>::get_string) .def("__str__", &PythonEdge<Graph>::get_string)
.def("__hash__", &PythonEdge<Graph>::get_hash); .def("__hash__", &PythonEdge<Graph>::get_hash);
...@@ -421,7 +421,7 @@ struct export_python_interface ...@@ -421,7 +421,7 @@ struct export_python_interface
edge_iterator> >("EdgeIterator", no_init) edge_iterator> >("EdgeIterator", no_init)
.def("__iter__", objects::identity_function()) .def("__iter__", objects::identity_function())
.def("__next__", &PythonIterator<Graph, PythonEdge<Graph>, .def("__next__", &PythonIterator<Graph, PythonEdge<Graph>,
edge_iterator>::next) edge_iterator>::next)
.def("next", &PythonIterator<Graph, PythonEdge<Graph>, .def("next", &PythonIterator<Graph, PythonEdge<Graph>,
edge_iterator>::next); edge_iterator>::next);
......
...@@ -65,20 +65,19 @@ template <class Graph, class Descriptor, class Iterator> ...@@ -65,20 +65,19 @@ template <class Graph, class Descriptor, class Iterator>
class PythonIterator class PythonIterator
{ {
public: public:
PythonIterator(std::shared_ptr<Graph>& gp, PythonIterator() = delete;
std::pair<Iterator,Iterator> e) explicit PythonIterator(const std::weak_ptr<Graph>& gp,
: _g(gp), _e(e) {} const std::pair<Iterator,Iterator>& range)
: _g(gp), _range(range) {}
Descriptor next() Descriptor next()
{ {
if (_e.first == _e.second) if (_range.first == _range.second || _g.expired())
boost::python::objects::stop_iteration_error(); boost::python::objects::stop_iteration_error();
Descriptor e(_g, *_e.first); return Descriptor(_g, *(_range.first++));
++_e.first;
return e;
} }
private: private:
std::shared_ptr<Graph> _g; std::weak_ptr<Graph> _g;
std::pair<Iterator,Iterator> _e; std::pair<Iterator,Iterator> _range;
}; };
#ifdef HAVE_BOOST_COROUTINE #ifdef HAVE_BOOST_COROUTINE
...@@ -121,17 +120,16 @@ template <class Graph> ...@@ -121,17 +120,16 @@ template <class Graph>
class PythonVertex : public VertexBase class PythonVertex : public VertexBase
{ {
public: public:
PythonVertex(std::shared_ptr<Graph> g, GraphInterface::vertex_t v): PythonVertex(std::weak_ptr<Graph> g, GraphInterface::vertex_t v):
_g(g), _v(v) {} _g(g), _v(v) {}
bool is_valid() const bool is_valid() const
{ {
std::shared_ptr<Graph> gp(_g); if (_g.expired())
Graph* g = gp.get();
if (g == nullptr)
return false; return false;
return ((_v != boost::graph_traits<Graph>::null_vertex()) && std::shared_ptr<Graph> gp = _g.lock();
(_v < num_vertices(*g))); Graph& g = *gp.get();
return _v < num_vertices(g);
} }
void check_valid() const void check_valid() const
...@@ -159,23 +157,16 @@ public: ...@@ -159,23 +157,16 @@ public:
template<class PMap> template<class PMap>
void operator()(const Graph& g, void operator()(const Graph& g,
typename boost::graph_traits<Graph>::vertex_descriptor v, typename boost::graph_traits<Graph>::vertex_descriptor v,
const boost::any& aweight, boost::python::object& deg, const PMap& weight, boost::python::object& deg) const
bool& found, PMap) const
{ {
try deg = boost::python::object(DegSelector()(v, g, weight));
{
const PMap& weight = boost::any_cast<const PMap&>(aweight);
deg = boost::python::object(DegSelector()(v, g, weight));
found = true;
}
catch (boost::bad_any_cast&) {}
} }
}; };
size_t get_in_degree() const size_t get_in_degree() const
{ {
check_valid(); check_valid();
std::shared_ptr<Graph> gp(_g); std::shared_ptr<Graph> gp = _g.lock();
Graph& g = *gp.get(); Graph& g = *gp.get();
size_t in_deg; size_t in_deg;
get_degree<in_degreeS>()(g, _v, in_deg); get_degree<in_degreeS>()(g, _v, in_deg);
...@@ -184,25 +175,24 @@ public: ...@@ -184,25 +175,24 @@ public:
boost::python::object get_weighted_in_degree(boost::any pmap) const boost::python::object get_weighted_in_degree(boost::any pmap) const
{ {
std::shared_ptr<Graph> gp(_g); check_valid();
std::shared_ptr<Graph> gp = _g.lock();
Graph& g = *gp.get(); Graph& g = *gp.get();
boost::python::object in_deg; boost::python::object in_deg;
bool found = false; if (!belongs<edge_scalar_properties>()(pmap))
boost::mpl::for_each<edge_scalar_properties>(std::bind(get_degree<in_degreeS>(),
std::ref(g), _v,
std::ref(pmap),
std::ref(in_deg),
std::ref(found),
std::placeholders::_1));
if (!found)
throw ValueException("edge weight property must be of scalar type"); throw ValueException("edge weight property must be of scalar type");
gt_dispatch<>()(std::bind(get_degree<in_degreeS>(),
std::ref(g), _v,
std::placeholders::_1,
std::ref(in_deg)),
edge_scalar_properties())(pmap);
return in_deg; return in_deg;
} }
size_t get_out_degree() const size_t get_out_degree() const
{ {
check_valid(); check_valid();
std::shared_ptr<Graph> gp(_g); std::shared_ptr<Graph> gp = _g.lock();
Graph& g = *gp.get(); Graph& g = *gp.get();
size_t out_deg; size_t out_deg;
get_degree<out_degreeS>()(g, _v, out_deg); get_degree<out_degreeS>()(g, _v, out_deg);
...@@ -212,18 +202,17 @@ public: ...@@ -212,18 +202,17 @@ public:
boost::python::object get_weighted_out_degree(boost::any pmap) const boost::python::object get_weighted_out_degree(boost::any pmap) const
{ {
std::shared_ptr<Graph> gp(_g); check_valid();
std::shared_ptr<Graph> gp = _g.lock();
Graph& g = *gp.get(); Graph& g = *gp.get();
boost::python::object out_deg; boost::python::object out_deg;
bool found = false; if (!belongs<edge_scalar_properties>()(pmap))
boost::mpl::for_each<edge_scalar_properties>(std::bind(get_degree<out_degreeS>(),
std::ref(g), _v,
std::ref(pmap),
std::ref(out_deg),
std::ref(found),
std::placeholders::_1));
if (!found)
throw ValueException("edge weight property must be of scalar type"); throw ValueException("edge weight property must be of scalar type");
gt_dispatch<>()(std::bind(get_degree<out_degreeS>(),
std::ref(g), _v,
std::placeholders::_1,
std::ref(out_deg)),
edge_scalar_properties())(pmap);
return out_deg; return out_deg;
} }
...@@ -231,25 +220,25 @@ public: ...@@ -231,25 +220,25 @@ public:
boost::python::object out_edges() const boost::python::object out_edges() const
{ {
check_valid(); check_valid();
std::shared_ptr<Graph> pg(_g); std::shared_ptr<Graph> gp = _g.lock();
Graph& g = *pg; Graph& g = *gp.get();
typedef typename boost::graph_traits<Graph>::out_edge_iterator typedef typename boost::graph_traits<Graph>::out_edge_iterator
out_edge_iterator; out_edge_iterator;
return boost::python::object(PythonIterator<Graph,PythonEdge<Graph>, return boost::python::object(PythonIterator<Graph,PythonEdge<Graph>,
out_edge_iterator> out_edge_iterator>
(pg, boost::out_edges(_v, g))); (_g, boost::out_edges(_v, g)));
} }
boost::python::object in_edges() const boost::python::object in_edges() const
{ {
check_valid(); check_valid();
std::shared_ptr<Graph> pg(_g); std::shared_ptr<Graph> gp = _g.lock();
Graph& g = *pg; Graph& g = *gp.get();
typedef typename in_edge_iteratorS<Graph>::type typedef typename in_edge_iteratorS<Graph>::type
in_edge_iterator; in_edge_iterator;
return boost::python::object(PythonIterator<Graph, PythonEdge<Graph>, return boost::python::object(PythonIterator<Graph, PythonEdge<Graph>,
in_edge_iterator> in_edge_iterator>
(pg, in_edge_iteratorS<Graph>::get_edges(_v, g))); (_g, in_edge_iteratorS<Graph>::get_edges(_v, g)));
} }
std::string get_string() const std::string get_string() const
...@@ -270,8 +259,10 @@ public: ...@@ -270,8 +259,10 @@ public:
size_t get_graph_ptr() const size_t get_graph_ptr() const
{ {
std::shared_ptr<Graph> pg(_g); if (_g.expired())
return size_t(pg.get()); return 0;
std::shared_ptr<Graph> gp = _g.lock();
return size_t(gp.get());
} }
std::string get_graph_type() const std::string get_graph_type() const
...@@ -307,23 +298,20 @@ class PythonEdge : public EdgeBase ...@@ -307,23 +298,20 @@ class PythonEdge : public EdgeBase
{ {
public: public:
typedef typename boost::graph_traits<Graph>::edge_descriptor edge_descriptor; typedef typename boost::graph_traits<Graph>::edge_descriptor edge_descriptor;
PythonEdge(std::shared_ptr<Graph> g, edge_descriptor e) PythonEdge(std::weak_ptr<Graph> g, edge_descriptor e)
: _g(g), _e(e) {} : _g(g), _e(e) {}
bool is_valid() const bool is_valid() const
{ {
std::shared_ptr<Graph> gp(_g); if (_g.expired())
Graph* g = gp.get();
if (g == nullptr)
return false; return false;
std::shared_ptr<Graph> gp = _g.lock();
Graph& g = *gp.get();
auto s = source(_e, *g); auto s = source(_e, g);
auto t = target(_e, *g); auto t = target(_e, g);
return ((s != boost::graph_traits<Graph>::null_vertex()) && return ((s < num_vertices(g)) && (t < num_vertices(g)));
(s < num_vertices(*g)) &&
(t != boost::graph_traits<Graph>::null_vertex()) &&
(t < num_vertices(*g)));
} }
void check_valid() const void check_valid() const
...@@ -340,23 +328,24 @@ public: ...@@ -340,23 +328,24 @@ public:
PythonVertex<Graph> get_source() const PythonVertex<Graph> get_source() const
{ {
check_valid(); check_valid();
std::shared_ptr<Graph> pg(_g); std::shared_ptr<Graph> gp = _g.lock();
Graph& g = *pg; Graph& g = *gp.get();
return PythonVertex<Graph>(pg, source(_e, g)); return PythonVertex<Graph>(gp, source(_e, g));
} }
PythonVertex<Graph> get_target() const PythonVertex<Graph> get_target() const
{ {
check_valid(); check_valid();
std::shared_ptr<Graph> pg(_g); std::shared_ptr<Graph> gp = _g.lock();
Graph& g = *pg; Graph& g = *gp.get();
return PythonVertex<Graph>(pg, target(_e, g)); return PythonVertex<Graph>(gp, target(_e, g));
} }
std::string get_string() const std::string get_string() const
{ {
check_valid(); check_valid();
Graph& g = *std::shared_ptr<Graph>(_g); std::shared_ptr<Graph> gp = _g.lock();
Graph& g = *gp.get();
auto s = source(_e, g); auto s = source(_e, g);
auto t = target(_e, g); auto t = target(_e, g);
return "(" + boost::lexical_cast<std::string>(s) + ", " return "(" + boost::lexical_cast<std::string>(s) + ", "
...@@ -366,15 +355,18 @@ public: ...@@ -366,15 +355,18 @@ public:
size_t get_hash() const size_t get_hash() const
{ {
check_valid(); check_valid();
Graph& g = *std::shared_ptr<Graph>(_g); std::shared_ptr<Graph> gp = _g.lock();
Graph& g = *gp.get();
auto eindex = get(boost::edge_index_t(), g); auto eindex = get(boost::edge_index_t(), g);
return std::hash<size_t>()(eindex[_e]); return std::hash<size_t>()(eindex[_e]);
} }
size_t get_graph_ptr() const size_t get_graph_ptr() const
{ {
std::shared_ptr<Graph> pg(_g); if (_g.expired())
return site_t(pg.get()); return 0;
std::shared_ptr<Graph> gp = _g.lock();
return size_t(gp.get());
} }
std::string get_graph_type() const std::string get_graph_type() const
......
...@@ -115,7 +115,7 @@ public: ...@@ -115,7 +115,7 @@ public:
template <class Edge, class Graph> template <class Edge, class Graph>
void edge_relaxed(const Edge& e, Graph& g) void edge_relaxed(const Edge& e, Graph& g)
{ {
std::shared_ptr<Graph> gp = retrieve_graph_view<Graph>(_gi, g); auto gp = retrieve_graph_view<Graph>(_gi, g);
_yield(boost::python::object(PythonEdge<Graph>(gp, e))); _yield(boost::python::object(PythonEdge<Graph>(gp, e)));
} }
......
...@@ -39,56 +39,56 @@ public: ...@@ -39,56 +39,56 @@ public:
template <class Vertex, class Graph> template <class Vertex, class Graph>
void initialize_vertex(Vertex u, Graph& g) void initialize_vertex(Vertex u, Graph& g)
{ {
std::shared_ptr<Graph> gp = retrieve_graph_view<Graph>(_gi, g); auto gp = retrieve_graph_view<Graph>(_gi, g);
_vis.attr("initialize_vertex")(PythonVertex<Graph>(gp, u)); _vis.attr("initialize_vertex")(PythonVertex<Graph>(gp, u));
} }
template <class Vertex, class Graph> template <class Vertex, class Graph>
void discover_vertex(Vertex u, Graph& g) void discover_vertex(Vertex u, Graph& g)
{ {
std::shared_ptr<Graph> gp = retrieve_graph_view<Graph>(_gi, g); auto gp = retrieve_graph_view<Graph>(_gi, g);
_vis.attr("discover_vertex")(PythonVertex<Graph>(gp, u)); _vis.attr("discover_vertex")(PythonVertex<Graph>(gp, u));
} }
template <class Vertex, class Graph> template <class Vertex, class Graph>
void examine_vertex(Vertex u, Graph& g) void examine_vertex(Vertex u, Graph& g)