the game where you go into mines and start crafting! but for consoles (forked directly from smartcmd's github)
at main 340 lines 11 kB view raw
1// Copyright (C) 2007 Trustees of Indiana University 2 3// Authors: Douglas Gregor 4// Andrew Lumsdaine 5 6// Use, modification and distribution is subject to the Boost Software 7// License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at 8// http://www.boost.org/LICENSE_1_0.txt) 9 10/** @file group.hpp 11 * 12 * This header defines the @c group class, which allows one to 13 * manipulate and query groups of processes. 14 */ 15#ifndef BOOST_MPI_GROUP_HPP 16#define BOOST_MPI_GROUP_HPP 17 18#include <boost/mpi/exception.hpp> 19#include <boost/shared_ptr.hpp> 20#include <boost/optional.hpp> 21#include <vector> 22 23namespace boost { namespace mpi { 24 25/** 26 * @brief A @c group is a representation of a subset of the processes 27 * within a @c communicator. 28 * 29 * The @c group class allows one to create arbitrary subsets of the 30 * processes within a communicator. One can compute the union, 31 * intersection, or difference of two groups, or create new groups by 32 * specifically including or excluding certain processes. Given a 33 * group, one can create a new communicator containing only the 34 * processes in that group. 35 */ 36class BOOST_MPI_DECL group 37{ 38public: 39 /** 40 * @brief Constructs an empty group. 41 */ 42 group() : group_ptr() { } 43 44 /** 45 * @brief Constructs a group from an @c MPI_Group. 46 * 47 * This routine allows one to construct a Boost.MPI @c group from a 48 * C @c MPI_Group. The @c group object can (optionally) adopt the @c 49 * MPI_Group, after which point the @c group object becomes 50 * responsible for freeing the @c MPI_Group when the last copy of @c 51 * group disappears. 52 * 53 * @param in_group The @c MPI_Group used to construct this @c group. 54 * 55 * @param adopt Whether the @c group should adopt the @c 56 * MPI_Group. When true, the @c group object (or one of its copies) 57 * will free the group (via @c MPI_Comm_free) when the last copy is 58 * destroyed. Otherwise, the user is responsible for calling @c 59 * MPI_Group_free. 60 */ 61 group(const MPI_Group& in_group, bool adopt); 62 63 /** 64 * @brief Determine the rank of the calling process in the group. 65 * 66 * This routine is equivalent to @c MPI_Group_rank. 67 * 68 * @returns The rank of the calling process in the group, which will 69 * be a value in [0, size()). If the calling process is not in the 70 * group, returns an empty value. 71 */ 72 optional<int> rank() const; 73 74 /** 75 * @brief Determine the number of processes in the group. 76 * 77 * This routine is equivalent to @c MPI_Group_size. 78 * 79 * @returns The number of processes in the group. 80 */ 81 int size() const; 82 83 /** 84 * @brief Translates the ranks from one group into the ranks of the 85 * same processes in another group. 86 * 87 * This routine translates each of the integer rank values in the 88 * iterator range @c [first, last) from the current group into rank 89 * values of the corresponding processes in @p to_group. The 90 * corresponding rank values are written via the output iterator @c 91 * out. When there is no correspondence between a rank in the 92 * current group and a rank in @c to_group, the value @c 93 * MPI_UNDEFINED is written to the output iterator. 94 * 95 * @param first Beginning of the iterator range of ranks in the 96 * current group. 97 * 98 * @param last Past the end of the iterator range of ranks in the 99 * current group. 100 * 101 * @param to_group The group that we are translating ranks to. 102 * 103 * @param out The output iterator to which the translated ranks will 104 * be written. 105 * 106 * @returns the output iterator, which points one step past the last 107 * rank written. 108 */ 109 template<typename InputIterator, typename OutputIterator> 110 OutputIterator translate_ranks(InputIterator first, InputIterator last, 111 const group& to_group, OutputIterator out); 112 113 /** 114 * @brief Determines whether the group is non-empty. 115 * 116 * @returns True if the group is not empty, false if it is empty. 117 */ 118 operator bool() const { return (bool)group_ptr; } 119 120 /** 121 * @brief Retrieves the underlying @c MPI_Group associated with this 122 * group. 123 * 124 * @returns The @c MPI_Group handle manipulated by this object. If 125 * this object represents the empty group, returns @c 126 * MPI_GROUP_EMPTY. 127 */ 128 operator MPI_Group() const 129 { 130 if (group_ptr) 131 return *group_ptr; 132 else 133 return MPI_GROUP_EMPTY; 134 } 135 136 /** 137 * @brief Creates a new group including a subset of the processes 138 * in the current group. 139 * 140 * This routine creates a new @c group which includes only those 141 * processes in the current group that are listed in the integer 142 * iterator range @c [first, last). Equivalent to @c 143 * MPI_Group_incl. 144 * 145 * @c first The beginning of the iterator range of ranks to include. 146 * 147 * @c last Past the end of the iterator range of ranks to include. 148 * 149 * @returns A new group containing those processes with ranks @c 150 * [first, last) in the current group. 151 */ 152 template<typename InputIterator> 153 group include(InputIterator first, InputIterator last); 154 155 /** 156 * @brief Creates a new group from all of the processes in the 157 * current group, exluding a specific subset of the processes. 158 * 159 * This routine creates a new @c group which includes all of the 160 * processes in the current group except those whose ranks are 161 * listed in the integer iterator range @c [first, 162 * last). Equivalent to @c MPI_Group_excl. 163 * 164 * @c first The beginning of the iterator range of ranks to exclude. 165 * 166 * @c last Past the end of the iterator range of ranks to exclude. 167 * 168 * @returns A new group containing all of the processes in the 169 * current group except those processes with ranks @c [first, last) 170 * in the current group. 171 */ 172 template<typename InputIterator> 173 group exclude(InputIterator first, InputIterator last); 174 175 176protected: 177 /** 178 * INTERNAL ONLY 179 * 180 * Function object that frees an MPI group and deletes the 181 * memory associated with it. Intended to be used as a deleter with 182 * shared_ptr. 183 */ 184 struct group_free 185 { 186 void operator()(MPI_Group* comm) const 187 { 188 int finalized; 189 BOOST_MPI_CHECK_RESULT(MPI_Finalized, (&finalized)); 190 if (!finalized) 191 BOOST_MPI_CHECK_RESULT(MPI_Group_free, (comm)); 192 delete comm; 193 } 194 }; 195 196 /** 197 * The underlying MPI group. This is a shared pointer, so the actual 198 * MPI group which will be shared among all related instances of the 199 * @c group class. When there are no more such instances, the group 200 * will be automatically freed. 201 */ 202 shared_ptr<MPI_Group> group_ptr; 203}; 204 205/** 206 * @brief Determines whether two process groups are identical. 207 * 208 * Equivalent to calling @c MPI_Group_compare and checking whether the 209 * result is @c MPI_IDENT. 210 * 211 * @returns True when the two process groups contain the same 212 * processes in the same order. 213 */ 214BOOST_MPI_DECL bool operator==(const group& g1, const group& g2); 215 216/** 217 * @brief Determines whether two process groups are not identical. 218 * 219 * Equivalent to calling @c MPI_Group_compare and checking whether the 220 * result is not @c MPI_IDENT. 221 * 222 * @returns False when the two process groups contain the same 223 * processes in the same order. 224 */ 225inline bool operator!=(const group& g1, const group& g2) 226{ 227 return !(g1 == g2); 228} 229 230/** 231 * @brief Computes the union of two process groups. 232 * 233 * This routine returns a new @c group that contains all processes 234 * that are either in group @c g1 or in group @c g2 (or both). The 235 * processes that are in @c g1 will be first in the resulting group, 236 * followed by the processes from @c g2 (but not also in @c 237 * g1). Equivalent to @c MPI_Group_union. 238 */ 239BOOST_MPI_DECL group operator|(const group& g1, const group& g2); 240 241/** 242 * @brief Computes the intersection of two process groups. 243 * 244 * This routine returns a new @c group that contains all processes 245 * that are in group @c g1 and in group @c g2, ordered in the same way 246 * as @c g1. Equivalent to @c MPI_Group_intersection. 247 */ 248BOOST_MPI_DECL group operator&(const group& g1, const group& g2); 249 250/** 251 * @brief Computes the difference between two process groups. 252 * 253 * This routine returns a new @c group that contains all processes 254 * that are in group @c g1 but not in group @c g2, ordered in the same way 255 * as @c g1. Equivalent to @c MPI_Group_difference. 256 */ 257BOOST_MPI_DECL group operator-(const group& g1, const group& g2); 258 259/************************************************************************ 260 * Implementation details * 261 ************************************************************************/ 262template<typename InputIterator, typename OutputIterator> 263OutputIterator 264group::translate_ranks(InputIterator first, InputIterator last, 265 const group& to_group, OutputIterator out) 266{ 267 std::vector<int> in_array(first, last); 268 if (in_array.empty()) 269 return out; 270 271 std::vector<int> out_array(in_array.size()); 272 BOOST_MPI_CHECK_RESULT(MPI_Group_translate_ranks, 273 ((MPI_Group)*this, 274 in_array.size(), 275 &in_array[0], 276 (MPI_Group)to_group, 277 &out_array[0])); 278 279 for (std::vector<int>::size_type i = 0, n = out_array.size(); i < n; ++i) 280 *out++ = out_array[i]; 281 return out; 282} 283 284/** 285 * INTERNAL ONLY 286 * 287 * Specialization of translate_ranks that handles the one case where 288 * we can avoid any memory allocation or copying. 289 */ 290template<> 291BOOST_MPI_DECL int* 292group::translate_ranks(int* first, int* last, const group& to_group, int* out); 293 294template<typename InputIterator> 295group group::include(InputIterator first, InputIterator last) 296{ 297 if (first == last) 298 return group(); 299 300 std::vector<int> ranks(first, last); 301 MPI_Group result; 302 BOOST_MPI_CHECK_RESULT(MPI_Group_incl, 303 ((MPI_Group)*this, ranks.size(), &ranks[0], &result)); 304 return group(result, /*adopt=*/true); 305} 306 307/** 308 * INTERNAL ONLY 309 * 310 * Specialization of group::include that handles the one case where we 311 * can avoid any memory allocation or copying before creating the 312 * group. 313 */ 314template<> BOOST_MPI_DECL group group::include(int* first, int* last); 315 316template<typename InputIterator> 317group group::exclude(InputIterator first, InputIterator last) 318{ 319 if (first == last) 320 return group(); 321 322 std::vector<int> ranks(first, last); 323 MPI_Group result; 324 BOOST_MPI_CHECK_RESULT(MPI_Group_excl, 325 ((MPI_Group)*this, ranks.size(), &ranks[0], &result)); 326 return group(result, /*adopt=*/true); 327} 328 329/** 330 * INTERNAL ONLY 331 * 332 * Specialization of group::exclude that handles the one case where we 333 * can avoid any memory allocation or copying before creating the 334 * group. 335 */ 336template<> BOOST_MPI_DECL group group::exclude(int* first, int* last); 337 338} } // end namespace boost::mpi 339 340#endif // BOOST_MPI_GROUP_HPP