named_graph.hpp 47 KB

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