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