1 // Copyright (C) 2004-2006 The Trustees of Indiana University.
2
3 // Use, modification and distribution is subject to the Boost Software
4 // License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
5 // http://www.boost.org/LICENSE_1_0.txt)
6
7 // Authors: Douglas Gregor
8 // Andrew Lumsdaine
9 #include <boost/graph/use_mpi.hpp>
10 #include <boost/config.hpp>
11 #include <boost/throw_exception.hpp>
12 #include <boost/graph/distributed/queue.hpp>
13 #include <boost/test/minimal.hpp>
14 #include <boost/graph/distributed/mpi_process_group.hpp>
15 #include <boost/pending/queue.hpp>
16 #include <boost/property_map/property_map.hpp>
17 #include <utility>
18 #include <iostream>
19
20 #ifdef BOOST_NO_EXCEPTIONS
21 void
throw_exception(std::exception const & ex)22 boost::throw_exception(std::exception const& ex)
23 {
24 std::cout << ex.what() << std::endl;
25 abort();
26 }
27 #endif
28
29 using boost::graph::distributed::mpi_process_group;
30
31 struct global_value
32 {
global_valueglobal_value33 global_value(int p = -1, std::size_t l = 0) : processor(p), value(l) {}
34
35 int processor;
36 std::size_t value;
37
38 template<typename Archiver>
serializeglobal_value39 void serialize(Archiver& ar, const unsigned int /*version*/)
40 {
41 ar & processor & value;
42 }
43 };
44
45 namespace boost { namespace mpi {
46 template<> struct is_mpi_datatype<global_value> : mpl::true_ { };
47 } } // end namespace boost::mpi
48
49 BOOST_IS_BITWISE_SERIALIZABLE(global_value)
50 BOOST_CLASS_IMPLEMENTATION(global_value,object_serializable)
51 BOOST_CLASS_TRACKING(global_value,track_never)
52
53 inline bool operator==(const global_value& x, const global_value& y)
54 { return x.processor == y.processor && x.value == y.value; }
55
56 struct global_value_owner_map
57 {
58 typedef int value_type;
59 typedef value_type reference;
60 typedef global_value key_type;
61 typedef boost::readable_property_map_tag category;
62 };
63
get(global_value_owner_map,global_value k)64 int get(global_value_owner_map, global_value k)
65 {
66 return k.processor;
67 }
68
test_distributed_queue()69 void test_distributed_queue()
70 {
71 mpi_process_group process_group;
72
73 typedef boost::queue<global_value> local_queue_type;
74
75 typedef boost::graph::distributed::distributed_queue<mpi_process_group,
76 global_value_owner_map,
77 local_queue_type> dist_queue_type;
78
79 dist_queue_type Q(process_group, global_value_owner_map());
80
81 mpi_process_group::process_id_type id = process_id(process_group),
82 n = num_processes(process_group);
83 global_value v(0, 0);
84
85 if (id == 0) {
86 std::cerr << "Should print level of each processor in a binary tree:\n";
87 }
88 synchronize(process_group);
89
90 if (id == n-1) Q.push(v);
91 while (!Q.empty()) {
92 v = Q.top(); Q.pop();
93
94 std::cerr << "#" << id << ": level = " << v.value << std::endl;
95
96 int level_begin = 1;
97 for (std::size_t i = 0; i < v.value; ++i) level_begin *= 2;
98 int level_end = level_begin * 2;
99 BOOST_CHECK(level_begin <= (id + 1));
100 BOOST_CHECK((id + 1) <= level_end);
101
102 ++v.value;
103 v.processor = v.processor * 2 + 1;
104 if (v.processor < n) Q.push(v);
105 ++v.processor;
106 if (v.processor < n) Q.push(v);
107 }
108 }
109
test_main(int argc,char ** argv)110 int test_main(int argc, char** argv)
111 {
112 boost::mpi::environment env(argc, argv);
113 test_distributed_queue();
114 return 0;
115 }
116