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