named_graph.hpp 47 KB

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