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)
return name;
}
size_t get_ptr(std::shared_ptr<GraphInterface::multigraph_t>& p)
{
return size_t(p.get());
};
// numpy array interface weirdness
void* do_import_array()
{
......@@ -484,7 +490,8 @@ BOOST_PYTHON_MODULE(libgraph_tool_core)
.def("shrink_to_fit", &GraphInterface::shrink_to_fit)
.def("get_graph_index", &GraphInterface::get_graph_index)
.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::edge_index_map_t>("edge_index_map", no_init);
......@@ -513,6 +520,10 @@ BOOST_PYTHON_MODULE(libgraph_tool_core)
float_from_convertible<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
to_python_converter<py::object, scxx_to_python<py::object> >();
to_python_converter<py::tuple, scxx_to_python<py::tuple> >();
......
......@@ -38,7 +38,7 @@ struct get_vertex_iterator
void operator()(Graph& g, GraphInterface& gi,
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;
iter = python::object(PythonIterator<Graph, PythonVertex<Graph>,
vertex_iterator>(gp, vertices(g)));
......@@ -60,7 +60,7 @@ struct get_vertex_soft
template <class Graph>
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))
v = python::object(PythonVertex<Graph>(gp, vertex(i, g)));
else
......@@ -74,7 +74,7 @@ struct get_vertex_hard
template <class Graph>
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;
for (auto vi : vertices_range(g))
{
......@@ -110,7 +110,7 @@ struct get_edge_iterator
void operator()(Graph& g, GraphInterface& gi, 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>::edge_iterator edge_iterator;
iter = python::object(PythonIterator<Graph, PythonEdge<Graph>,
edge_iterator>(gp, edges(g)));
......@@ -131,7 +131,7 @@ struct add_new_vertex
void operator()(Graph& g, GraphInterface& gi, size_t n,
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)
{
for (size_t i = 0; i < n; ++i)
......@@ -204,7 +204,7 @@ struct add_new_edge
void operator()(Graph& g, GraphInterface& gi, size_t s, size_t t,
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;
new_e = python::object(PythonEdge<Graph>(gp, e));
}
......@@ -249,7 +249,7 @@ struct get_edge_dispatch
void operator()(Graph& g, GraphInterface& gi, size_t s, size_t t,
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 ?
in_degreeS()(t, g) : out_degree(t, g);
if (out_degree(s, g) <= k_t)
......@@ -396,8 +396,8 @@ struct export_python_interface
"Return the target vertex.")
.def("is_valid", &PythonEdge<Graph>::is_valid,
"Return whether the edge is valid.")
.def("graph_ptr", &PythonVertex<Graph>::get_graph_ptr)
.def("graph_type", &PythonVertex<Graph>::get_graph_type)
.def("graph_ptr", &PythonEdge<Graph>::get_graph_ptr)
.def("graph_type", &PythonEdge<Graph>::get_graph_type)
.def("__str__", &PythonEdge<Graph>::get_string)
.def("__hash__", &PythonEdge<Graph>::get_hash);
......@@ -421,7 +421,7 @@ struct export_python_interface
edge_iterator> >("EdgeIterator", no_init)
.def("__iter__", objects::identity_function())
.def("__next__", &PythonIterator<Graph, PythonEdge<Graph>,
edge_iterator>::next)
edge_iterator>::next)
.def("next", &PythonIterator<Graph, PythonEdge<Graph>,
edge_iterator>::next);
......
......@@ -65,20 +65,19 @@ template <class Graph, class Descriptor, class Iterator>
class PythonIterator
{
public:
PythonIterator(std::shared_ptr<Graph>& gp,
std::pair<Iterator,Iterator> e)
: _g(gp), _e(e) {}
PythonIterator() = delete;
explicit PythonIterator(const std::weak_ptr<Graph>& gp,
const std::pair<Iterator,Iterator>& range)
: _g(gp), _range(range) {}
Descriptor next()
{
if (_e.first == _e.second)
if (_range.first == _range.second || _g.expired())
boost::python::objects::stop_iteration_error();
Descriptor e(_g, *_e.first);
++_e.first;
return e;
return Descriptor(_g, *(_range.first++));
}
private:
std::shared_ptr<Graph> _g;
std::pair<Iterator,Iterator> _e;
std::weak_ptr<Graph> _g;
std::pair<Iterator,Iterator> _range;
};
#ifdef HAVE_BOOST_COROUTINE
......@@ -121,17 +120,16 @@ template <class Graph>
class PythonVertex : public VertexBase
{
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) {}
bool is_valid() const
{
std::shared_ptr<Graph> gp(_g);
Graph* g = gp.get();
if (g == nullptr)
if (_g.expired())
return false;
return ((_v != boost::graph_traits<Graph>::null_vertex()) &&
(_v < num_vertices(*g)));
std::shared_ptr<Graph> gp = _g.lock();
Graph& g = *gp.get();
return _v < num_vertices(g);
}
void check_valid() const
......@@ -159,23 +157,16 @@ public:
template<class PMap>
void operator()(const Graph& g,
typename boost::graph_traits<Graph>::vertex_descriptor v,
const boost::any& aweight, boost::python::object& deg,
bool& found, PMap) const
const PMap& weight, boost::python::object& deg) const
{
try
{
const PMap& weight = boost::any_cast<const PMap&>(aweight);
deg = boost::python::object(DegSelector()(v, g, weight));
found = true;
}
catch (boost::bad_any_cast&) {}
deg = boost::python::object(DegSelector()(v, g, weight));
}
};
size_t get_in_degree() const
{
check_valid();
std::shared_ptr<Graph> gp(_g);
std::shared_ptr<Graph> gp = _g.lock();
Graph& g = *gp.get();
size_t in_deg;
get_degree<in_degreeS>()(g, _v, in_deg);
......@@ -184,25 +175,24 @@ public:
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();
boost::python::object in_deg;
bool found = false;
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)
if (!belongs<edge_scalar_properties>()(pmap))
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;
}
size_t get_out_degree() const
{
check_valid();
std::shared_ptr<Graph> gp(_g);
std::shared_ptr<Graph> gp = _g.lock();
Graph& g = *gp.get();
size_t out_deg;
get_degree<out_degreeS>()(g, _v, out_deg);
......@@ -212,18 +202,17 @@ public:
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();
boost::python::object out_deg;
bool found = false;
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)
if (!belongs<edge_scalar_properties>()(pmap))
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;
}
......@@ -231,25 +220,25 @@ public:
boost::python::object out_edges() const
{
check_valid();
std::shared_ptr<Graph> pg(_g);
Graph& g = *pg;
std::shared_ptr<Graph> gp = _g.lock();
Graph& g = *gp.get();
typedef typename boost::graph_traits<Graph>::out_edge_iterator
out_edge_iterator;
return boost::python::object(PythonIterator<Graph,PythonEdge<Graph>,
out_edge_iterator>
(pg, boost::out_edges(_v, g)));
(_g, boost::out_edges(_v, g)));
}
boost::python::object in_edges() const
{
check_valid();
std::shared_ptr<Graph> pg(_g);
Graph& g = *pg;
std::shared_ptr<Graph> gp = _g.lock();
Graph& g = *gp.get();
typedef typename in_edge_iteratorS<Graph>::type
in_edge_iterator;
return boost::python::object(PythonIterator<Graph, PythonEdge<Graph>,
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
......@@ -270,8 +259,10 @@ public:
size_t get_graph_ptr() const
{
std::shared_ptr<Graph> pg(_g);
return size_t(pg.get());
if (_g.expired())
return 0;
std::shared_ptr<Graph> gp = _g.lock();
return size_t(gp.get());
}
std::string get_graph_type() const
......@@ -307,23 +298,20 @@ class PythonEdge : public EdgeBase
{
public:
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) {}
bool is_valid() const
{
std::shared_ptr<Graph> gp(_g);
Graph* g = gp.get();
if (g == nullptr)
if (_g.expired())
return false;
std::shared_ptr<Graph> gp = _g.lock();
Graph& g = *gp.get();
auto s = source(_e, *g);
auto t = target(_e, *g);
auto s = source(_e, g);
auto t = target(_e, g);
return ((s != boost::graph_traits<Graph>::null_vertex()) &&
(s < num_vertices(*g)) &&
(t != boost::graph_traits<Graph>::null_vertex()) &&
(t < num_vertices(*g)));
return ((s < num_vertices(g)) && (t < num_vertices(g)));
}
void check_valid() const
......@@ -340,23 +328,24 @@ public:
PythonVertex<Graph> get_source() const
{
check_valid();
std::shared_ptr<Graph> pg(_g);
Graph& g = *pg;
return PythonVertex<Graph>(pg, source(_e, g));
std::shared_ptr<Graph> gp = _g.lock();
Graph& g = *gp.get();
return PythonVertex<Graph>(gp, source(_e, g));
}
PythonVertex<Graph> get_target() const
{
check_valid();
std::shared_ptr<Graph> pg(_g);
Graph& g = *pg;
return PythonVertex<Graph>(pg, target(_e, g));
std::shared_ptr<Graph> gp = _g.lock();
Graph& g = *gp.get();
return PythonVertex<Graph>(gp, target(_e, g));
}
std::string get_string() const
{
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 t = target(_e, g);
return "(" + boost::lexical_cast<std::string>(s) + ", "
......@@ -366,15 +355,18 @@ public:
size_t get_hash() const
{
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);
return std::hash<size_t>()(eindex[_e]);
}
size_t get_graph_ptr() const
{
std::shared_ptr<Graph> pg(_g);
return site_t(pg.get());
if (_g.expired())
return 0;
std::shared_ptr<Graph> gp = _g.lock();
return size_t(gp.get());
}
std::string get_graph_type() const
......
......@@ -115,7 +115,7 @@ public:
template <class Edge, class Graph>
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)));
}
......
......@@ -39,56 +39,56 @@ public:
template <class Vertex, class Graph>
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));
}
template <class Vertex, class Graph>
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));
}
template <class Vertex, class Graph>
void examine_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("examine_vertex")(PythonVertex<Graph>(gp, u));
}
template <class Edge, class Graph>
void examine_edge(Edge e, Graph& g)
{
std::shared_ptr<Graph> gp = retrieve_graph_view<Graph>(_gi, g);
auto gp = retrieve_graph_view<Graph>(_gi, g);
_vis.attr("examine_edge") (PythonEdge<Graph>(gp, e));
}
template <class Edge, class Graph>
void edge_relaxed(Edge e, Graph& g)
{
std::shared_ptr<Graph> gp = retrieve_graph_view<Graph>(_gi, g);
auto gp = retrieve_graph_view<Graph>(_gi, g);
_vis.attr("edge_relaxed") (PythonEdge<Graph>(gp, e));
}
template <class Edge, class Graph>
void edge_not_relaxed(Edge e, Graph& g)
{
std::shared_ptr<Graph> gp = retrieve_graph_view<Graph>(_gi, g);
auto gp = retrieve_graph_view<Graph>(_gi, g);
_vis.attr("edge_not_relaxed") (PythonEdge<Graph>(gp, e));
}
template <class Edge, class Graph>
void black_target(Edge e, Graph& g)
{
std::shared_ptr<Graph> gp = retrieve_graph_view<Graph>(_gi, g);
auto gp = retrieve_graph_view<Graph>(_gi, g);
_vis.attr("black_target") (PythonEdge<Graph>(gp, e));
}
template <class Vertex, class Graph>
void finish_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("finish_vertex")(PythonVertex<Graph>(gp, u));
}
......
......@@ -39,7 +39,7 @@ public:
template <class Edge, class Graph>
void examine_edge(Edge e, Graph& g)
{
std::shared_ptr<Graph> gp = retrieve_graph_view<Graph>(_gi, g);
auto gp = retrieve_graph_view<Graph>(_gi, g);
_vis.attr("examine_edge")
(PythonEdge<Graph>(gp, e));
}
......@@ -47,7 +47,7 @@ public:
template <class Edge, class Graph>
void edge_relaxed(Edge e, Graph& g)
{
std::shared_ptr<Graph> gp = retrieve_graph_view<Graph>(_gi, g);
auto gp = retrieve_graph_view<Graph>(_gi, g);
_vis.attr("edge_relaxed")
(PythonEdge<Graph>(gp, e));
}
......@@ -55,7 +55,7 @@ public:
template <class Edge, class Graph>
void edge_not_relaxed(Edge e, Graph& g)
{
std::shared_ptr<Graph> gp = retrieve_graph_view<Graph>(_gi, g);
auto gp = retrieve_graph_view<Graph>(_gi, g);
_vis.attr("edge_not_relaxed")
(PythonEdge<Graph>(gp, e));
}
......@@ -63,7 +63,7 @@ public:
template <class Edge, class Graph>
void edge_minimized(Edge e, Graph& g)
{
std::shared_ptr<Graph> gp = retrieve_graph_view<Graph>(_gi, g);
auto gp = retrieve_graph_view<Graph>(_gi, g);
_vis.attr("edge_minimized")
(PythonEdge<Graph>(gp, e));
}
......@@ -71,7 +71,7 @@ public:
template <class Edge, class Graph>
void edge_not_minimized(Edge e, Graph& g)
{
std::shared_ptr<Graph> gp = retrieve_graph_view<Graph>(_gi, g);
auto gp = retrieve_graph_view<Graph>(_gi, g);
_vis.attr("edge_not_minimized")
(PythonEdge<Graph>(gp, e));
}
......
......@@ -42,63 +42,63 @@ public:
template <class Vertex, class Graph>
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));
}
template <class Vertex, class Graph>
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));
}
template <class Vertex, class Graph>
void examine_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("examine_vertex")(PythonVertex<Graph>(gp, u));
}
template <class Edge, class Graph>
void examine_edge(Edge e, Graph& g)
{
std::shared_ptr<Graph> gp = retrieve_graph_view<Graph>(_gi, g);
auto gp = retrieve_graph_view<Graph>(_gi, g);
_vis.attr("examine_edge")(PythonEdge<Graph>(gp, e));
}
template <class Edge, class Graph>
void tree_edge(Edge e, Graph& g)
{
std::shared_ptr<Graph> gp = retrieve_graph_view<Graph>(_gi, g);
auto gp = retrieve_graph_view<Graph>(_gi, g);
_vis.attr("tree_edge")(PythonEdge<Graph>(gp, e));
}
template <class Edge, class Graph>
void non_tree_edge(Edge e, Graph& g)
{
std::shared_ptr<Graph> gp = retrieve_graph_view<Graph>(_gi, g);
auto gp = retrieve_graph_view<Graph>(_gi, g);
_vis.attr("non_tree_edge")(PythonEdge<Graph>(gp, e));
}
template <class Edge, class Graph>
void gray_target(Edge e, Graph& g)
{
std::shared_ptr<Graph> gp = retrieve_graph_view<Graph>(_gi, g);
auto gp = retrieve_graph_view<Graph>(_gi, g);
_vis.attr("gray_target")(PythonEdge<Graph>(gp, e));
}
template <class Edge, class Graph>
void black_target(Edge e, Graph& g)
{
std::shared_ptr<Graph> gp = retrieve_graph_view<Graph>(_gi, g);
auto gp = retrieve_graph_view<Graph>(_gi, g);
_vis.attr("black_target")(PythonEdge<Graph>(gp, e));
}
template <class Vertex, class Graph>
void finish_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("finish_vertex")(PythonVertex<Graph>(gp, u));
}
......@@ -135,7 +135,7 @@ public:
template <class Edge, class Graph>
void tree_edge(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)));
}
......
......@@ -35,54 +35,54 @@ public:
template <class Vertex, class Graph>