named_graph.hpp 47 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241
  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