1 /*
2  *  per_thread_bool_indicator.h
3  *
4  *  This file is part of NEST.
5  *
6  *  Copyright (C) 2004 The NEST Initiative
7  *
8  *  NEST is free software: you can redistribute it and/or modify
9  *  it under the terms of the GNU General Public License as published by
10  *  the Free Software Foundation, either version 2 of the License, or
11  *  (at your option) any later version.
12  *
13  *  NEST is distributed in the hope that it will be useful,
14  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
15  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16  *  GNU General Public License for more details.
17  *
18  *  You should have received a copy of the GNU General Public License
19  *  along with NEST.  If not, see <http://www.gnu.org/licenses/>.
20  *
21  */
22 
23 #ifndef PER_THREAD_BOOL_INDICATOR_H
24 #define PER_THREAD_BOOL_INDICATOR_H
25 
26 // C++ includes:
27 #include <cassert>
28 #include <cstddef>
29 #include <cstdint>
30 
31 // Includes from nestkernel:
32 #include "nest_types.h"
33 #include "vp_manager.h"
34 
35 // Includes from sli:
36 #include "dictdatum.h"
37 
38 namespace nest
39 {
40 
41 /**
42  * A wrapper class for an integer that is only allowed to take the
43  * values 0 and 1. Used by PerThreadBoolIndicator to create a
44  * thread-safe vector indicating per-thread status. See issue #1394.
45  */
46 class BoolIndicatorUInt64
47 {
48 public:
49   BoolIndicatorUInt64();
50   BoolIndicatorUInt64( const bool status );
51 
52   bool is_true() const;
53   bool is_false() const;
54 
55   void set_true();
56   void set_false();
57 
58   void logical_and( const bool status );
59 
60 private:
61   static constexpr std::uint_fast64_t true_uint64 = true;
62   static constexpr std::uint_fast64_t false_uint64 = false;
63   std::uint_fast64_t status_;
64 };
65 
66 inline bool
is_true()67 BoolIndicatorUInt64::is_true() const
68 {
69   return ( status_ == true_uint64 );
70 }
71 
72 inline bool
is_false()73 BoolIndicatorUInt64::is_false() const
74 {
75   return ( status_ == false_uint64 );
76 }
77 
78 inline void
set_true()79 BoolIndicatorUInt64::set_true()
80 {
81   status_ = true_uint64;
82 }
83 
84 inline void
set_false()85 BoolIndicatorUInt64::set_false()
86 {
87   status_ = false_uint64;
88 }
89 
90 inline void
logical_and(const bool status)91 BoolIndicatorUInt64::logical_and( const bool status )
92 {
93   status_ = ( static_cast< bool >( status_ ) and status );
94 }
95 
96 /**
97  * A thread-safe vector to keep track of the status across threads,
98  * for example during gather operations. Uses a vector of integers
99  * instead of a vector of bools to guarantee thread safety.
100  * See issue #1394.
101  */
102 class PerThreadBoolIndicator
103 {
104 public:
PerThreadBoolIndicator()105   PerThreadBoolIndicator(){};
106 
107   BoolIndicatorUInt64& operator[]( const thread tid );
108 
109   /**
110    * Resize to the given number of threads and set all elements to false.
111    */
112   void initialize( const thread num_threads, const bool status );
113 
114   /**
115    * Waits for all threads and returns whether all elements are false.
116    */
117   bool all_false() const;
118 
119   /**
120    * Waits for all threads and returns whether all elements are true.
121    */
122   bool all_true() const;
123 
124   /**
125    * Waits for all threads and returns whether any elements are false.
126    */
127   bool any_false() const;
128 
129   /**
130    * Waits for all threads and returns whether any elements are true.
131    */
132   bool any_true() const;
133 
134 private:
135   std::vector< BoolIndicatorUInt64 > per_thread_status_;
136 };
137 
138 } // namespace nest
139 
140 #endif /* PER_THREAD_BOOL_INDICATOR_H */
141