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