Squashed 'boost/' content from commit b4feb19f2

git-subtree-dir: boost
git-subtree-split: b4feb19f287ee92d87a9624b5d36b7cf46aeadeb
This commit is contained in:
Bill Somerville
2018-06-09 21:48:32 +01:00
commit 4ebe6417a5
12444 changed files with 2327021 additions and 0 deletions
@@ -0,0 +1,163 @@
// Copyright 2004 The Trustees of Indiana University.
// Use, modification and distribution is subject to the Boost Software
// License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
// Authors: Douglas Gregor
// Andrew Lumsdaine
#ifndef BOOST_GRAPH_PARALLEL_BFS_HPP
#define BOOST_GRAPH_PARALLEL_BFS_HPP
#ifndef BOOST_GRAPH_USE_MPI
#error "Parallel BGL files should not be included unless <boost/graph/use_mpi.hpp> has been included"
#endif
#include <boost/graph/breadth_first_search.hpp>
#include <boost/graph/overloading.hpp>
#include <boost/graph/distributed/concepts.hpp>
#include <boost/graph/distributed/detail/filtered_queue.hpp>
#include <boost/graph/distributed/queue.hpp>
#include <boost/dynamic_bitset.hpp>
#include <boost/pending/queue.hpp>
#include <boost/graph/parallel/properties.hpp>
#include <boost/graph/parallel/container_traits.hpp>
namespace boost {
namespace detail {
/** @brief A unary predicate that decides when to push into a
* breadth-first search queue.
*
* This predicate stores a color map that is used to determine
* when to push. If it is provided with a key for which the color
* is white, it darkens the color to gray and returns true (so
* that the value will be pushed appropriately); if the color is
* not white, it returns false so that the vertex will be
* ignored.
*/
template<typename ColorMap>
struct darken_and_push
{
typedef typename property_traits<ColorMap>::key_type argument_type;
typedef bool result_type;
explicit darken_and_push(const ColorMap& color) : color(color) { }
bool operator()(const argument_type& value) const
{
typedef color_traits<typename property_traits<ColorMap>::value_type>
Color;
if (get(color, value) == Color::white()) {
put(color, value, Color::gray());
return true;
} else {
return false;
}
}
ColorMap color;
};
template<typename IndexMap>
struct has_not_been_seen
{
typedef bool result_type;
has_not_been_seen() { }
has_not_been_seen(std::size_t n, IndexMap index_map)
: seen(n), index_map(index_map) {}
template<typename Key>
result_type operator()(Key key)
{
bool result = seen[get(index_map, key)];
seen[get(index_map, key)] = true;
return !result;
}
void swap(has_not_been_seen& other)
{
using std::swap;
swap(seen, other.seen);
swap(index_map, other.index_map);
}
private:
dynamic_bitset<> seen;
IndexMap index_map;
};
template<typename IndexMap>
inline void
swap(has_not_been_seen<IndexMap>& x, has_not_been_seen<IndexMap>& y)
{
x.swap(y);
}
template <class DistributedGraph, class ColorMap, class BFSVisitor,
class BufferRef, class VertexIndexMap>
inline void
parallel_bfs_helper
(DistributedGraph& g,
typename graph_traits<DistributedGraph>::vertex_descriptor s,
ColorMap color,
BFSVisitor vis,
BufferRef Q,
VertexIndexMap)
{
set_property_map_role(vertex_color, color);
color.set_consistency_model(0);
breadth_first_search(g, s, Q.ref, vis, color);
}
template <class DistributedGraph, class ColorMap, class BFSVisitor,
class VertexIndexMap>
void parallel_bfs_helper
(DistributedGraph& g,
typename graph_traits<DistributedGraph>::vertex_descriptor s,
ColorMap color,
BFSVisitor vis,
boost::param_not_found,
VertexIndexMap vertex_index)
{
using boost::graph::parallel::process_group;
typedef graph_traits<DistributedGraph> Traits;
typedef typename Traits::vertex_descriptor Vertex;
typedef typename boost::graph::parallel::process_group_type<DistributedGraph>::type
process_group_type;
set_property_map_role(vertex_color, color);
color.set_consistency_model(0);
// Buffer default
typedef typename property_map<DistributedGraph, vertex_owner_t>
::const_type vertex_owner_map;
typedef boost::graph::distributed::distributed_queue<
process_group_type, vertex_owner_map, queue<Vertex>,
detail::darken_and_push<ColorMap> > queue_t;
queue_t Q(process_group(g),
get(vertex_owner, g),
detail::darken_and_push<ColorMap>(color));
breadth_first_search(g, s, Q, vis, color);
}
template <class DistributedGraph, class ColorMap, class BFSVisitor,
class P, class T, class R>
void bfs_helper
(DistributedGraph& g,
typename graph_traits<DistributedGraph>::vertex_descriptor s,
ColorMap color,
BFSVisitor vis,
const bgl_named_params<P, T, R>& params,
boost::mpl::true_)
{
parallel_bfs_helper
(g, s, color, vis, get_param(params, buffer_param_t()),
choose_const_pmap(get_param(params, vertex_index), g, vertex_index));
}
}
}
#endif // BOOST_GRAPH_PARALLEL_BFS_HPP
+213
View File
@@ -0,0 +1,213 @@
// Copyright (C) 2004-2006 The Trustees of Indiana University.
// Use, modification and distribution is subject to the Boost Software
// License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
// Authors: Douglas Gregor
// Andrew Lumsdaine
//
// Distributed graph concepts and helpers
//
#ifndef BOOST_GRAPH_DISTRIBUTED_CONCEPTS_HPP
#define BOOST_GRAPH_DISTRIBUTED_CONCEPTS_HPP
#ifndef BOOST_GRAPH_USE_MPI
#error "Parallel BGL files should not be included unless <boost/graph/use_mpi.hpp> has been included"
#endif
#include <boost/version.hpp>
#include <boost/graph/graph_traits.hpp>
#include <boost/graph/graph_concepts.hpp>
#include <boost/concept/assert.hpp>
#if BOOST_VERSION >= 103500
# include <boost/concept/detail/concept_def.hpp>
#endif
namespace boost {
#if BOOST_VERSION >= 103500
namespace concepts {
#endif
#if BOOST_VERSION < 103500
template <class G>
struct DistributedVertexListGraphConcept
{
typedef typename graph_traits<G>::vertex_iterator vertex_iterator;
typedef typename graph_traits<G>::vertices_size_type vertices_size_type;
typedef typename graph_traits<G>::traversal_category
traversal_category;
void constraints() {
BOOST_CONCEPT_ASSERT(( GraphConcept<G> ));
BOOST_CONCEPT_ASSERT(( MultiPassInputIteratorConcept<vertex_iterator> ));
BOOST_CONCEPT_ASSERT(( ConvertibleConcept<traversal_category,
distributed_vertex_list_graph_tag> ));
#ifdef BOOST_VECTOR_AS_GRAPH_GRAPH_ADL_HACK
// dwa 2003/7/11 -- This clearly shouldn't be necessary, but if
// you want to use vector_as_graph, it is! I'm sure the graph
// library leaves these out all over the place. Probably a
// redesign involving specializing a template with a static
// member function is in order :(
using boost::vertices;
#endif
p = vertices(g);
v = *p.first;
const_constraints(g);
}
void const_constraints(const G& cg) {
#ifdef BOOST_VECTOR_AS_GRAPH_GRAPH_ADL_HACK
// dwa 2003/7/11 -- This clearly shouldn't be necessary, but if
// you want to use vector_as_graph, it is! I'm sure the graph
// library leaves these out all over the place. Probably a
// redesign involving specializing a template with a static
// member function is in order :(
using boost::vertices;
#endif
p = vertices(cg);
v = *p.first;
V = num_vertices(cg);
}
std::pair<vertex_iterator,vertex_iterator> p;
typename graph_traits<G>::vertex_descriptor v;
G g;
vertices_size_type V;
};
template <class G>
struct DistributedEdgeListGraphConcept
{
typedef typename graph_traits<G>::edge_descriptor edge_descriptor;
typedef typename graph_traits<G>::edge_iterator edge_iterator;
typedef typename graph_traits<G>::edges_size_type edges_size_type;
typedef typename graph_traits<G>::traversal_category
traversal_category;
void constraints() {
BOOST_CONCEPT_ASSERT(( GraphConcept<G> ));
BOOST_CONCEPT_ASSERT(( MultiPassInputIteratorConcept<edge_iterator> ));
BOOST_CONCEPT_ASSERT(( DefaultConstructibleConcept<edge_descriptor> ));
BOOST_CONCEPT_ASSERT(( EqualityComparableConcept<edge_descriptor> ));
BOOST_CONCEPT_ASSERT(( AssignableConcept<edge_descriptor> ));
BOOST_CONCEPT_ASSERT(( ConvertibleConcept<traversal_category,
distributed_edge_list_graph_tag> ));
p = edges(g);
e = *p.first;
u = source(e, g);
v = target(e, g);
const_constraints(g);
}
void const_constraints(const G& cg) {
p = edges(cg);
E = num_edges(cg);
e = *p.first;
u = source(e, cg);
v = target(e, cg);
}
std::pair<edge_iterator,edge_iterator> p;
typename graph_traits<G>::vertex_descriptor u, v;
typename graph_traits<G>::edge_descriptor e;
edges_size_type E;
G g;
};
#else
BOOST_concept(DistributedVertexListGraph,(G))
: Graph<G>
{
typedef typename graph_traits<G>::vertex_iterator vertex_iterator;
typedef typename graph_traits<G>::vertices_size_type vertices_size_type;
typedef typename graph_traits<G>::traversal_category
traversal_category;
~DistributedVertexListGraph() {
BOOST_CONCEPT_ASSERT((MultiPassInputIterator<vertex_iterator>));
BOOST_CONCEPT_ASSERT((Convertible<traversal_category,
distributed_vertex_list_graph_tag>));
#ifdef BOOST_VECTOR_AS_GRAPH_GRAPH_ADL_HACK
// dwa 2003/7/11 -- This clearly shouldn't be necessary, but if
// you want to use vector_as_graph, it is! I'm sure the graph
// library leaves these out all over the place. Probably a
// redesign involving specializing a template with a static
// member function is in order :(
using boost::vertices;
#endif
p = vertices(g);
v = *p.first;
const_constraints(g);
}
void const_constraints(const G& cg) {
#ifdef BOOST_VECTOR_AS_GRAPH_GRAPH_ADL_HACK
// dwa 2003/7/11 -- This clearly shouldn't be necessary, but if
// you want to use vector_as_graph, it is! I'm sure the graph
// library leaves these out all over the place. Probably a
// redesign involving specializing a template with a static
// member function is in order :(
using boost::vertices;
#endif
p = vertices(cg);
v = *p.first;
V = num_vertices(cg);
}
std::pair<vertex_iterator,vertex_iterator> p;
typename graph_traits<G>::vertex_descriptor v;
G g;
vertices_size_type V;
};
BOOST_concept(DistributedEdgeListGraph,(G))
: Graph<G>
{
typedef typename graph_traits<G>::edge_descriptor edge_descriptor;
typedef typename graph_traits<G>::edge_iterator edge_iterator;
typedef typename graph_traits<G>::edges_size_type edges_size_type;
typedef typename graph_traits<G>::traversal_category
traversal_category;
~DistributedEdgeListGraph() {
BOOST_CONCEPT_ASSERT((MultiPassInputIterator<edge_iterator>));
BOOST_CONCEPT_ASSERT((DefaultConstructible<edge_descriptor>));
BOOST_CONCEPT_ASSERT((EqualityComparable<edge_descriptor>));
BOOST_CONCEPT_ASSERT((Assignable<edge_descriptor>));
BOOST_CONCEPT_ASSERT((Convertible<traversal_category,
distributed_edge_list_graph_tag>));
p = edges(g);
e = *p.first;
u = source(e, g);
v = target(e, g);
const_constraints(g);
}
void const_constraints(const G& cg) {
p = edges(cg);
E = num_edges(cg);
e = *p.first;
u = source(e, cg);
v = target(e, cg);
}
std::pair<edge_iterator,edge_iterator> p;
typename graph_traits<G>::vertex_descriptor u, v;
typename graph_traits<G>::edge_descriptor e;
edges_size_type E;
G g;
};
#endif
#if BOOST_VERSION >= 103500
} // end namespace concepts
using concepts::DistributedVertexListGraphConcept;
using concepts::DistributedEdgeListGraphConcept;
#endif
} // end namespace boost
#if BOOST_VERSION >= 103500
# include <boost/concept/detail/concept_undef.hpp>
#endif
#endif // BOOST_GRAPH_DISTRIBUTED_CONCEPTS_HPP
@@ -0,0 +1,108 @@
// Copyright (C) 2004-2006 The Trustees of Indiana University.
// Use, modification and distribution is subject to the Boost Software
// License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
// Authors: Douglas Gregor
// Andrew Lumsdaine
#ifndef BOOST_FILTERED_QUEUE_HPP
#define BOOST_FILTERED_QUEUE_HPP
#ifndef BOOST_GRAPH_USE_MPI
#error "Parallel BGL files should not be included unless <boost/graph/use_mpi.hpp> has been included"
#endif
#include <algorithm>
namespace boost {
/** Queue adaptor that filters elements pushed into the queue
* according to some predicate.
*/
template<typename Buffer, typename Predicate>
class filtered_queue
{
public:
typedef Buffer buffer_type;
typedef Predicate predicate_type;
typedef typename Buffer::value_type value_type;
typedef typename Buffer::size_type size_type;
/**
* Constructs a new filtered queue with an initial buffer and a
* predicate.
*
* @param buffer the initial buffer
* @param pred the predicate
*/
explicit
filtered_queue(const buffer_type& buffer = buffer_type(),
const predicate_type& pred = predicate_type())
: buffer(buffer), pred(pred) {}
/** Push a value into the queue.
*
* If the predicate returns @c true for @p x, pushes @p x into the
* buffer.
*/
void push(const value_type& x) { if (pred(x)) buffer.push(x); }
/** Pop the front element off the buffer.
*
* @pre @c !empty()
*/
void pop() { buffer.pop(); }
/** Retrieve the front (top) element in the buffer.
*
* @pre @c !empty()
*/
value_type& top() { return buffer.top(); }
/**
* \overload
*/
const value_type& top() const { return buffer.top(); }
/** Determine the number of elements in the buffer. */
size_type size() const { return buffer.size(); }
/** Determine if the buffer is empty. */
bool empty() const { return buffer.empty(); }
/** Get a reference to the underlying buffer. */
buffer_type& base() { return buffer; }
const buffer_type& base() const { return buffer; }
/** Swap the contents of this with @p other. */
void swap(filtered_queue& other)
{
using std::swap;
swap(buffer, other.buffer);
swap(pred, other.pred);
}
private:
buffer_type buffer;
predicate_type pred;
};
/** Create a filtered queue. */
template<typename Buffer, typename Predicate>
inline filtered_queue<Buffer, Predicate>
make_filtered_queue(const Buffer& buffer, const Predicate& pred)
{ return filtered_queue<Buffer, Predicate>(buffer, pred); }
/** Swap a filtered_queue. */
template<typename Buffer, typename Predicate>
inline void
swap(filtered_queue<Buffer, Predicate>& x,
filtered_queue<Buffer, Predicate>& y)
{
x.swap(y);
}
} // end namespace boost
#endif // BOOST_FILTERED_QUEUE_HPP
+177
View File
@@ -0,0 +1,177 @@
// Copyright (C) 2004-2006 The Trustees of Indiana University.
// Use, modification and distribution is subject to the Boost Software
// License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
// Authors: Douglas Gregor
// Andrew Lumsdaine
#include <boost/optional.hpp>
#include <cassert>
#include <boost/graph/parallel/algorithm.hpp>
#include <boost/graph/parallel/process_group.hpp>
#include <functional>
#include <algorithm>
#include <boost/graph/parallel/simple_trigger.hpp>
#ifndef BOOST_GRAPH_USE_MPI
#error "Parallel BGL files should not be included unless <boost/graph/use_mpi.hpp> has been included"
#endif
namespace boost { namespace graph { namespace distributed {
template<BOOST_DISTRIBUTED_QUEUE_PARMS>
BOOST_DISTRIBUTED_QUEUE_TYPE::
distributed_queue(const ProcessGroup& process_group, const OwnerMap& owner,
const Buffer& buffer, bool polling)
: process_group(process_group, attach_distributed_object()),
owner(owner),
buffer(buffer),
polling(polling)
{
if (!polling)
outgoing_buffers.reset(
new outgoing_buffers_t(num_processes(process_group)));
setup_triggers();
}
template<BOOST_DISTRIBUTED_QUEUE_PARMS>
BOOST_DISTRIBUTED_QUEUE_TYPE::
distributed_queue(const ProcessGroup& process_group, const OwnerMap& owner,
const Buffer& buffer, const UnaryPredicate& pred,
bool polling)
: process_group(process_group, attach_distributed_object()),
owner(owner),
buffer(buffer),
pred(pred),
polling(polling)
{
if (!polling)
outgoing_buffers.reset(
new outgoing_buffers_t(num_processes(process_group)));
setup_triggers();
}
template<BOOST_DISTRIBUTED_QUEUE_PARMS>
BOOST_DISTRIBUTED_QUEUE_TYPE::
distributed_queue(const ProcessGroup& process_group, const OwnerMap& owner,
const UnaryPredicate& pred, bool polling)
: process_group(process_group, attach_distributed_object()),
owner(owner),
pred(pred),
polling(polling)
{
if (!polling)
outgoing_buffers.reset(
new outgoing_buffers_t(num_processes(process_group)));
setup_triggers();
}
template<BOOST_DISTRIBUTED_QUEUE_PARMS>
void
BOOST_DISTRIBUTED_QUEUE_TYPE::push(const value_type& x)
{
typename ProcessGroup::process_id_type dest = get(owner, x);
if (outgoing_buffers)
outgoing_buffers->at(dest).push_back(x);
else if (dest == process_id(process_group))
buffer.push(x);
else
send(process_group, get(owner, x), msg_push, x);
}
template<BOOST_DISTRIBUTED_QUEUE_PARMS>
bool
BOOST_DISTRIBUTED_QUEUE_TYPE::empty() const
{
/* Processes will stay here until the buffer is nonempty or
synchronization with the other processes indicates that all local
buffers are empty (and no messages are in transit).
*/
while (buffer.empty() && !do_synchronize()) ;
return buffer.empty();
}
template<BOOST_DISTRIBUTED_QUEUE_PARMS>
typename BOOST_DISTRIBUTED_QUEUE_TYPE::size_type
BOOST_DISTRIBUTED_QUEUE_TYPE::size() const
{
empty();
return buffer.size();
}
template<BOOST_DISTRIBUTED_QUEUE_PARMS>
void BOOST_DISTRIBUTED_QUEUE_TYPE::setup_triggers()
{
using boost::graph::parallel::simple_trigger;
simple_trigger(process_group, msg_push, this,
&distributed_queue::handle_push);
simple_trigger(process_group, msg_multipush, this,
&distributed_queue::handle_multipush);
}
template<BOOST_DISTRIBUTED_QUEUE_PARMS>
void
BOOST_DISTRIBUTED_QUEUE_TYPE::
handle_push(int /*source*/, int /*tag*/, const value_type& value,
trigger_receive_context)
{
if (pred(value)) buffer.push(value);
}
template<BOOST_DISTRIBUTED_QUEUE_PARMS>
void
BOOST_DISTRIBUTED_QUEUE_TYPE::
handle_multipush(int /*source*/, int /*tag*/,
const std::vector<value_type>& values,
trigger_receive_context)
{
for (std::size_t i = 0; i < values.size(); ++i)
if (pred(values[i])) buffer.push(values[i]);
}
template<BOOST_DISTRIBUTED_QUEUE_PARMS>
bool
BOOST_DISTRIBUTED_QUEUE_TYPE::do_synchronize() const
{
#ifdef PBGL_ACCOUNTING
++num_synchronizations;
#endif
using boost::parallel::all_reduce;
using std::swap;
typedef typename ProcessGroup::process_id_type process_id_type;
if (outgoing_buffers) {
// Transfer all of the push requests
process_id_type id = process_id(process_group);
process_id_type np = num_processes(process_group);
for (process_id_type dest = 0; dest < np; ++dest) {
outgoing_buffer_t& outgoing = outgoing_buffers->at(dest);
std::size_t size = outgoing.size();
if (size != 0) {
if (dest != id) {
send(process_group, dest, msg_multipush, outgoing);
} else {
for (std::size_t i = 0; i < size; ++i)
buffer.push(outgoing[i]);
}
outgoing.clear();
}
}
}
synchronize(process_group);
unsigned local_size = buffer.size();
unsigned global_size =
all_reduce(process_group, local_size, std::plus<unsigned>());
return global_size == 0;
}
} } } // end namespace boost::graph::distributed
+278
View File
@@ -0,0 +1,278 @@
// Copyright (C) 2004-2006 The Trustees of Indiana University.
// Use, modification and distribution is subject to the Boost Software
// License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
// Authors: Douglas Gregor
// Andrew Lumsdaine
#ifndef BOOST_GRAPH_DISTRIBUTED_QUEUE_HPP
#define BOOST_GRAPH_DISTRIBUTED_QUEUE_HPP
#ifndef BOOST_GRAPH_USE_MPI
#error "Parallel BGL files should not be included unless <boost/graph/use_mpi.hpp> has been included"
#endif
#include <boost/graph/parallel/process_group.hpp>
#include <boost/optional.hpp>
#include <boost/shared_ptr.hpp>
#include <vector>
namespace boost { namespace graph { namespace distributed {
/// A unary predicate that always returns "true".
struct always_push
{
template<typename T> bool operator()(const T&) const { return true; }
};
/** A distributed queue adaptor.
*
* Class template @c distributed_queue implements a distributed queue
* across a process group. The distributed queue is an adaptor over an
* existing (local) queue, which must model the @ref Buffer
* concept. Each process stores a distinct copy of the local queue,
* from which it draws or removes elements via the @ref pop and @ref
* top members.
*
* The value type of the local queue must be a model of the @ref
* GlobalDescriptor concept. The @ref push operation of the
* distributed queue passes (via a message) the value to its owning
* processor. Thus, the elements within a particular local queue are
* guaranteed to have the process owning that local queue as an owner.
*
* Synchronization of distributed queues occurs in the @ref empty and
* @ref size functions, which will only return "empty" values (true or
* 0, respectively) when the entire distributed queue is empty. If the
* local queue is empty but the distributed queue is not, the
* operation will block until either condition changes. When the @ref
* size function of a nonempty queue returns, it returns the size of
* the local queue. These semantics were selected so that sequential
* code that processes elements in the queue via the following idiom
* can be parallelized via introduction of a distributed queue:
*
* distributed_queue<...> Q;
* Q.push(x);
* while (!Q.empty()) {
* // do something, that may push a value onto Q
* }
*
* In the parallel version, the initial @ref push operation will place
* the value @c x onto its owner's queue. All processes will
* synchronize at the call to empty, and only the process owning @c x
* will be allowed to execute the loop (@ref Q.empty() returns
* false). This iteration may in turn push values onto other remote
* queues, so when that process finishes execution of the loop body
* and all processes synchronize again in @ref empty, more processes
* may have nonempty local queues to execute. Once all local queues
* are empty, @ref Q.empty() returns @c false for all processes.
*
* The distributed queue can receive messages at two different times:
* during synchronization and when polling @ref empty. Messages are
* always received during synchronization, to ensure that accurate
* local queue sizes can be determines. However, whether @ref empty
* should poll for messages is specified as an option to the
* constructor. Polling may be desired when the order in which
* elements in the queue are processed is not important, because it
* permits fewer synchronization steps and less communication
* overhead. However, when more strict ordering guarantees are
* required, polling may be semantically incorrect. By disabling
* polling, one ensures that parallel execution using the idiom above
* will not process an element at a later "level" before an earlier
* "level".
*
* The distributed queue nearly models the @ref Buffer
* concept. However, the @ref push routine does not necessarily
* increase the result of @c size() by one (although the size of the
* global queue does increase by one).
*/
template<typename ProcessGroup, typename OwnerMap, typename Buffer,
typename UnaryPredicate = always_push>
class distributed_queue
{
typedef distributed_queue self_type;
enum {
/** Message indicating a remote push. The message contains a
* single value x of type value_type that is to be pushed on the
* receiver's queue.
*/
msg_push,
/** Push many elements at once. */
msg_multipush
};
public:
typedef ProcessGroup process_group_type;
typedef Buffer buffer_type;
typedef typename buffer_type::value_type value_type;
typedef typename buffer_type::size_type size_type;
/** Construct a new distributed queue.
*
* Build a new distributed queue that communicates over the given @p
* process_group, whose local queue is initialized via @p buffer and
* which may or may not poll for messages.
*/
explicit
distributed_queue(const ProcessGroup& process_group,
const OwnerMap& owner,
const Buffer& buffer,
bool polling = false);
/** Construct a new distributed queue.
*
* Build a new distributed queue that communicates over the given @p
* process_group, whose local queue is initialized via @p buffer and
* which may or may not poll for messages.
*/
explicit
distributed_queue(const ProcessGroup& process_group = ProcessGroup(),
const OwnerMap& owner = OwnerMap(),
const Buffer& buffer = Buffer(),
const UnaryPredicate& pred = UnaryPredicate(),
bool polling = false);
/** Construct a new distributed queue.
*
* Build a new distributed queue that communicates over the given @p
* process_group, whose local queue is default-initalized and which
* may or may not poll for messages.
*/
distributed_queue(const ProcessGroup& process_group, const OwnerMap& owner,
const UnaryPredicate& pred, bool polling = false);
/** Virtual destructor required with virtual functions.
*
*/
virtual ~distributed_queue() {}
/** Push an element onto the distributed queue.
*
* The element will be sent to its owner process to be added to that
* process's local queue. If polling is enabled for this queue and
* the owner process is the current process, the value will be
* immediately pushed onto the local queue.
*
* Complexity: O(1) messages of size O(sizeof(value_type)) will be
* transmitted.
*/
void push(const value_type& x);
/** Pop an element off the local queue.
*
* @p @c !empty()
*/
void pop() { buffer.pop(); }
/**
* Return the element at the top of the local queue.
*
* @p @c !empty()
*/
value_type& top() { return buffer.top(); }
/**
* \overload
*/
const value_type& top() const { return buffer.top(); }
/** Determine if the queue is empty.
*
* When the local queue is nonempty, returns @c true. If the local
* queue is empty, synchronizes with all other processes in the
* process group until either (1) the local queue is nonempty
* (returns @c true) (2) the entire distributed queue is empty
* (returns @c false).
*/
bool empty() const;
/** Determine the size of the local queue.
*
* The behavior of this routine is equivalent to the behavior of
* @ref empty, except that when @ref empty returns true this
* function returns the size of the local queue and when @ref empty
* returns false this function returns zero.
*/
size_type size() const;
// private:
/** Synchronize the distributed queue and determine if all queues
* are empty.
*
* \returns \c true when all local queues are empty, or false if at least
* one of the local queues is nonempty.
* Defined as virtual for derived classes like depth_limited_distributed_queue.
*/
virtual bool do_synchronize() const;
private:
// Setup triggers
void setup_triggers();
// Message handlers
void
handle_push(int source, int tag, const value_type& value,
trigger_receive_context);
void
handle_multipush(int source, int tag, const std::vector<value_type>& values,
trigger_receive_context);
mutable ProcessGroup process_group;
OwnerMap owner;
mutable Buffer buffer;
UnaryPredicate pred;
bool polling;
typedef std::vector<value_type> outgoing_buffer_t;
typedef std::vector<outgoing_buffer_t> outgoing_buffers_t;
shared_ptr<outgoing_buffers_t> outgoing_buffers;
};
/// Helper macro containing the normal names for the template
/// parameters to distributed_queue.
#define BOOST_DISTRIBUTED_QUEUE_PARMS \
typename ProcessGroup, typename OwnerMap, typename Buffer, \
typename UnaryPredicate
/// Helper macro containing the normal template-id for
/// distributed_queue.
#define BOOST_DISTRIBUTED_QUEUE_TYPE \
distributed_queue<ProcessGroup, OwnerMap, Buffer, UnaryPredicate>
/** Synchronize all processes involved with the given distributed queue.
*
* This function will synchronize all of the local queues for a given
* distributed queue, by ensuring that no additional messages are in
* transit. It is rarely required by the user, because most
* synchronization of distributed queues occurs via the @c empty or @c
* size methods.
*/
template<BOOST_DISTRIBUTED_QUEUE_PARMS>
inline void
synchronize(const BOOST_DISTRIBUTED_QUEUE_TYPE& Q)
{ Q.do_synchronize(); }
/// Construct a new distributed queue.
template<typename ProcessGroup, typename OwnerMap, typename Buffer>
inline distributed_queue<ProcessGroup, OwnerMap, Buffer>
make_distributed_queue(const ProcessGroup& process_group,
const OwnerMap& owner,
const Buffer& buffer,
bool polling = false)
{
typedef distributed_queue<ProcessGroup, OwnerMap, Buffer> result_type;
return result_type(process_group, owner, buffer, polling);
}
} } } // end namespace boost::graph::distributed
#include <boost/graph/distributed/detail/queue.ipp>
#undef BOOST_DISTRIBUTED_QUEUE_TYPE
#undef BOOST_DISTRIBUTED_QUEUE_PARMS
#endif // BOOST_GRAPH_DISTRIBUTED_QUEUE_HPP
@@ -0,0 +1,116 @@
// Copyright (C) 2006 The Trustees of Indiana University.
// Use, modification and distribution is subject to the Boost Software
// License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
// Authors: Douglas Gregor
// Jeremiah Willcock
// Andrew Lumsdaine
// Distributed version of the two-bit color map
#ifndef BOOST_DISTRIBUTED_TWO_BIT_COLOR_MAP_HPP
#define BOOST_DISTRIBUTED_TWO_BIT_COLOR_MAP_HPP
#ifndef BOOST_GRAPH_USE_MPI
#error "Parallel BGL files should not be included unless <boost/graph/use_mpi.hpp> has been included"
#endif
#include <boost/graph/two_bit_color_map.hpp>
#include <boost/property_map/parallel/distributed_property_map.hpp>
#include <boost/property_map/parallel/local_property_map.hpp>
namespace boost {
template<typename ProcessGroup, typename GlobalMap, typename StorageMap>
class two_bit_color_map<local_property_map<ProcessGroup,GlobalMap,StorageMap> >
: public parallel::distributed_property_map<ProcessGroup, GlobalMap,
two_bit_color_map<StorageMap> >
{
typedef two_bit_color_map<StorageMap> local_map;
typedef parallel::distributed_property_map<ProcessGroup, GlobalMap,
local_map >
inherited;
typedef local_property_map<ProcessGroup, GlobalMap, StorageMap>
index_map_type;
public:
two_bit_color_map(std::size_t inital_size,
const index_map_type& index = index_map_type())
: inherited(index.process_group(), index.global(),
local_map(inital_size, index.base())) { }
inherited& base() { return *this; }
const inherited& base() const { return *this; }
};
template<typename ProcessGroup, typename GlobalMap, typename StorageMap>
inline two_bit_color_type
get(two_bit_color_map<local_property_map<ProcessGroup,GlobalMap,StorageMap> >
const& pm,
typename property_traits<GlobalMap>::key_type key)
{
return get(pm.base(), key);
}
template<typename ProcessGroup, typename GlobalMap, typename StorageMap>
inline void
put(two_bit_color_map<local_property_map<ProcessGroup,GlobalMap,StorageMap> >
const& pm,
typename property_traits<GlobalMap>::key_type key,
two_bit_color_type value)
{
put(pm.base(), key, value);
}
template<typename ProcessGroup, typename GlobalMap, typename StorageMap>
class two_bit_color_map<parallel::distributed_property_map<
ProcessGroup, GlobalMap, StorageMap> >
: public parallel::distributed_property_map<
ProcessGroup, GlobalMap, two_bit_color_map<StorageMap> >
{
typedef two_bit_color_map<StorageMap> local_map;
typedef parallel::distributed_property_map<ProcessGroup,GlobalMap,local_map>
inherited;
typedef parallel::distributed_property_map<ProcessGroup, GlobalMap,
StorageMap>
index_map_type;
public:
two_bit_color_map(std::size_t inital_size,
const index_map_type& index = index_map_type())
: inherited(index.process_group(), index.global(),
local_map(inital_size, index.base())) { }
inherited& base() { return *this; }
const inherited& base() const { return *this; }
};
template<typename ProcessGroup, typename GlobalMap, typename StorageMap>
inline two_bit_color_type
get(two_bit_color_map<
parallel::distributed_property_map<
ProcessGroup, GlobalMap, two_bit_color_map<StorageMap> > > const& pm,
typename property_traits<GlobalMap>::key_type key)
{
return get(pm.base(), key);
}
template<typename ProcessGroup, typename GlobalMap, typename StorageMap>
inline void
put(two_bit_color_map<
parallel::distributed_property_map<
ProcessGroup, GlobalMap, two_bit_color_map<StorageMap> > > const& pm,
typename property_traits<GlobalMap>::key_type key,
two_bit_color_type value)
{
put(pm.base(), key, value);
}
} // end namespace boost
#endif // BOOST_DISTRIBUTED_TWO_BIT_COLOR_MAP_HPP