Imported Upstream version 1.72.0
[platform/upstream/boost.git] / libs / mpi / src / environment.cpp
1 // Copyright (C) 2005-2006 Douglas Gregor <doug.gregor@gmail.com>
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 // Message Passing Interface 1.1 -- 7.1.1. Environmental Inquiries
8 #include <boost/mpi/environment.hpp>
9 #include <boost/mpi/exception.hpp>
10 #include <boost/mpi/detail/mpi_datatype_cache.hpp>
11 #include <boost/core/uncaught_exceptions.hpp>
12 #include <cassert>
13 #include <string>
14 #include <exception>
15 #include <stdexcept>
16 #include <ostream>
17
18 namespace boost { namespace mpi {
19 namespace threading {
20 std::istream& operator>>(std::istream& in, level& l)
21 {
22   std::string tk;
23   in >> tk;
24   if (!in.bad()) {
25     if (tk == "single") {
26       l = single;
27     } else if (tk == "funneled") {
28       l = funneled;
29     } else if (tk == "serialized") {
30       l = serialized;
31     } else if (tk == "multiple") {
32       l = multiple;
33     } else {
34       in.setstate(std::ios::badbit);
35     }
36   }
37   return in;
38 }
39
40 std::ostream& operator<<(std::ostream& out, level l)
41 {
42   switch(l) {
43   case single:
44     out << "single";
45     break;
46   case funneled:
47     out << "funneled";
48     break;
49   case serialized:
50     out << "serialized";
51     break;
52   case multiple:
53     out << "multiple";
54     break;
55   default:
56     out << "<level error>[" << int(l) << ']';
57     out.setstate(std::ios::badbit);
58     break;
59   }
60   return out;
61 }
62
63 } // namespace threading
64
65 #ifdef BOOST_MPI_HAS_NOARG_INITIALIZATION
66 environment::environment(bool abrt)
67   : i_initialized(false),
68     abort_on_exception(abrt)
69 {
70   if (!initialized()) {
71     BOOST_MPI_CHECK_RESULT(MPI_Init, (0, 0));
72     i_initialized = true;
73   }
74
75 #if (2 <= MPI_VERSION)
76   MPI_Comm_set_errhandler(MPI_COMM_WORLD, MPI_ERRORS_RETURN);
77 #else
78   MPI_Errhandler_set(MPI_COMM_WORLD, MPI_ERRORS_RETURN);
79 #endif
80 }
81
82 environment::environment(threading::level mt_level, bool abrt)
83   : i_initialized(false),
84     abort_on_exception(abrt)
85 {
86   // It is not clear that we can pass null in MPI_Init_thread.
87   int dummy_thread_level = 0;
88   if (!initialized()) {
89     BOOST_MPI_CHECK_RESULT(MPI_Init_thread, 
90                            (0, 0, int(mt_level), &dummy_thread_level ));
91     i_initialized = true;
92   }
93
94 #if (2 <= MPI_VERSION)
95   MPI_Comm_set_errhandler(MPI_COMM_WORLD, MPI_ERRORS_RETURN);
96 #else
97   MPI_Errhandler_set(MPI_COMM_WORLD, MPI_ERRORS_RETURN);
98 #endif
99 }
100 #endif
101
102 environment::environment(int& argc, char** &argv, bool abrt)
103   : i_initialized(false),
104     abort_on_exception(abrt)
105 {
106   if (!initialized()) {
107     BOOST_MPI_CHECK_RESULT(MPI_Init, (&argc, &argv));
108     i_initialized = true;
109   }
110
111 #if (2 <= MPI_VERSION)
112   MPI_Comm_set_errhandler(MPI_COMM_WORLD, MPI_ERRORS_RETURN);
113 #else
114   MPI_Errhandler_set(MPI_COMM_WORLD, MPI_ERRORS_RETURN);
115 #endif
116 }
117
118 environment::environment(int& argc, char** &argv, threading::level mt_level,
119                          bool abrt)
120   : i_initialized(false),
121     abort_on_exception(abrt)
122 {
123   // It is not clear that we can pass null in MPI_Init_thread.
124   int dummy_thread_level = 0;
125   if (!initialized()) {
126     BOOST_MPI_CHECK_RESULT(MPI_Init_thread, 
127                            (&argc, &argv, int(mt_level), &dummy_thread_level));
128     i_initialized = true;
129   }
130
131 #if (2 <= MPI_VERSION)
132   MPI_Comm_set_errhandler(MPI_COMM_WORLD, MPI_ERRORS_RETURN);
133 #else
134   MPI_Errhandler_set(MPI_COMM_WORLD, MPI_ERRORS_RETURN);
135 #endif
136 }
137
138 environment::~environment()
139 {
140   if (i_initialized) {
141     if (boost::core::uncaught_exceptions() > 0 && abort_on_exception) {
142       abort(-1);
143     } else if (!finalized()) {
144       detail::mpi_datatype_cache().clear();
145       BOOST_MPI_CHECK_RESULT(MPI_Finalize, ());
146     }
147   }
148 }
149
150 void environment::abort(int errcode)
151 {
152   BOOST_MPI_CHECK_RESULT(MPI_Abort, (MPI_COMM_WORLD, errcode));
153 }
154
155 bool environment::initialized()
156 {
157   int flag;
158   BOOST_MPI_CHECK_RESULT(MPI_Initialized, (&flag));
159   return flag != 0;
160 }
161
162 bool environment::finalized()
163 {
164   int flag;
165   BOOST_MPI_CHECK_RESULT(MPI_Finalized, (&flag));
166   return flag != 0;
167 }
168
169 int environment::max_tag()
170 {
171   int* max_tag_value;
172   int found = 0;
173
174 #if (2 <= MPI_VERSION)
175   BOOST_MPI_CHECK_RESULT(MPI_Comm_get_attr,
176                          (MPI_COMM_WORLD, MPI_TAG_UB, &max_tag_value, &found));
177 #else
178   BOOST_MPI_CHECK_RESULT(MPI_Attr_get,
179                          (MPI_COMM_WORLD, MPI_TAG_UB, &max_tag_value, &found));
180 #endif
181   assert(found != 0);
182   return *max_tag_value - num_reserved_tags;
183 }
184
185 int environment::collectives_tag()
186 {
187   return max_tag() + 1;
188 }
189
190 optional<int> environment::host_rank()
191 {
192   int* host;
193   int found = 0;
194
195 #if (2 <= MPI_VERSION)
196   BOOST_MPI_CHECK_RESULT(MPI_Comm_get_attr,
197                          (MPI_COMM_WORLD, MPI_HOST, &host, &found));
198 #else
199   BOOST_MPI_CHECK_RESULT(MPI_Attr_get,
200                          (MPI_COMM_WORLD, MPI_HOST, &host, &found));
201 #endif
202   if (!found || *host == MPI_PROC_NULL)
203     return optional<int>();
204   else
205     return *host;
206 }
207
208 optional<int> environment::io_rank()
209 {
210   int* io;
211   int found = 0;
212
213 #if (2 <= MPI_VERSION)
214   BOOST_MPI_CHECK_RESULT(MPI_Comm_get_attr,
215                          (MPI_COMM_WORLD, MPI_IO, &io, &found));
216 #else
217   BOOST_MPI_CHECK_RESULT(MPI_Attr_get,
218                          (MPI_COMM_WORLD, MPI_IO, &io, &found));
219 #endif
220   if (!found || *io == MPI_PROC_NULL)
221     return optional<int>();
222   else
223     return *io;
224 }
225
226 std::string environment::processor_name()
227 {
228   char name[MPI_MAX_PROCESSOR_NAME];
229   int len;
230
231   BOOST_MPI_CHECK_RESULT(MPI_Get_processor_name, (name, &len));
232   return std::string(name, len);
233 }
234
235 threading::level environment::thread_level()
236 {
237   int level;
238
239   BOOST_MPI_CHECK_RESULT(MPI_Query_thread, (&level));
240   return static_cast<threading::level>(level);
241 }
242
243 bool environment::is_main_thread()
244 {
245   int isit;
246
247   BOOST_MPI_CHECK_RESULT(MPI_Is_thread_main, (&isit));
248   return static_cast<bool>(isit);
249 }
250
251 std::pair<int, int> environment::version()
252 {
253   int major, minor;
254   BOOST_MPI_CHECK_RESULT(MPI_Get_version, (&major, &minor));
255   return std::make_pair(major, minor);
256 }
257
258 } } // end namespace boost::mpi