1 // Copyright(C) 1999-2020 National Technology & Engineering Solutions 2 // of Sandia, LLC (NTESS). Under the terms of Contract DE-NA0003525 with 3 // NTESS, the U.S. Government retains certain rights in this software. 4 // 5 // See packages/seacas/LICENSE for details 6 #ifndef IOSS_Ioss_SerializeIO_h 7 #define IOSS_Ioss_SerializeIO_h 8 9 #include "vtk_ioss_mangle.h" 10 11 #include <Ioss_CodeTypes.h> 12 13 namespace Ioss { 14 class DatabaseIO; 15 } // namespace Ioss 16 17 namespace Ioss { 18 19 /** 20 * @brief Class <code>SerializeIO</code> is a sentry class which performs serialization 21 * for mesh database I/O. 22 * 23 * This sentry guards serialization of parallel I/O routines. At construction, it 24 * blocks the processes via an MPI barrier, releasing them to execute in groups specified 25 * by <code>s_groupSize</code>. At destruction, it continues to block via MPI barriers 26 * until all the processor have been released by the constructor. 27 * 28 * In the case where the constructor is called, and the sentry is already active and owned 29 * by the processes group, the constructor and destructor simply fall through since the 30 * serialization is already in place at a higher level. 31 * 32 * \note All ranks must call the SerializeIO constructor synchronously. 33 * \note It is recommended to use RAII and keep the area protected by the SerializeIO as small as 34 * possible. 35 * 36 * The flow is that the ranks are split into groups of the specified size. Assume 3 ranks of group 37 * size 1. 38 * 39 * * First time through, 40 * - rank 0 falls through and 41 * - ranks 1, 2 sit at the barrier 42 * - rank 0 hits the destructor and then all 3 ranks are in the barrier so they all go to next 43 * step 44 * - (rank 1,2 in constructor, rank 0 in destructor) 45 * * `s_owner` is now equal to `m_groupRank` on rank 1, so it falls out of the do while; 46 * - rank 2 still in the constructor do while Barrier 47 * - rank 0 in the destructor do while Barrier 48 * - rank 1 does its work and calls destructor; 49 * - all ranks in Barrier, so they go to next step. 50 * * `s_owner` now equal to `m_groupRank` on rank 2, so if falls out of the do while; 51 * - ranks 0,1 in destructor do while at the Barrier 52 * - rank 2 does it work and calls destructor 53 * - all ranks are now in the destructor Barrier, so they go to next step 54 * - all ranks clear the Destructor and go to next step. 55 * 56 */ 57 class SerializeIO 58 { 59 public: 60 /** 61 * Creates a new <code>SerializeIO</code> instance. 62 * 63 * @param database_io a <code>DatabaseIO</code> variable ... 64 */ 65 explicit SerializeIO(const DatabaseIO *database_io); 66 SerializeIO(const SerializeIO &from) = delete; 67 SerializeIO &operator=(const SerializeIO &from) = delete; 68 ~SerializeIO(); 69 getOwner()70 inline static int getOwner() { return s_owner; } 71 getRank()72 inline static int getRank() { return s_rank; } 73 getSize()74 inline static int getSize() { return s_size; } 75 getGroupRank()76 inline static int getGroupRank() { return s_groupRank; } 77 getGroupSize()78 inline static int getGroupSize() { return s_groupSize; } 79 80 static void setGroupFactor(int factor); 81 isEnabled()82 inline static bool isEnabled() { return s_groupFactor != 0; } 83 inBarrier()84 inline static bool inBarrier() { return s_owner != -1; } 85 inMyGroup()86 inline static bool inMyGroup() { return s_owner == s_groupRank; } 87 88 private: 89 const DatabaseIO *m_databaseIO; ///< Database I/O pointer 90 #if defined(IOSS_THREADSAFE) 91 static std::mutex m_; 92 #endif 93 bool m_activeFallThru; ///< No barriers since my group is running 94 95 static int s_groupFactor; ///< Grouping factor 96 static int s_size; ///< Number of processors 97 static int s_rank; ///< My processor rank 98 static int s_groupSize; ///< Number of groups 99 static int s_groupRank; ///< My group rank 100 static int s_owner; ///< Group currently running 101 }; 102 103 } // namespace Ioss 104 105 #endif // IOSS_Ioss_SerializeIO_h 106