Imported Upstream version 1.57.0
[platform/upstream/boost.git] / libs / mpi / test / nonblocking_test.cpp
1 // Copyright (C) 2006 Douglas Gregor.
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 // A test of the nonblocking point-to-point operations.
8 #include <boost/mpi/nonblocking.hpp>
9 #include <boost/mpi/communicator.hpp>
10 #include <boost/mpi/environment.hpp>
11 #include <boost/test/minimal.hpp>
12 #include "gps_position.hpp"
13 #include <boost/lexical_cast.hpp>
14 #include <boost/serialization/string.hpp>
15 #include <boost/serialization/list.hpp>
16 #include <iterator>
17 #include <algorithm>
18
19 using boost::mpi::communicator;
20 using boost::mpi::request;
21 using boost::mpi::status;
22
23 enum method_kind { 
24   mk_wait_any, mk_test_any, mk_wait_all, mk_wait_all_keep, 
25   mk_test_all, mk_test_all_keep, mk_wait_some, mk_wait_some_keep,
26   mk_test_some, mk_test_some_keep,
27   mk_all,                // use to run all of the different methods
28   mk_all_except_test_all // use for serialized types
29 };
30
31 static const char* method_kind_names[mk_all] = {
32   "wait_any",
33   "test_any",
34   "wait_all",
35   "wait_all (keep results)",
36   "test_all",
37   "test_all (keep results)",
38   "wait_some",
39   "wait_some (keep results)",
40   "test_some",
41   "test_some (keep results)"
42 };
43
44
45 template<typename T>
46 void
47 nonblocking_test(const communicator& comm, const T* values, int num_values, 
48                  const char* kind, method_kind method = mk_all)
49 {
50   using boost::mpi::wait_any;
51   using boost::mpi::test_any;
52   using boost::mpi::wait_all;
53   using boost::mpi::test_all;
54   using boost::mpi::wait_some;
55   using boost::mpi::test_some;
56
57   if (method == mk_all || method == mk_all_except_test_all) {
58     nonblocking_test(comm, values, num_values, kind, mk_wait_any);
59     nonblocking_test(comm, values, num_values, kind, mk_test_any);
60     nonblocking_test(comm, values, num_values, kind, mk_wait_all);
61     nonblocking_test(comm, values, num_values, kind, mk_wait_all_keep);
62     if (method == mk_all) {
63       nonblocking_test(comm, values, num_values, kind, mk_test_all);
64       nonblocking_test(comm, values, num_values, kind, mk_test_all_keep);
65     }
66     nonblocking_test(comm, values, num_values, kind, mk_wait_some);
67     nonblocking_test(comm, values, num_values, kind, mk_wait_some_keep);
68     nonblocking_test(comm, values, num_values, kind, mk_test_some);
69     nonblocking_test(comm, values, num_values, kind, mk_test_some_keep);
70   } else {
71     if (comm.rank() == 0) {
72       std::cout << "Testing " << method_kind_names[method] 
73                 << " with " << kind << "...";
74       std::cout.flush();
75     }
76
77     typedef std::pair<status, std::vector<request>::iterator> 
78       status_iterator_pair;
79
80     T incoming_value;
81     std::vector<T> incoming_values(num_values);
82
83     std::vector<request> reqs;
84     // Send/receive the first value
85     reqs.push_back(comm.isend((comm.rank() + 1) % comm.size(), 0, values[0]));
86     reqs.push_back(comm.irecv((comm.rank() + comm.size() - 1) % comm.size(),
87                               0, incoming_value));
88
89     if (method != mk_wait_any && method != mk_test_any) {
90 #ifndef LAM_MPI
91       // We've run into problems here (with 0-length messages) with
92       // LAM/MPI on Mac OS X and x86-86 Linux. Will investigate
93       // further at a later time, but the problem only seems to occur
94       // when using shared memory, not TCP.
95
96       // Send/receive an empty message
97       reqs.push_back(comm.isend((comm.rank() + 1) % comm.size(), 1));
98       reqs.push_back(comm.irecv((comm.rank() + comm.size() - 1) % comm.size(),
99                                 1));
100 #endif
101
102       // Send/receive an array
103       reqs.push_back(comm.isend((comm.rank() + 1) % comm.size(), 2, values,
104                                 num_values));
105       reqs.push_back(comm.irecv((comm.rank() + comm.size() - 1) % comm.size(),
106                                 2, &incoming_values.front(), num_values));
107     }
108
109     switch (method) {
110     case mk_wait_any:
111       if (wait_any(reqs.begin(), reqs.end()).second == reqs.begin())
112         reqs[1].wait();
113       else
114         reqs[0].wait();
115       break;
116
117     case mk_test_any:
118       {
119         boost::optional<status_iterator_pair> result;
120         do {
121           result = test_any(reqs.begin(), reqs.end());
122         } while (!result);
123         if (result->second == reqs.begin())
124           reqs[1].wait();
125         else
126           reqs[0].wait();
127         break;
128       }
129
130     case mk_wait_all:
131       wait_all(reqs.begin(), reqs.end());
132       break;
133
134     case mk_wait_all_keep:
135       {
136         std::vector<status> stats;
137         wait_all(reqs.begin(), reqs.end(), std::back_inserter(stats));
138       }
139       break;
140
141     case mk_test_all:
142       while (!test_all(reqs.begin(), reqs.end())) { /* Busy wait */ }
143       break;
144
145     case mk_test_all_keep:
146       {
147         std::vector<status> stats;
148         while (!test_all(reqs.begin(), reqs.end(), std::back_inserter(stats)))
149           /* Busy wait */;
150       }
151       break;
152
153     case mk_wait_some:
154       {
155         std::vector<request>::iterator pos = reqs.end();
156         do {
157           pos = wait_some(reqs.begin(), pos);
158         } while (pos != reqs.begin());
159       }
160       break;
161
162     case mk_wait_some_keep:
163       {
164         std::vector<status> stats;
165         std::vector<request>::iterator pos = reqs.end();
166         do {
167           pos = wait_some(reqs.begin(), pos, std::back_inserter(stats)).second;
168         } while (pos != reqs.begin());
169       }
170       break;
171
172     case mk_test_some:
173       {
174         std::vector<request>::iterator pos = reqs.end();
175         do {
176           pos = test_some(reqs.begin(), pos);
177         } while (pos != reqs.begin());
178       }
179       break;
180
181     case mk_test_some_keep:
182       {
183         std::vector<status> stats;
184         std::vector<request>::iterator pos = reqs.end();
185         do {
186           pos = test_some(reqs.begin(), pos, std::back_inserter(stats)).second;
187         } while (pos != reqs.begin());
188       }
189       break;
190
191     default:
192       BOOST_CHECK(false);
193     }
194
195     if (comm.rank() == 0) {
196       bool okay = true;
197
198       if (!((incoming_value == values[0])))
199         okay = false;
200
201       if (method != mk_wait_any && method != mk_test_any
202           && !std::equal(incoming_values.begin(), incoming_values.end(),
203                          values))
204         okay = false;
205
206       if (okay)
207         std::cout << "OK." << std::endl;
208       else
209         std::cerr << "ERROR!" << std::endl;
210     }
211
212     BOOST_CHECK(incoming_value == values[0]);
213
214     if (method != mk_wait_any && method != mk_test_any)
215       BOOST_CHECK(std::equal(incoming_values.begin(), incoming_values.end(),
216                              values));
217   }
218 }
219
220 int test_main(int argc, char* argv[])
221 {
222   boost::mpi::environment env(argc, argv);
223
224   communicator comm;
225
226   int int_array[3] = {17, 42, 256};
227   nonblocking_test(comm, int_array, 3, "integers");
228
229   gps_position gps_array[2] = {
230     gps_position(17, 42, .06),
231     gps_position(42, 17, .06)
232   };
233   nonblocking_test(comm, gps_array, 2, "gps positions");
234
235   std::string string_array[2] = { "Hello", "World" };
236   nonblocking_test(comm, string_array, 2, "strings", 
237                    mk_all_except_test_all);
238
239   std::list<std::string> lst_of_strings;
240   for (int i = 0; i < comm.size(); ++i)
241     lst_of_strings.push_back(boost::lexical_cast<std::string>(i));
242
243   nonblocking_test(comm, &lst_of_strings, 1, "list of strings", 
244                    mk_all_except_test_all);
245
246   return 0;
247 }