annotate DEPENDENCIES/generic/include/boost/graph/distributed/named_graph.hpp @ 125:34e428693f5d vext

Vext -> Repoint
author Chris Cannam
date Thu, 14 Jun 2018 11:15:39 +0100
parents c530137014c0
children
rev   line source
Chris@16 1 // Copyright (C) 2007 Douglas Gregor
Chris@16 2 // Copyright (C) 2007 Hartmut Kaiser
Chris@16 3
Chris@16 4 // Use, modification and distribution is subject to the Boost Software
Chris@16 5 // License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
Chris@16 6 // http://www.boost.org/LICENSE_1_0.txt)
Chris@16 7
Chris@16 8 // TODO:
Chris@16 9 // - Cache (some) remote vertex names?
Chris@16 10 #ifndef BOOST_GRAPH_DISTRIBUTED_NAMED_GRAPH_HPP
Chris@16 11 #define BOOST_GRAPH_DISTRIBUTED_NAMED_GRAPH_HPP
Chris@16 12
Chris@16 13 #ifndef BOOST_GRAPH_USE_MPI
Chris@16 14 #error "Parallel BGL files should not be included unless <boost/graph/use_mpi.hpp> has been included"
Chris@16 15 #endif
Chris@16 16
Chris@16 17 #include <boost/assert.hpp>
Chris@16 18 #include <boost/graph/named_graph.hpp>
Chris@16 19 #include <boost/functional/hash.hpp>
Chris@16 20 #include <boost/variant.hpp>
Chris@16 21 #include <boost/graph/parallel/simple_trigger.hpp>
Chris@16 22 #include <boost/graph/parallel/process_group.hpp>
Chris@16 23 #include <boost/graph/parallel/detail/property_holders.hpp>
Chris@16 24
Chris@16 25 namespace boost { namespace graph { namespace distributed {
Chris@16 26
Chris@16 27 using boost::parallel::trigger_receive_context;
Chris@16 28 using boost::detail::parallel::pair_with_property;
Chris@16 29
Chris@16 30 /*******************************************************************
Chris@16 31 * Hashed distribution of named entities *
Chris@16 32 *******************************************************************/
Chris@16 33
Chris@16 34 template<typename T>
Chris@16 35 struct hashed_distribution
Chris@16 36 {
Chris@16 37 template<typename ProcessGroup>
Chris@16 38 hashed_distribution(const ProcessGroup& pg, std::size_t /*num_vertices*/ = 0)
Chris@16 39 : n(num_processes(pg)) { }
Chris@16 40
Chris@16 41 int operator()(const T& value) const
Chris@16 42 {
Chris@16 43 return hasher(value) % n;
Chris@16 44 }
Chris@16 45
Chris@16 46 std::size_t n;
Chris@16 47 hash<T> hasher;
Chris@16 48 };
Chris@16 49
Chris@16 50 /// Specialization for named graphs
Chris@16 51 template <typename InDistribution, typename VertexProperty, typename VertexSize,
Chris@16 52 typename ProcessGroup,
Chris@16 53 typename ExtractName
Chris@16 54 = typename internal_vertex_name<VertexProperty>::type>
Chris@16 55 struct select_distribution
Chris@16 56 {
Chris@16 57 private:
Chris@16 58 /// The type used to name vertices in the graph
Chris@16 59 typedef typename remove_cv<
Chris@16 60 typename remove_reference<
Chris@16 61 typename ExtractName::result_type>::type>::type
Chris@16 62 vertex_name_type;
Chris@16 63
Chris@16 64 public:
Chris@16 65 /**
Chris@16 66 * The @c type field provides a distribution object that maps
Chris@16 67 * vertex names to processors. The distribution object will be
Chris@16 68 * constructed with the process group over which communication will
Chris@16 69 * occur. The distribution object shall also be a function
Chris@16 70 * object mapping from the type of the name to a processor number
Chris@16 71 * in @c [0, @c p) (for @c p processors). By default, the mapping
Chris@16 72 * function uses the @c boost::hash value of the name, modulo @c p.
Chris@16 73 */
Chris@16 74 typedef typename mpl::if_<is_same<InDistribution, defaultS>,
Chris@16 75 hashed_distribution<vertex_name_type>,
Chris@16 76 InDistribution>::type
Chris@16 77 type;
Chris@16 78
Chris@16 79 /// for named graphs the default type is the same as the stored distribution
Chris@16 80 /// type
Chris@16 81 typedef type default_type;
Chris@16 82 };
Chris@16 83
Chris@16 84 /// Specialization for non-named graphs
Chris@16 85 template <typename InDistribution, typename VertexProperty, typename VertexSize,
Chris@16 86 typename ProcessGroup>
Chris@16 87 struct select_distribution<InDistribution, VertexProperty, VertexSize,
Chris@16 88 ProcessGroup, void>
Chris@16 89 {
Chris@16 90 /// the distribution type stored in the graph for non-named graphs should be
Chris@16 91 /// the variant_distribution type
Chris@16 92 typedef typename mpl::if_<is_same<InDistribution, defaultS>,
Chris@16 93 boost::parallel::variant_distribution<ProcessGroup,
Chris@16 94 VertexSize>,
Chris@16 95 InDistribution>::type type;
Chris@16 96
Chris@16 97 /// default_type is used as the distribution functor for the
Chris@16 98 /// adjacency_list, it should be parallel::block by default
Chris@16 99 typedef typename mpl::if_<is_same<InDistribution, defaultS>,
Chris@16 100 boost::parallel::block, type>::type
Chris@16 101 default_type;
Chris@16 102 };
Chris@16 103
Chris@16 104
Chris@16 105 /*******************************************************************
Chris@16 106 * Named graph mixin *
Chris@16 107 *******************************************************************/
Chris@16 108
Chris@16 109 /**
Chris@16 110 * named_graph is a mixin that provides names for the vertices of a
Chris@16 111 * graph, including a mapping from names to vertices. Graph types that
Chris@16 112 * may or may not be have vertex names (depending on the properties
Chris@16 113 * supplied by the user) should use maybe_named_graph.
Chris@16 114 *
Chris@16 115 * Template parameters:
Chris@16 116 *
Chris@16 117 * Graph: the graph type that derives from named_graph
Chris@16 118 *
Chris@16 119 * Vertex: the type of a vertex descriptor in Graph. Note: we cannot
Chris@16 120 * use graph_traits here, because the Graph is not yet defined.
Chris@16 121 *
Chris@16 122 * VertexProperty: the type of the property stored along with the
Chris@16 123 * vertex.
Chris@16 124 *
Chris@16 125 * ProcessGroup: the process group over which the distributed name
Chris@16 126 * graph mixin will communicate.
Chris@16 127 */
Chris@16 128 template<typename Graph, typename Vertex, typename Edge, typename Config>
Chris@16 129 class named_graph
Chris@16 130 {
Chris@16 131 public:
Chris@16 132 /// Messages passed within the distributed named graph
Chris@16 133 enum message_kind {
Chris@16 134 /**
Chris@16 135 * Requests the addition of a vertex on a remote processor. The
Chris@16 136 * message data is a @c vertex_name_type.
Chris@16 137 */
Chris@16 138 msg_add_vertex_name,
Chris@16 139
Chris@16 140 /**
Chris@16 141 * Requests the addition of a vertex on a remote processor. The
Chris@16 142 * message data is a @c vertex_name_type. The remote processor
Chris@16 143 * will send back a @c msg_add_vertex_name_reply message
Chris@16 144 * containing the vertex descriptor.
Chris@16 145 */
Chris@16 146 msg_add_vertex_name_with_reply,
Chris@16 147
Chris@16 148 /**
Chris@16 149 * Requests the vertex descriptor corresponding to the given
Chris@16 150 * vertex name. The remote process will reply with a
Chris@16 151 * @c msg_find_vertex_reply message containing the answer.
Chris@16 152 */
Chris@16 153 msg_find_vertex,
Chris@16 154
Chris@16 155 /**
Chris@16 156 * Requests the addition of an edge on a remote processor. The
Chris@16 157 * data stored in these messages is a @c pair<source, target>@,
Chris@16 158 * where @c source and @c target may be either names (of type @c
Chris@16 159 * vertex_name_type) or vertex descriptors, depending on what
Chris@16 160 * information we have locally.
Chris@16 161 */
Chris@16 162 msg_add_edge_name_name,
Chris@16 163 msg_add_edge_vertex_name,
Chris@16 164 msg_add_edge_name_vertex,
Chris@16 165
Chris@16 166 /**
Chris@16 167 * These messages are identical to msg_add_edge_*_*, except that
Chris@16 168 * the process actually adding the edge will send back a @c
Chris@16 169 * pair<edge_descriptor,bool>
Chris@16 170 */
Chris@16 171 msg_add_edge_name_name_with_reply,
Chris@16 172 msg_add_edge_vertex_name_with_reply,
Chris@16 173 msg_add_edge_name_vertex_with_reply,
Chris@16 174
Chris@16 175 /**
Chris@16 176 * Requests the addition of an edge with a property on a remote
Chris@16 177 * processor. The data stored in these messages is a @c
Chris@16 178 * pair<vertex_property_type, pair<source, target>>@, where @c
Chris@16 179 * source and @c target may be either names (of type @c
Chris@16 180 * vertex_name_type) or vertex descriptors, depending on what
Chris@16 181 * information we have locally.
Chris@16 182 */
Chris@16 183 msg_add_edge_name_name_with_property,
Chris@16 184 msg_add_edge_vertex_name_with_property,
Chris@16 185 msg_add_edge_name_vertex_with_property,
Chris@16 186
Chris@16 187 /**
Chris@16 188 * These messages are identical to msg_add_edge_*_*_with_property,
Chris@16 189 * except that the process actually adding the edge will send back
Chris@16 190 * a @c pair<edge_descriptor,bool>.
Chris@16 191 */
Chris@16 192 msg_add_edge_name_name_with_reply_and_property,
Chris@16 193 msg_add_edge_vertex_name_with_reply_and_property,
Chris@16 194 msg_add_edge_name_vertex_with_reply_and_property
Chris@16 195 };
Chris@16 196
Chris@16 197 /// The vertex descriptor type
Chris@16 198 typedef Vertex vertex_descriptor;
Chris@16 199
Chris@16 200 /// The edge descriptor type
Chris@16 201 typedef Edge edge_descriptor;
Chris@16 202
Chris@16 203 /// The vertex property type
Chris@16 204 typedef typename Config::vertex_property_type vertex_property_type;
Chris@16 205
Chris@16 206 /// The vertex property type
Chris@16 207 typedef typename Config::edge_property_type edge_property_type;
Chris@16 208
Chris@16 209 /// The type used to extract names from the property structure
Chris@16 210 typedef typename internal_vertex_name<vertex_property_type>::type
Chris@16 211 extract_name_type;
Chris@16 212
Chris@16 213 /// The type used to name vertices in the graph
Chris@16 214 typedef typename remove_cv<
Chris@16 215 typename remove_reference<
Chris@16 216 typename extract_name_type::result_type>::type>::type
Chris@16 217 vertex_name_type;
Chris@16 218
Chris@16 219 /// The type used to distribute named vertices in the graph
Chris@16 220 typedef typename Config::distribution_type distribution_type;
Chris@16 221 typedef typename Config::base_distribution_type base_distribution_type;
Chris@16 222
Chris@16 223 /// The type used for communication in the distributed structure
Chris@16 224 typedef typename Config::process_group_type process_group_type;
Chris@16 225
Chris@16 226 /// Type used to identify processes
Chris@16 227 typedef typename process_group_type::process_id_type process_id_type;
Chris@16 228
Chris@16 229 /// a reference to this class, which is used for disambiguation of the
Chris@16 230 // add_vertex function
Chris@16 231 typedef named_graph named_graph_type;
Chris@16 232
Chris@16 233 /// Structure returned when adding a vertex by vertex name
Chris@16 234 struct lazy_add_vertex;
Chris@16 235 friend struct lazy_add_vertex;
Chris@16 236
Chris@16 237 /// Structure returned when adding an edge by vertex name
Chris@16 238 struct lazy_add_edge;
Chris@16 239 friend struct lazy_add_edge;
Chris@16 240
Chris@16 241 /// Structure returned when adding an edge by vertex name with a property
Chris@16 242 struct lazy_add_edge_with_property;
Chris@16 243 friend struct lazy_add_edge_with_property;
Chris@16 244
Chris@16 245 explicit named_graph(const process_group_type& pg);
Chris@16 246
Chris@16 247 named_graph(const process_group_type& pg, const base_distribution_type& distribution);
Chris@16 248
Chris@16 249 /// Set up triggers, but only for the BSP process group
Chris@16 250 void setup_triggers();
Chris@16 251
Chris@16 252 /// Retrieve the derived instance
Chris@16 253 Graph& derived() { return static_cast<Graph&>(*this); }
Chris@16 254 const Graph& derived() const { return static_cast<const Graph&>(*this); }
Chris@16 255
Chris@16 256 /// Retrieve the process group
Chris@16 257 process_group_type& process_group() { return process_group_; }
Chris@16 258 const process_group_type& process_group() const { return process_group_; }
Chris@16 259
Chris@16 260 // Retrieve the named distribution
Chris@16 261 distribution_type& named_distribution() { return distribution_; }
Chris@16 262 const distribution_type& named_distribution() const { return distribution_; }
Chris@16 263
Chris@16 264 /// Notify the named_graph that we have added the given vertex. This
Chris@16 265 /// is a no-op.
Chris@16 266 void added_vertex(Vertex) { }
Chris@16 267
Chris@16 268 /// Notify the named_graph that we are removing the given
Chris@16 269 /// vertex. This is a no-op.
Chris@16 270 template <typename VertexIterStability>
Chris@16 271 void removing_vertex(Vertex, VertexIterStability) { }
Chris@16 272
Chris@16 273 /// Notify the named_graph that we are clearing the graph
Chris@16 274 void clearing_graph() { }
Chris@16 275
Chris@16 276 /// Retrieve the owner of a given vertex based on the properties
Chris@16 277 /// associated with that vertex. This operation just returns the
Chris@16 278 /// number of the local processor, adding all vertices locally.
Chris@16 279 process_id_type owner_by_property(const vertex_property_type&);
Chris@16 280
Chris@16 281 protected:
Chris@16 282 void
Chris@16 283 handle_add_vertex_name(int source, int tag, const vertex_name_type& msg,
Chris@16 284 trigger_receive_context);
Chris@16 285
Chris@16 286 vertex_descriptor
Chris@16 287 handle_add_vertex_name_with_reply(int source, int tag,
Chris@16 288 const vertex_name_type& msg,
Chris@16 289 trigger_receive_context);
Chris@16 290
Chris@16 291 boost::parallel::detail::untracked_pair<vertex_descriptor, bool>
Chris@16 292 handle_find_vertex(int source, int tag, const vertex_name_type& msg,
Chris@16 293 trigger_receive_context);
Chris@16 294
Chris@16 295 template<typename U, typename V>
Chris@16 296 void handle_add_edge(int source, int tag, const boost::parallel::detail::untracked_pair<U, V>& msg,
Chris@16 297 trigger_receive_context);
Chris@16 298
Chris@16 299 template<typename U, typename V>
Chris@16 300 boost::parallel::detail::untracked_pair<edge_descriptor, bool>
Chris@16 301 handle_add_edge_with_reply(int source, int tag, const boost::parallel::detail::untracked_pair<U, V>& msg,
Chris@16 302 trigger_receive_context);
Chris@16 303
Chris@16 304 template<typename U, typename V>
Chris@16 305 void
Chris@16 306 handle_add_edge_with_property
Chris@16 307 (int source, int tag,
Chris@16 308 const pair_with_property<U, V, edge_property_type>& msg,
Chris@16 309 trigger_receive_context);
Chris@16 310
Chris@16 311 template<typename U, typename V>
Chris@16 312 boost::parallel::detail::untracked_pair<edge_descriptor, bool>
Chris@16 313 handle_add_edge_with_reply_and_property
Chris@16 314 (int source, int tag,
Chris@16 315 const pair_with_property<U, V, edge_property_type>& msg,
Chris@16 316 trigger_receive_context);
Chris@16 317
Chris@16 318 /// The process group for this distributed data structure
Chris@16 319 process_group_type process_group_;
Chris@16 320
Chris@16 321 /// The distribution we will use to map names to processors
Chris@16 322 distribution_type distribution_;
Chris@16 323 };
Chris@16 324
Chris@16 325 /// Helper macro containing the template parameters of named_graph
Chris@16 326 #define BGL_NAMED_GRAPH_PARAMS \
Chris@16 327 typename Graph, typename Vertex, typename Edge, typename Config
Chris@16 328 /// Helper macro containing the named_graph<...> instantiation
Chris@16 329 #define BGL_NAMED_GRAPH \
Chris@16 330 named_graph<Graph, Vertex, Edge, Config>
Chris@16 331
Chris@16 332 /**
Chris@16 333 * Data structure returned from add_vertex that will "lazily" add the
Chris@16 334 * vertex, either when it is converted to a @c vertex_descriptor or
Chris@16 335 * when the most recent copy has been destroyed.
Chris@16 336 */
Chris@16 337 template<BGL_NAMED_GRAPH_PARAMS>
Chris@16 338 struct BGL_NAMED_GRAPH::lazy_add_vertex
Chris@16 339 {
Chris@16 340 /// Construct a new lazyily-added vertex
Chris@16 341 lazy_add_vertex(named_graph& self, const vertex_name_type& name)
Chris@16 342 : self(self), name(name), committed(false) { }
Chris@16 343
Chris@16 344 /// Transfer responsibility for adding the vertex from the source of
Chris@16 345 /// the copy to the newly-constructed opbject.
Chris@16 346 lazy_add_vertex(const lazy_add_vertex& other)
Chris@101 347 : self(other.self), name(other.name), committed(other.committed)
Chris@16 348 {
Chris@16 349 other.committed = true;
Chris@16 350 }
Chris@16 351
Chris@16 352 /// If the vertex has not been added yet, add it
Chris@16 353 ~lazy_add_vertex();
Chris@16 354
Chris@16 355 /// Add the vertex and return its descriptor. This conversion can
Chris@16 356 /// only occur once, and only when this object is responsible for
Chris@16 357 /// creating the vertex.
Chris@16 358 operator vertex_descriptor() const { return commit(); }
Chris@16 359
Chris@16 360 /// Add the vertex and return its descriptor. This can only be
Chris@16 361 /// called once, and only when this object is responsible for
Chris@16 362 /// creating the vertex.
Chris@16 363 vertex_descriptor commit() const;
Chris@16 364
Chris@16 365 protected:
Chris@16 366 named_graph& self;
Chris@16 367 vertex_name_type name;
Chris@16 368 mutable bool committed;
Chris@16 369 };
Chris@16 370
Chris@16 371 template<BGL_NAMED_GRAPH_PARAMS>
Chris@16 372 BGL_NAMED_GRAPH::lazy_add_vertex::~lazy_add_vertex()
Chris@16 373 {
Chris@16 374 typedef typename BGL_NAMED_GRAPH::process_id_type process_id_type;
Chris@16 375
Chris@16 376 /// If this vertex has already been created or will be created by
Chris@16 377 /// someone else, or if someone threw an exception, we will not
Chris@16 378 /// create the vertex now.
Chris@16 379 if (committed || std::uncaught_exception())
Chris@16 380 return;
Chris@16 381
Chris@16 382 committed = true;
Chris@16 383
Chris@16 384 process_id_type owner = self.named_distribution()(name);
Chris@16 385 if (owner == process_id(self.process_group()))
Chris@16 386 /// Add the vertex locally
Chris@16 387 add_vertex(self.derived().base().vertex_constructor(name), self.derived());
Chris@16 388 else
Chris@16 389 /// Ask the owner of the vertex to add a vertex with this name
Chris@16 390 send(self.process_group(), owner, msg_add_vertex_name, name);
Chris@16 391 }
Chris@16 392
Chris@16 393 template<BGL_NAMED_GRAPH_PARAMS>
Chris@16 394 typename BGL_NAMED_GRAPH::vertex_descriptor
Chris@16 395 BGL_NAMED_GRAPH::lazy_add_vertex::commit() const
Chris@16 396 {
Chris@16 397 typedef typename BGL_NAMED_GRAPH::process_id_type process_id_type;
Chris@16 398 BOOST_ASSERT (!committed);
Chris@16 399 committed = true;
Chris@16 400
Chris@16 401 process_id_type owner = self.named_distribution()(name);
Chris@16 402 if (owner == process_id(self.process_group()))
Chris@16 403 /// Add the vertex locally
Chris@16 404 return add_vertex(self.derived().base().vertex_constructor(name),
Chris@16 405 self.derived());
Chris@16 406 else {
Chris@16 407 /// Ask the owner of the vertex to add a vertex with this name
Chris@16 408 vertex_descriptor result;
Chris@16 409 send_oob_with_reply(self.process_group(), owner,
Chris@16 410 msg_add_vertex_name_with_reply, name, result);
Chris@16 411 return result;
Chris@16 412 }
Chris@16 413 }
Chris@16 414
Chris@16 415 /**
Chris@16 416 * Data structure returned from add_edge that will "lazily" add the
Chris@16 417 * edge, either when it is converted to a @c
Chris@16 418 * pair<edge_descriptor,bool> or when the most recent copy has been
Chris@16 419 * destroyed.
Chris@16 420 */
Chris@16 421 template<BGL_NAMED_GRAPH_PARAMS>
Chris@16 422 struct BGL_NAMED_GRAPH::lazy_add_edge
Chris@16 423 {
Chris@16 424 /// The graph's edge descriptor
Chris@16 425 typedef typename graph_traits<Graph>::edge_descriptor edge_descriptor;
Chris@16 426
Chris@16 427 /// Add an edge for the edge (u, v) based on vertex names
Chris@16 428 lazy_add_edge(BGL_NAMED_GRAPH& self,
Chris@16 429 const vertex_name_type& u_name,
Chris@16 430 const vertex_name_type& v_name)
Chris@16 431 : self(self), u(u_name), v(v_name), committed(false) { }
Chris@16 432
Chris@16 433 /// Add an edge for the edge (u, v) based on a vertex descriptor and name
Chris@16 434 lazy_add_edge(BGL_NAMED_GRAPH& self,
Chris@16 435 vertex_descriptor u,
Chris@16 436 const vertex_name_type& v_name)
Chris@16 437 : self(self), u(u), v(v_name), committed(false) { }
Chris@16 438
Chris@16 439 /// Add an edge for the edge (u, v) based on a vertex name and descriptor
Chris@16 440 lazy_add_edge(BGL_NAMED_GRAPH& self,
Chris@16 441 const vertex_name_type& u_name,
Chris@16 442 vertex_descriptor v)
Chris@16 443 : self(self), u(u_name), v(v), committed(false) { }
Chris@16 444
Chris@16 445 /// Add an edge for the edge (u, v) based on vertex descriptors
Chris@16 446 lazy_add_edge(BGL_NAMED_GRAPH& self,
Chris@16 447 vertex_descriptor u,
Chris@16 448 vertex_descriptor v)
Chris@16 449 : self(self), u(u), v(v), committed(false) { }
Chris@16 450
Chris@16 451 /// Copy a lazy_add_edge structure, which transfers responsibility
Chris@16 452 /// for adding the edge to the newly-constructed object.
Chris@16 453 lazy_add_edge(const lazy_add_edge& other)
Chris@16 454 : self(other.self), u(other.u), v(other.v), committed(other.committed)
Chris@16 455 {
Chris@16 456 other.committed = true;
Chris@16 457 }
Chris@16 458
Chris@16 459 /// If the edge has not yet been added, add the edge but don't wait
Chris@16 460 /// for a reply.
Chris@16 461 ~lazy_add_edge();
Chris@16 462
Chris@16 463 /// Returns commit().
Chris@16 464 operator std::pair<edge_descriptor, bool>() const { return commit(); }
Chris@16 465
Chris@16 466 // Add the edge. This operation will block if a remote edge is
Chris@16 467 // being added.
Chris@16 468 std::pair<edge_descriptor, bool> commit() const;
Chris@16 469
Chris@16 470 protected:
Chris@16 471 BGL_NAMED_GRAPH& self;
Chris@16 472 mutable variant<vertex_descriptor, vertex_name_type> u;
Chris@16 473 mutable variant<vertex_descriptor, vertex_name_type> v;
Chris@16 474 mutable bool committed;
Chris@16 475
Chris@16 476 private:
Chris@16 477 // No copy-assignment semantics
Chris@16 478 void operator=(lazy_add_edge&);
Chris@16 479 };
Chris@16 480
Chris@16 481 template<BGL_NAMED_GRAPH_PARAMS>
Chris@16 482 BGL_NAMED_GRAPH::lazy_add_edge::~lazy_add_edge()
Chris@16 483 {
Chris@16 484 using boost::parallel::detail::make_untracked_pair;
Chris@16 485
Chris@16 486 /// If this edge has already been created or will be created by
Chris@16 487 /// someone else, or if someone threw an exception, we will not
Chris@16 488 /// create the edge now.
Chris@16 489 if (committed || std::uncaught_exception())
Chris@16 490 return;
Chris@16 491
Chris@16 492 committed = true;
Chris@16 493
Chris@16 494 if (vertex_name_type* v_name = boost::get<vertex_name_type>(&v)) {
Chris@16 495 // We haven't resolved the target vertex to a descriptor yet, so
Chris@16 496 // it must not be local. Send a message to the owner of the target
Chris@16 497 // of the edge. If the owner of the target does not happen to own
Chris@16 498 // the source, it will resolve the target to a vertex descriptor
Chris@16 499 // and pass the message along to the owner of the source.
Chris@16 500 if (vertex_name_type* u_name = boost::get<vertex_name_type>(&u))
Chris@16 501 send(self.process_group(), self.distribution_(*v_name),
Chris@16 502 BGL_NAMED_GRAPH::msg_add_edge_name_name,
Chris@16 503 make_untracked_pair(*u_name, *v_name));
Chris@16 504 else
Chris@16 505 send(self.process_group(), self.distribution_(*v_name),
Chris@16 506 BGL_NAMED_GRAPH::msg_add_edge_vertex_name,
Chris@16 507 make_untracked_pair(boost::get<vertex_descriptor>(u), *v_name));
Chris@16 508 } else {
Chris@16 509 if (vertex_name_type* u_name = boost::get<vertex_name_type>(&u))
Chris@16 510 // We haven't resolved the source vertex to a descriptor yet, so
Chris@16 511 // it must not be local. Send a message to the owner of the
Chris@16 512 // source vertex requesting the edge addition.
Chris@16 513 send(self.process_group(), self.distribution_(*u_name),
Chris@16 514 BGL_NAMED_GRAPH::msg_add_edge_name_vertex,
Chris@16 515 make_untracked_pair(*u_name, boost::get<vertex_descriptor>(v)));
Chris@16 516 else
Chris@16 517 // We have descriptors for both of the vertices, either of which
Chris@16 518 // may be remote or local. Tell the owner of the source vertex
Chris@16 519 // to add the edge (it may be us!).
Chris@16 520 add_edge(boost::get<vertex_descriptor>(u),
Chris@16 521 boost::get<vertex_descriptor>(v),
Chris@16 522 self.derived());
Chris@16 523 }
Chris@16 524 }
Chris@16 525
Chris@16 526 template<BGL_NAMED_GRAPH_PARAMS>
Chris@16 527 std::pair<typename graph_traits<Graph>::edge_descriptor, bool>
Chris@16 528 BGL_NAMED_GRAPH::lazy_add_edge::commit() const
Chris@16 529 {
Chris@16 530 typedef typename BGL_NAMED_GRAPH::process_id_type process_id_type;
Chris@16 531 using boost::parallel::detail::make_untracked_pair;
Chris@16 532
Chris@16 533 BOOST_ASSERT(!committed);
Chris@16 534 committed = true;
Chris@16 535
Chris@16 536 /// The result we will return, if we are sending a message to
Chris@16 537 /// request that someone else add the edge.
Chris@16 538 boost::parallel::detail::untracked_pair<edge_descriptor, bool> result;
Chris@16 539
Chris@16 540 /// The owner of the vertex "u"
Chris@16 541 process_id_type u_owner;
Chris@16 542
Chris@16 543 process_id_type rank = process_id(self.process_group());
Chris@16 544 if (const vertex_name_type* u_name = boost::get<vertex_name_type>(&u)) {
Chris@16 545 /// We haven't resolved the source vertex to a descriptor yet, so
Chris@16 546 /// it must not be local.
Chris@16 547 u_owner = self.named_distribution()(*u_name);
Chris@16 548
Chris@16 549 /// Send a message to the remote vertex requesting that it add the
Chris@16 550 /// edge. The message differs depending on whether we have a
Chris@16 551 /// vertex name or a vertex descriptor for the target.
Chris@16 552 if (const vertex_name_type* v_name = boost::get<vertex_name_type>(&v))
Chris@16 553 send_oob_with_reply(self.process_group(), u_owner,
Chris@16 554 BGL_NAMED_GRAPH::msg_add_edge_name_name_with_reply,
Chris@16 555 make_untracked_pair(*u_name, *v_name), result);
Chris@16 556 else
Chris@16 557 send_oob_with_reply(self.process_group(), u_owner,
Chris@16 558 BGL_NAMED_GRAPH::msg_add_edge_name_vertex_with_reply,
Chris@16 559 make_untracked_pair(*u_name,
Chris@16 560 boost::get<vertex_descriptor>(v)),
Chris@16 561 result);
Chris@16 562 } else {
Chris@16 563 /// We have resolved the source vertex to a descriptor, which may
Chris@16 564 /// either be local or remote.
Chris@16 565 u_owner
Chris@16 566 = get(vertex_owner, self.derived(),
Chris@16 567 boost::get<vertex_descriptor>(u));
Chris@16 568 if (u_owner == rank) {
Chris@16 569 /// The source is local. If we need to, resolve the target vertex.
Chris@16 570 if (const vertex_name_type* v_name = boost::get<vertex_name_type>(&v))
Chris@16 571 v = add_vertex(*v_name, self.derived());
Chris@16 572
Chris@16 573 /// Add the edge using vertex descriptors
Chris@16 574 return add_edge(boost::get<vertex_descriptor>(u),
Chris@16 575 boost::get<vertex_descriptor>(v),
Chris@16 576 self.derived());
Chris@16 577 } else {
Chris@16 578 /// The source is remote. Just send a message to its owner
Chris@16 579 /// requesting that the owner add the new edge, either directly
Chris@16 580 /// or via the derived class's add_edge function.
Chris@16 581 if (const vertex_name_type* v_name = boost::get<vertex_name_type>(&v))
Chris@16 582 send_oob_with_reply
Chris@16 583 (self.process_group(), u_owner,
Chris@16 584 BGL_NAMED_GRAPH::msg_add_edge_vertex_name_with_reply,
Chris@16 585 make_untracked_pair(boost::get<vertex_descriptor>(u), *v_name),
Chris@16 586 result);
Chris@16 587 else
Chris@16 588 return add_edge(boost::get<vertex_descriptor>(u),
Chris@16 589 boost::get<vertex_descriptor>(v),
Chris@16 590 self.derived());
Chris@16 591 }
Chris@16 592 }
Chris@16 593
Chris@16 594 // If we get here, the edge has been added remotely and "result"
Chris@16 595 // contains the result of that edge addition.
Chris@16 596 return result;
Chris@16 597 }
Chris@16 598
Chris@16 599 /**
Chris@16 600 * Data structure returned from add_edge that will "lazily" add the
Chris@16 601 * edge with a property, either when it is converted to a @c
Chris@16 602 * pair<edge_descriptor,bool> or when the most recent copy has been
Chris@16 603 * destroyed.
Chris@16 604 */
Chris@16 605 template<BGL_NAMED_GRAPH_PARAMS>
Chris@16 606 struct BGL_NAMED_GRAPH::lazy_add_edge_with_property
Chris@16 607 {
Chris@16 608 /// The graph's edge descriptor
Chris@16 609 typedef typename graph_traits<Graph>::edge_descriptor edge_descriptor;
Chris@16 610
Chris@16 611 /// The Edge property type for our graph
Chris@16 612 typedef typename Config::edge_property_type edge_property_type;
Chris@16 613
Chris@16 614 /// Add an edge for the edge (u, v) based on vertex names
Chris@16 615 lazy_add_edge_with_property(BGL_NAMED_GRAPH& self,
Chris@16 616 const vertex_name_type& u_name,
Chris@16 617 const vertex_name_type& v_name,
Chris@16 618 const edge_property_type& property)
Chris@16 619 : self(self), u(u_name), v(v_name), property(property), committed(false)
Chris@16 620 {
Chris@16 621 }
Chris@16 622
Chris@16 623 /// Add an edge for the edge (u, v) based on a vertex descriptor and name
Chris@16 624 lazy_add_edge_with_property(BGL_NAMED_GRAPH& self,
Chris@16 625 vertex_descriptor u,
Chris@16 626 const vertex_name_type& v_name,
Chris@16 627 const edge_property_type& property)
Chris@16 628 : self(self), u(u), v(v_name), property(property), committed(false) { }
Chris@16 629
Chris@16 630 /// Add an edge for the edge (u, v) based on a vertex name and descriptor
Chris@16 631 lazy_add_edge_with_property(BGL_NAMED_GRAPH& self,
Chris@16 632 const vertex_name_type& u_name,
Chris@16 633 vertex_descriptor v,
Chris@16 634 const edge_property_type& property)
Chris@16 635 : self(self), u(u_name), v(v), property(property), committed(false) { }
Chris@16 636
Chris@16 637 /// Add an edge for the edge (u, v) based on vertex descriptors
Chris@16 638 lazy_add_edge_with_property(BGL_NAMED_GRAPH& self,
Chris@16 639 vertex_descriptor u,
Chris@16 640 vertex_descriptor v,
Chris@16 641 const edge_property_type& property)
Chris@16 642 : self(self), u(u), v(v), property(property), committed(false) { }
Chris@16 643
Chris@16 644 /// Copy a lazy_add_edge_with_property structure, which transfers
Chris@16 645 /// responsibility for adding the edge to the newly-constructed
Chris@16 646 /// object.
Chris@16 647 lazy_add_edge_with_property(const lazy_add_edge_with_property& other)
Chris@16 648 : self(other.self), u(other.u), v(other.v), property(other.property),
Chris@16 649 committed(other.committed)
Chris@16 650 {
Chris@16 651 other.committed = true;
Chris@16 652 }
Chris@16 653
Chris@16 654 /// If the edge has not yet been added, add the edge but don't wait
Chris@16 655 /// for a reply.
Chris@16 656 ~lazy_add_edge_with_property();
Chris@16 657
Chris@16 658 /// Returns commit().
Chris@16 659 operator std::pair<edge_descriptor, bool>() const { return commit(); }
Chris@16 660
Chris@16 661 // Add the edge. This operation will block if a remote edge is
Chris@16 662 // being added.
Chris@16 663 std::pair<edge_descriptor, bool> commit() const;
Chris@16 664
Chris@16 665 protected:
Chris@16 666 BGL_NAMED_GRAPH& self;
Chris@16 667 mutable variant<vertex_descriptor, vertex_name_type> u;
Chris@16 668 mutable variant<vertex_descriptor, vertex_name_type> v;
Chris@16 669 edge_property_type property;
Chris@16 670 mutable bool committed;
Chris@16 671
Chris@16 672 private:
Chris@16 673 // No copy-assignment semantics
Chris@16 674 void operator=(lazy_add_edge_with_property&);
Chris@16 675 };
Chris@16 676
Chris@16 677 template<BGL_NAMED_GRAPH_PARAMS>
Chris@16 678 BGL_NAMED_GRAPH::lazy_add_edge_with_property::~lazy_add_edge_with_property()
Chris@16 679 {
Chris@16 680 using boost::detail::parallel::make_pair_with_property;
Chris@16 681
Chris@16 682 /// If this edge has already been created or will be created by
Chris@16 683 /// someone else, or if someone threw an exception, we will not
Chris@16 684 /// create the edge now.
Chris@16 685 if (committed || std::uncaught_exception())
Chris@16 686 return;
Chris@16 687
Chris@16 688 committed = true;
Chris@16 689
Chris@16 690 if (vertex_name_type* v_name = boost::get<vertex_name_type>(&v)) {
Chris@16 691 // We haven't resolved the target vertex to a descriptor yet, so
Chris@16 692 // it must not be local. Send a message to the owner of the target
Chris@16 693 // of the edge. If the owner of the target does not happen to own
Chris@16 694 // the source, it will resolve the target to a vertex descriptor
Chris@16 695 // and pass the message along to the owner of the source.
Chris@16 696 if (vertex_name_type* u_name = boost::get<vertex_name_type>(&u))
Chris@16 697 send(self.process_group(), self.distribution_(*v_name),
Chris@16 698 BGL_NAMED_GRAPH::msg_add_edge_name_name_with_property,
Chris@16 699 make_pair_with_property(*u_name, *v_name, property));
Chris@16 700 else
Chris@16 701 send(self.process_group(), self.distribution_(*v_name),
Chris@16 702 BGL_NAMED_GRAPH::msg_add_edge_vertex_name_with_property,
Chris@16 703 make_pair_with_property(boost::get<vertex_descriptor>(u), *v_name,
Chris@16 704 property));
Chris@16 705 } else {
Chris@16 706 if (vertex_name_type* u_name = boost::get<vertex_name_type>(&u))
Chris@16 707 // We haven't resolved the source vertex to a descriptor yet, so
Chris@16 708 // it must not be local. Send a message to the owner of the
Chris@16 709 // source vertex requesting the edge addition.
Chris@16 710 send(self.process_group(), self.distribution_(*u_name),
Chris@16 711 BGL_NAMED_GRAPH::msg_add_edge_name_vertex_with_property,
Chris@16 712 make_pair_with_property(*u_name, boost::get<vertex_descriptor>(v),
Chris@16 713 property));
Chris@16 714 else
Chris@16 715 // We have descriptors for both of the vertices, either of which
Chris@16 716 // may be remote or local. Tell the owner of the source vertex
Chris@16 717 // to add the edge (it may be us!).
Chris@16 718 add_edge(boost::get<vertex_descriptor>(u),
Chris@16 719 boost::get<vertex_descriptor>(v),
Chris@16 720 property,
Chris@16 721 self.derived());
Chris@16 722 }
Chris@16 723 }
Chris@16 724
Chris@16 725 template<BGL_NAMED_GRAPH_PARAMS>
Chris@16 726 std::pair<typename graph_traits<Graph>::edge_descriptor, bool>
Chris@16 727 BGL_NAMED_GRAPH::lazy_add_edge_with_property::commit() const
Chris@16 728 {
Chris@16 729 using boost::detail::parallel::make_pair_with_property;
Chris@16 730 typedef typename BGL_NAMED_GRAPH::process_id_type process_id_type;
Chris@16 731 BOOST_ASSERT(!committed);
Chris@16 732 committed = true;
Chris@16 733
Chris@16 734 /// The result we will return, if we are sending a message to
Chris@16 735 /// request that someone else add the edge.
Chris@16 736 boost::parallel::detail::untracked_pair<edge_descriptor, bool> result;
Chris@16 737
Chris@16 738 /// The owner of the vertex "u"
Chris@16 739 process_id_type u_owner;
Chris@16 740
Chris@16 741 process_id_type rank = process_id(self.process_group());
Chris@16 742 if (const vertex_name_type* u_name = boost::get<vertex_name_type>(&u)) {
Chris@16 743 /// We haven't resolved the source vertex to a descriptor yet, so
Chris@16 744 /// it must not be local.
Chris@16 745 u_owner = self.named_distribution()(*u_name);
Chris@16 746
Chris@16 747 /// Send a message to the remote vertex requesting that it add the
Chris@16 748 /// edge. The message differs depending on whether we have a
Chris@16 749 /// vertex name or a vertex descriptor for the target.
Chris@16 750 if (const vertex_name_type* v_name = boost::get<vertex_name_type>(&v))
Chris@16 751 send_oob_with_reply
Chris@16 752 (self.process_group(), u_owner,
Chris@16 753 BGL_NAMED_GRAPH::msg_add_edge_name_name_with_reply_and_property,
Chris@16 754 make_pair_with_property(*u_name, *v_name, property),
Chris@16 755 result);
Chris@16 756 else
Chris@16 757 send_oob_with_reply
Chris@16 758 (self.process_group(), u_owner,
Chris@16 759 BGL_NAMED_GRAPH::msg_add_edge_name_vertex_with_reply_and_property,
Chris@16 760 make_pair_with_property(*u_name,
Chris@16 761 boost::get<vertex_descriptor>(v),
Chris@16 762 property),
Chris@16 763 result);
Chris@16 764 } else {
Chris@16 765 /// We have resolved the source vertex to a descriptor, which may
Chris@16 766 /// either be local or remote.
Chris@16 767 u_owner
Chris@16 768 = get(vertex_owner, self.derived(),
Chris@16 769 boost::get<vertex_descriptor>(u));
Chris@16 770 if (u_owner == rank) {
Chris@16 771 /// The source is local. If we need to, resolve the target vertex.
Chris@16 772 if (const vertex_name_type* v_name = boost::get<vertex_name_type>(&v))
Chris@16 773 v = add_vertex(*v_name, self.derived());
Chris@16 774
Chris@16 775 /// Add the edge using vertex descriptors
Chris@16 776 return add_edge(boost::get<vertex_descriptor>(u),
Chris@16 777 boost::get<vertex_descriptor>(v),
Chris@16 778 property,
Chris@16 779 self.derived());
Chris@16 780 } else {
Chris@16 781 /// The source is remote. Just send a message to its owner
Chris@16 782 /// requesting that the owner add the new edge, either directly
Chris@16 783 /// or via the derived class's add_edge function.
Chris@16 784 if (const vertex_name_type* v_name = boost::get<vertex_name_type>(&v))
Chris@16 785 send_oob_with_reply
Chris@16 786 (self.process_group(), u_owner,
Chris@16 787 BGL_NAMED_GRAPH::msg_add_edge_vertex_name_with_reply_and_property,
Chris@16 788 make_pair_with_property(boost::get<vertex_descriptor>(u), *v_name,
Chris@16 789 property),
Chris@16 790 result);
Chris@16 791 else
Chris@16 792 return add_edge(boost::get<vertex_descriptor>(u),
Chris@16 793 boost::get<vertex_descriptor>(v),
Chris@16 794 property,
Chris@16 795 self.derived());
Chris@16 796 }
Chris@16 797 }
Chris@16 798
Chris@16 799 // If we get here, the edge has been added remotely and "result"
Chris@16 800 // contains the result of that edge addition.
Chris@16 801 return result;
Chris@16 802 }
Chris@16 803
Chris@16 804 /// Construct the named_graph with a particular process group
Chris@16 805 template<BGL_NAMED_GRAPH_PARAMS>
Chris@16 806 BGL_NAMED_GRAPH::named_graph(const process_group_type& pg)
Chris@101 807 : process_group_(pg, boost::parallel::attach_distributed_object()),
Chris@16 808 distribution_(pg)
Chris@16 809 {
Chris@16 810 setup_triggers();
Chris@16 811 }
Chris@16 812
Chris@16 813 /// Construct the named_graph mixin with a particular process group
Chris@16 814 /// and distribution function
Chris@16 815 template<BGL_NAMED_GRAPH_PARAMS>
Chris@16 816 BGL_NAMED_GRAPH::named_graph(const process_group_type& pg,
Chris@16 817 const base_distribution_type& distribution)
Chris@101 818 : process_group_(pg, boost::parallel::attach_distributed_object()),
Chris@16 819 distribution_(pg, distribution)
Chris@16 820 {
Chris@16 821 setup_triggers();
Chris@16 822 }
Chris@16 823
Chris@16 824 template<BGL_NAMED_GRAPH_PARAMS>
Chris@16 825 void
Chris@16 826 BGL_NAMED_GRAPH::setup_triggers()
Chris@16 827 {
Chris@16 828 using boost::graph::parallel::simple_trigger;
Chris@16 829
Chris@16 830 simple_trigger(process_group_, msg_add_vertex_name, this,
Chris@16 831 &named_graph::handle_add_vertex_name);
Chris@16 832 simple_trigger(process_group_, msg_add_vertex_name_with_reply, this,
Chris@16 833 &named_graph::handle_add_vertex_name_with_reply);
Chris@16 834 simple_trigger(process_group_, msg_find_vertex, this,
Chris@16 835 &named_graph::handle_find_vertex);
Chris@16 836 simple_trigger(process_group_, msg_add_edge_name_name, this,
Chris@16 837 &named_graph::template handle_add_edge<vertex_name_type,
Chris@16 838 vertex_name_type>);
Chris@16 839 simple_trigger(process_group_, msg_add_edge_name_name_with_reply, this,
Chris@16 840 &named_graph::template handle_add_edge_with_reply
Chris@16 841 <vertex_name_type, vertex_name_type>);
Chris@16 842 simple_trigger(process_group_, msg_add_edge_name_vertex, this,
Chris@16 843 &named_graph::template handle_add_edge<vertex_name_type,
Chris@16 844 vertex_descriptor>);
Chris@16 845 simple_trigger(process_group_, msg_add_edge_name_vertex_with_reply, this,
Chris@16 846 &named_graph::template handle_add_edge_with_reply
Chris@16 847 <vertex_name_type, vertex_descriptor>);
Chris@16 848 simple_trigger(process_group_, msg_add_edge_vertex_name, this,
Chris@16 849 &named_graph::template handle_add_edge<vertex_descriptor,
Chris@16 850 vertex_name_type>);
Chris@16 851 simple_trigger(process_group_, msg_add_edge_vertex_name_with_reply, this,
Chris@16 852 &named_graph::template handle_add_edge_with_reply
Chris@16 853 <vertex_descriptor, vertex_name_type>);
Chris@16 854 simple_trigger(process_group_, msg_add_edge_name_name_with_property, this,
Chris@16 855 &named_graph::
Chris@16 856 template handle_add_edge_with_property<vertex_name_type,
Chris@16 857 vertex_name_type>);
Chris@16 858 simple_trigger(process_group_,
Chris@16 859 msg_add_edge_name_name_with_reply_and_property, this,
Chris@16 860 &named_graph::template handle_add_edge_with_reply_and_property
Chris@16 861 <vertex_name_type, vertex_name_type>);
Chris@16 862 simple_trigger(process_group_, msg_add_edge_name_vertex_with_property, this,
Chris@16 863 &named_graph::
Chris@16 864 template handle_add_edge_with_property<vertex_name_type,
Chris@16 865 vertex_descriptor>);
Chris@16 866 simple_trigger(process_group_,
Chris@16 867 msg_add_edge_name_vertex_with_reply_and_property, this,
Chris@16 868 &named_graph::template handle_add_edge_with_reply_and_property
Chris@16 869 <vertex_name_type, vertex_descriptor>);
Chris@16 870 simple_trigger(process_group_, msg_add_edge_vertex_name_with_property, this,
Chris@16 871 &named_graph::
Chris@16 872 template handle_add_edge_with_property<vertex_descriptor,
Chris@16 873 vertex_name_type>);
Chris@16 874 simple_trigger(process_group_,
Chris@16 875 msg_add_edge_vertex_name_with_reply_and_property, this,
Chris@16 876 &named_graph::template handle_add_edge_with_reply_and_property
Chris@16 877 <vertex_descriptor, vertex_name_type>);
Chris@16 878 }
Chris@16 879
Chris@16 880 /// Retrieve the vertex associated with the given name
Chris@16 881 template<BGL_NAMED_GRAPH_PARAMS>
Chris@16 882 optional<Vertex>
Chris@16 883 find_vertex(typename BGL_NAMED_GRAPH::vertex_name_type const& name,
Chris@16 884 const BGL_NAMED_GRAPH& g)
Chris@16 885 {
Chris@16 886 typedef typename Graph::local_vertex_descriptor local_vertex_descriptor;
Chris@16 887 typedef typename graph_traits<Graph>::vertex_descriptor vertex_descriptor;
Chris@16 888
Chris@16 889 // Determine the owner of this name
Chris@16 890 typename BGL_NAMED_GRAPH::process_id_type owner
Chris@16 891 = g.named_distribution()(name);
Chris@16 892
Chris@16 893 if (owner == process_id(g.process_group())) {
Chris@16 894 // The vertex is local, so search for a mapping here
Chris@16 895 optional<local_vertex_descriptor> result
Chris@16 896 = find_vertex(name, g.derived().base());
Chris@16 897 if (result)
Chris@16 898 return Vertex(owner, *result);
Chris@16 899 else
Chris@16 900 return optional<Vertex>();
Chris@16 901 }
Chris@16 902 else {
Chris@16 903 // Ask the ownering process for the name of this vertex
Chris@16 904 boost::parallel::detail::untracked_pair<vertex_descriptor, bool> result;
Chris@16 905 send_oob_with_reply(g.process_group(), owner,
Chris@16 906 BGL_NAMED_GRAPH::msg_find_vertex, name, result);
Chris@16 907 if (result.second)
Chris@16 908 return result.first;
Chris@16 909 else
Chris@16 910 return optional<Vertex>();
Chris@16 911 }
Chris@16 912 }
Chris@16 913
Chris@16 914 /// meta-function helping in figuring out if the given VertextProerty belongs to
Chris@16 915 /// a named graph
Chris@16 916 template<typename VertexProperty>
Chris@16 917 struct not_is_named_graph
Chris@16 918 : is_same<typename internal_vertex_name<VertexProperty>::type, void>
Chris@16 919 {};
Chris@16 920
Chris@16 921 /// Retrieve the vertex associated with the given name
Chris@16 922 template<typename Graph>
Chris@16 923 typename Graph::named_graph_type::lazy_add_vertex
Chris@16 924 add_vertex(typename Graph::vertex_name_type const& name,
Chris@16 925 Graph& g,
Chris@16 926 typename disable_if<
Chris@16 927 not_is_named_graph<typename Graph::vertex_property_type>,
Chris@16 928 void*>::type = 0)
Chris@16 929 {
Chris@16 930 return typename Graph::named_graph_type::lazy_add_vertex(g, name);
Chris@16 931 }
Chris@16 932
Chris@16 933 /// Add an edge using vertex names to refer to the vertices
Chris@16 934 template<BGL_NAMED_GRAPH_PARAMS>
Chris@16 935 typename BGL_NAMED_GRAPH::lazy_add_edge
Chris@16 936 add_edge(typename BGL_NAMED_GRAPH::vertex_name_type const& u_name,
Chris@16 937 typename BGL_NAMED_GRAPH::vertex_name_type const& v_name,
Chris@16 938 BGL_NAMED_GRAPH& g)
Chris@16 939 {
Chris@16 940 typedef typename BGL_NAMED_GRAPH::lazy_add_edge lazy_add_edge;
Chris@16 941 typedef typename BGL_NAMED_GRAPH::process_id_type process_id_type;
Chris@16 942
Chris@16 943 process_id_type rank = process_id(g.process_group());
Chris@16 944 process_id_type u_owner = g.named_distribution()(u_name);
Chris@16 945 process_id_type v_owner = g.named_distribution()(v_name);
Chris@16 946
Chris@16 947 // Resolve local vertex names before building the "lazy" edge
Chris@16 948 // addition structure.
Chris@16 949 if (u_owner == rank && v_owner == rank)
Chris@16 950 return lazy_add_edge(g, add_vertex(u_name, g), add_vertex(v_name, g));
Chris@16 951 else if (u_owner == rank && v_owner != rank)
Chris@16 952 return lazy_add_edge(g, add_vertex(u_name, g), v_name);
Chris@16 953 else if (u_owner != rank && v_owner == rank)
Chris@16 954 return lazy_add_edge(g, u_name, add_vertex(v_name, g));
Chris@16 955 else
Chris@16 956 return lazy_add_edge(g, u_name, v_name);
Chris@16 957 }
Chris@16 958
Chris@16 959 template<BGL_NAMED_GRAPH_PARAMS>
Chris@16 960 typename BGL_NAMED_GRAPH::lazy_add_edge
Chris@16 961 add_edge(typename BGL_NAMED_GRAPH::vertex_name_type const& u_name,
Chris@16 962 typename BGL_NAMED_GRAPH::vertex_descriptor const& v,
Chris@16 963 BGL_NAMED_GRAPH& g)
Chris@16 964 {
Chris@16 965 // Resolve local vertex names before building the "lazy" edge
Chris@16 966 // addition structure.
Chris@16 967 typedef typename BGL_NAMED_GRAPH::lazy_add_edge lazy_add_edge;
Chris@16 968 if (g.named_distribution()(u_name) == process_id(g.process_group()))
Chris@16 969 return lazy_add_edge(g, add_vertex(u_name, g), v);
Chris@16 970 else
Chris@16 971 return lazy_add_edge(g, u_name, v);
Chris@16 972 }
Chris@16 973
Chris@16 974 template<BGL_NAMED_GRAPH_PARAMS>
Chris@16 975 typename BGL_NAMED_GRAPH::lazy_add_edge
Chris@16 976 add_edge(typename BGL_NAMED_GRAPH::vertex_descriptor const& u,
Chris@16 977 typename BGL_NAMED_GRAPH::vertex_name_type const& v_name,
Chris@16 978 BGL_NAMED_GRAPH& g)
Chris@16 979 {
Chris@16 980 // Resolve local vertex names before building the "lazy" edge
Chris@16 981 // addition structure.
Chris@16 982 typedef typename BGL_NAMED_GRAPH::lazy_add_edge lazy_add_edge;
Chris@16 983 if (g.named_distribution()(v_name) == process_id(g.process_group()))
Chris@16 984 return lazy_add_edge(g, u, add_vertex(v_name, g));
Chris@16 985 else
Chris@16 986 return lazy_add_edge(g, u, v_name);
Chris@16 987 }
Chris@16 988
Chris@16 989 /// Add an edge using vertex names to refer to the vertices
Chris@16 990 template<BGL_NAMED_GRAPH_PARAMS>
Chris@16 991 typename BGL_NAMED_GRAPH::lazy_add_edge_with_property
Chris@16 992 add_edge(typename BGL_NAMED_GRAPH::vertex_name_type const& u_name,
Chris@16 993 typename BGL_NAMED_GRAPH::vertex_name_type const& v_name,
Chris@16 994 typename Graph::edge_property_type const& property,
Chris@16 995 BGL_NAMED_GRAPH& g)
Chris@16 996 {
Chris@16 997 typedef typename BGL_NAMED_GRAPH::lazy_add_edge_with_property lazy_add_edge;
Chris@16 998 typedef typename BGL_NAMED_GRAPH::process_id_type process_id_type;
Chris@16 999
Chris@16 1000 process_id_type rank = process_id(g.process_group());
Chris@16 1001 process_id_type u_owner = g.named_distribution()(u_name);
Chris@16 1002 process_id_type v_owner = g.named_distribution()(v_name);
Chris@16 1003
Chris@16 1004 // Resolve local vertex names before building the "lazy" edge
Chris@16 1005 // addition structure.
Chris@16 1006 if (u_owner == rank && v_owner == rank)
Chris@16 1007 return lazy_add_edge(g, add_vertex(u_name, g), add_vertex(v_name, g),
Chris@16 1008 property);
Chris@16 1009 else if (u_owner == rank && v_owner != rank)
Chris@16 1010 return lazy_add_edge(g, add_vertex(u_name, g), v_name, property);
Chris@16 1011 else if (u_owner != rank && v_owner == rank)
Chris@16 1012 return lazy_add_edge(g, u_name, add_vertex(v_name, g), property);
Chris@16 1013 else
Chris@16 1014 return lazy_add_edge(g, u_name, v_name, property);
Chris@16 1015 }
Chris@16 1016
Chris@16 1017 template<BGL_NAMED_GRAPH_PARAMS>
Chris@16 1018 typename BGL_NAMED_GRAPH::lazy_add_edge_with_property
Chris@16 1019 add_edge(typename BGL_NAMED_GRAPH::vertex_name_type const& u_name,
Chris@16 1020 typename BGL_NAMED_GRAPH::vertex_descriptor const& v,
Chris@16 1021 typename Graph::edge_property_type const& property,
Chris@16 1022 BGL_NAMED_GRAPH& g)
Chris@16 1023 {
Chris@16 1024 // Resolve local vertex names before building the "lazy" edge
Chris@16 1025 // addition structure.
Chris@16 1026 typedef typename BGL_NAMED_GRAPH::lazy_add_edge_with_property lazy_add_edge;
Chris@16 1027 if (g.named_distribution()(u_name) == process_id(g.process_group()))
Chris@16 1028 return lazy_add_edge(g, add_vertex(u_name, g), v, property);
Chris@16 1029 else
Chris@16 1030 return lazy_add_edge(g, u_name, v, property);
Chris@16 1031 }
Chris@16 1032
Chris@16 1033 template<BGL_NAMED_GRAPH_PARAMS>
Chris@16 1034 typename BGL_NAMED_GRAPH::lazy_add_edge_with_property
Chris@16 1035 add_edge(typename BGL_NAMED_GRAPH::vertex_descriptor const& u,
Chris@16 1036 typename BGL_NAMED_GRAPH::vertex_name_type const& v_name,
Chris@16 1037 typename Graph::edge_property_type const& property,
Chris@16 1038 BGL_NAMED_GRAPH& g)
Chris@16 1039 {
Chris@16 1040 // Resolve local vertex names before building the "lazy" edge
Chris@16 1041 // addition structure.
Chris@16 1042 typedef typename BGL_NAMED_GRAPH::lazy_add_edge_with_property lazy_add_edge;
Chris@16 1043 if (g.named_distribution()(v_name) == process_id(g.process_group()))
Chris@16 1044 return lazy_add_edge(g, u, add_vertex(v_name, g), property);
Chris@16 1045 else
Chris@16 1046 return lazy_add_edge(g, u, v_name, property);
Chris@16 1047 }
Chris@16 1048
Chris@16 1049 template<BGL_NAMED_GRAPH_PARAMS>
Chris@16 1050 typename BGL_NAMED_GRAPH::process_id_type
Chris@16 1051 BGL_NAMED_GRAPH::owner_by_property(const vertex_property_type& property)
Chris@16 1052 {
Chris@16 1053 return distribution_(derived().base().extract_name(property));
Chris@16 1054 }
Chris@16 1055
Chris@16 1056
Chris@16 1057 /*******************************************************************
Chris@16 1058 * Message handlers *
Chris@16 1059 *******************************************************************/
Chris@16 1060
Chris@16 1061 template<BGL_NAMED_GRAPH_PARAMS>
Chris@16 1062 void
Chris@16 1063 BGL_NAMED_GRAPH::
Chris@16 1064 handle_add_vertex_name(int /*source*/, int /*tag*/,
Chris@16 1065 const vertex_name_type& msg, trigger_receive_context)
Chris@16 1066 {
Chris@16 1067 add_vertex(msg, derived());
Chris@16 1068 }
Chris@16 1069
Chris@16 1070 template<BGL_NAMED_GRAPH_PARAMS>
Chris@16 1071 typename BGL_NAMED_GRAPH::vertex_descriptor
Chris@16 1072 BGL_NAMED_GRAPH::
Chris@16 1073 handle_add_vertex_name_with_reply(int source, int /*tag*/,
Chris@16 1074 const vertex_name_type& msg,
Chris@16 1075 trigger_receive_context)
Chris@16 1076 {
Chris@16 1077 return add_vertex(msg, derived());
Chris@16 1078 }
Chris@16 1079
Chris@16 1080 template<BGL_NAMED_GRAPH_PARAMS>
Chris@16 1081 boost::parallel::detail::untracked_pair<typename BGL_NAMED_GRAPH::vertex_descriptor, bool>
Chris@16 1082 BGL_NAMED_GRAPH::
Chris@16 1083 handle_find_vertex(int source, int /*tag*/, const vertex_name_type& msg,
Chris@16 1084 trigger_receive_context)
Chris@16 1085 {
Chris@16 1086 using boost::parallel::detail::make_untracked_pair;
Chris@16 1087
Chris@16 1088 optional<vertex_descriptor> v = find_vertex(msg, derived());
Chris@16 1089 if (v)
Chris@16 1090 return make_untracked_pair(*v, true);
Chris@16 1091 else
Chris@16 1092 return make_untracked_pair(graph_traits<Graph>::null_vertex(), false);
Chris@16 1093 }
Chris@16 1094
Chris@16 1095 template<BGL_NAMED_GRAPH_PARAMS>
Chris@16 1096 template<typename U, typename V>
Chris@16 1097 void
Chris@16 1098 BGL_NAMED_GRAPH::
Chris@16 1099 handle_add_edge(int source, int /*tag*/, const boost::parallel::detail::untracked_pair<U, V>& msg,
Chris@16 1100 trigger_receive_context)
Chris@16 1101 {
Chris@16 1102 add_edge(msg.first, msg.second, derived());
Chris@16 1103 }
Chris@16 1104
Chris@16 1105 template<BGL_NAMED_GRAPH_PARAMS>
Chris@16 1106 template<typename U, typename V>
Chris@16 1107 boost::parallel::detail::untracked_pair<typename BGL_NAMED_GRAPH::edge_descriptor, bool>
Chris@16 1108 BGL_NAMED_GRAPH::
Chris@16 1109 handle_add_edge_with_reply(int source, int /*tag*/, const boost::parallel::detail::untracked_pair<U, V>& msg,
Chris@16 1110 trigger_receive_context)
Chris@16 1111 {
Chris@16 1112 std::pair<typename BGL_NAMED_GRAPH::edge_descriptor, bool> p =
Chris@16 1113 add_edge(msg.first, msg.second, derived());
Chris@16 1114 return p;
Chris@16 1115 }
Chris@16 1116
Chris@16 1117 template<BGL_NAMED_GRAPH_PARAMS>
Chris@16 1118 template<typename U, typename V>
Chris@16 1119 void
Chris@16 1120 BGL_NAMED_GRAPH::
Chris@16 1121 handle_add_edge_with_property
Chris@16 1122 (int source, int tag,
Chris@16 1123 const pair_with_property<U, V, edge_property_type>& msg,
Chris@16 1124 trigger_receive_context)
Chris@16 1125 {
Chris@16 1126 add_edge(msg.first, msg.second, msg.get_property(), derived());
Chris@16 1127 }
Chris@16 1128
Chris@16 1129 template<BGL_NAMED_GRAPH_PARAMS>
Chris@16 1130 template<typename U, typename V>
Chris@16 1131 boost::parallel::detail::untracked_pair<typename BGL_NAMED_GRAPH::edge_descriptor, bool>
Chris@16 1132 BGL_NAMED_GRAPH::
Chris@16 1133 handle_add_edge_with_reply_and_property
Chris@16 1134 (int source, int tag,
Chris@16 1135 const pair_with_property<U, V, edge_property_type>& msg,
Chris@16 1136 trigger_receive_context)
Chris@16 1137 {
Chris@16 1138 std:: pair<typename BGL_NAMED_GRAPH::edge_descriptor, bool> p =
Chris@16 1139 add_edge(msg.first, msg.second, msg.get_property(), derived());
Chris@16 1140 return p;
Chris@16 1141 }
Chris@16 1142
Chris@16 1143 #undef BGL_NAMED_GRAPH
Chris@16 1144 #undef BGL_NAMED_GRAPH_PARAMS
Chris@16 1145
Chris@16 1146 /*******************************************************************
Chris@16 1147 * Maybe named graph mixin *
Chris@16 1148 *******************************************************************/
Chris@16 1149
Chris@16 1150 /**
Chris@16 1151 * A graph mixin that can provide a mapping from names to vertices,
Chris@16 1152 * and use that mapping to simplify creation and manipulation of
Chris@16 1153 * graphs.
Chris@16 1154 */
Chris@16 1155 template<typename Graph, typename Vertex, typename Edge, typename Config,
Chris@16 1156 typename ExtractName
Chris@16 1157 = typename internal_vertex_name<typename Config::vertex_property_type>::type>
Chris@16 1158 struct maybe_named_graph
Chris@16 1159 : public named_graph<Graph, Vertex, Edge, Config>
Chris@16 1160 {
Chris@16 1161 private:
Chris@16 1162 typedef named_graph<Graph, Vertex, Edge, Config> inherited;
Chris@16 1163 typedef typename Config::process_group_type process_group_type;
Chris@16 1164
Chris@16 1165 public:
Chris@16 1166 /// The type used to distribute named vertices in the graph
Chris@16 1167 typedef typename Config::distribution_type distribution_type;
Chris@16 1168 typedef typename Config::base_distribution_type base_distribution_type;
Chris@16 1169
Chris@16 1170 explicit maybe_named_graph(const process_group_type& pg) : inherited(pg) { }
Chris@16 1171
Chris@16 1172 maybe_named_graph(const process_group_type& pg,
Chris@16 1173 const base_distribution_type& distribution)
Chris@16 1174 : inherited(pg, distribution) { }
Chris@16 1175
Chris@16 1176 distribution_type& distribution() { return this->distribution_; }
Chris@16 1177 const distribution_type& distribution() const { return this->distribution_; }
Chris@16 1178 };
Chris@16 1179
Chris@16 1180 /**
Chris@16 1181 * A graph mixin that can provide a mapping from names to vertices,
Chris@16 1182 * and use that mapping to simplify creation and manipulation of
Chris@16 1183 * graphs. This partial specialization turns off this functionality
Chris@16 1184 * when the @c VertexProperty does not have an internal vertex name.
Chris@16 1185 */
Chris@16 1186 template<typename Graph, typename Vertex, typename Edge, typename Config>
Chris@16 1187 struct maybe_named_graph<Graph, Vertex, Edge, Config, void>
Chris@16 1188 {
Chris@16 1189 private:
Chris@16 1190 typedef typename Config::process_group_type process_group_type;
Chris@16 1191 typedef typename Config::vertex_property_type vertex_property_type;
Chris@16 1192
Chris@16 1193 public:
Chris@16 1194 typedef typename process_group_type::process_id_type process_id_type;
Chris@16 1195
Chris@16 1196 /// The type used to distribute named vertices in the graph
Chris@16 1197 typedef typename Config::distribution_type distribution_type;
Chris@16 1198 typedef typename Config::base_distribution_type base_distribution_type;
Chris@16 1199
Chris@16 1200 explicit maybe_named_graph(const process_group_type&) { }
Chris@16 1201
Chris@16 1202 maybe_named_graph(const process_group_type& pg,
Chris@16 1203 const base_distribution_type& distribution)
Chris@16 1204 : distribution_(pg, distribution) { }
Chris@16 1205
Chris@16 1206 /// Notify the named_graph that we have added the given vertex. This
Chris@16 1207 /// is a no-op.
Chris@16 1208 void added_vertex(Vertex) { }
Chris@16 1209
Chris@16 1210 /// Notify the named_graph that we are removing the given
Chris@16 1211 /// vertex. This is a no-op.
Chris@16 1212 template <typename VertexIterStability>
Chris@16 1213 void removing_vertex(Vertex, VertexIterStability) { }
Chris@16 1214
Chris@16 1215 /// Notify the named_graph that we are clearing the graph
Chris@16 1216 void clearing_graph() { }
Chris@16 1217
Chris@16 1218 /// Retrieve the owner of a given vertex based on the properties
Chris@16 1219 /// associated with that vertex. This operation just returns the
Chris@16 1220 /// number of the local processor, adding all vertices locally.
Chris@16 1221 process_id_type owner_by_property(const vertex_property_type&)
Chris@16 1222 {
Chris@16 1223 return process_id(pg);
Chris@16 1224 }
Chris@16 1225
Chris@16 1226 distribution_type& distribution() { return distribution_; }
Chris@16 1227 const distribution_type& distribution() const { return distribution_; }
Chris@16 1228
Chris@16 1229 protected:
Chris@16 1230 /// The process group of the graph
Chris@16 1231 process_group_type pg;
Chris@16 1232
Chris@16 1233 /// The distribution used for the graph
Chris@16 1234 distribution_type distribution_;
Chris@16 1235 };
Chris@16 1236
Chris@16 1237 } } } // end namespace boost::graph::distributed
Chris@16 1238
Chris@16 1239 #endif // BOOST_GRAPH_DISTRIBUTED_NAMED_GRAPH_HPP