warpcore 0.0.1
Hashing at the Speed of Light on modern CUDA-accelerators
status.cuh
Go to the documentation of this file.
1 #ifndef WARPCORE_STATUS_CUH
2 #define WARPCORE_STATUS_CUH
3 
4 namespace warpcore
5 {
6 
7 // forward declaration of handlers which need to be friends with Status
8 namespace status_handlers
9 {
10  template<status_base_t Ignore>
11  class ReturnBoolean;
12 }
13 
14 /*! \brief status/error indicator
15  */
16 class Status
17 {
18 
19 public:
21 
22  static_assert(
25  "unsupported base type");
26 
27  Status() noexcept = default;
28  constexpr Status(const Status&) noexcept = default;
29  constexpr Status(Status&& s) noexcept = default;
30 
31  // TODO needed?
33  constexpr operator base_type() noexcept { return status_; }
34 
36  constexpr base_type base() const noexcept { return status_; }
37 
39  static constexpr Status none() noexcept { return Status(base_type(0)); }
41  static constexpr Status all() noexcept { return Status(mask); }
42 
44  static constexpr Status unknown_error() noexcept { return Status(one << 0); }
46  static constexpr Status probing_length_exceeded() noexcept { return Status(one << 1); }
48  static constexpr Status invalid_configuration() noexcept { return Status(one << 2); }
50  static constexpr Status invalid_key() noexcept { return Status(one << 3); }
52  static constexpr Status duplicate_key() noexcept { return Status(one << 4); }
54  static constexpr Status key_not_found() noexcept { return Status(one << 5); }
56  static constexpr Status index_overflow() noexcept { return Status(one << 6); }
58  static constexpr Status out_of_memory() noexcept { return Status(one << 7); }
60  static constexpr Status not_initialized() noexcept { return Status(one << 8); }
62  static constexpr Status dry_run() noexcept { return Status(one << 9); }
64  static constexpr Status invalid_phase_overlap() noexcept { return Status(one << 10); }
66  static constexpr Status max_values_for_key_reached() noexcept { return Status(one << 11); }
68  static constexpr Status invalid_value() noexcept { return Status(one << 12); }
69 
71  static constexpr Status error_mask() noexcept
72  {
73  return
74  unknown_error() +
76  index_overflow() +
77  out_of_memory() +
78  not_initialized() +
80  }
81 
83  static constexpr Status warning_mask() noexcept
84  {
85  return all() - error_mask();
86  }
87 
89  constexpr Status get_errors() const noexcept { return Status(status_ & error_mask().status_); }
91  constexpr Status get_warnings() const noexcept { return Status(status_ & warning_mask().status_); }
92 
94  constexpr bool has_any(const Status& s = all()) const noexcept { return status_ & s.status_; }
96  constexpr bool has_any_errors() const noexcept { return has_any(error_mask()); }
98  constexpr bool has_any_warnings() const noexcept { return has_any(warning_mask()); }
100  constexpr bool has_all(const Status& s = all()) const noexcept { return (status_ & s.status_) == s.status_; }
101 
103  constexpr bool has_unknown_error() const noexcept { return status_ & unknown_error().status_; }
105  constexpr bool has_probing_length_exceeded() const noexcept { return status_ & probing_length_exceeded().status_; }
107  constexpr bool has_invalid_configuration() const noexcept { return status_ & invalid_configuration().status_; }
109  constexpr bool has_invalid_key() const noexcept { return status_ & invalid_key().status_; }
111  constexpr bool has_duplicate_key() const noexcept { return status_ & duplicate_key().status_; }
113  constexpr bool has_key_not_found() const noexcept { return status_ & key_not_found().status_; }
115  constexpr bool has_index_overflow() const noexcept { return status_ & index_overflow().status_; }
117  constexpr bool has_out_of_memory() const noexcept { return status_ & out_of_memory().status_; }
119  constexpr bool has_not_initialized() const noexcept { return status_ & not_initialized().status_; }
121  constexpr bool has_dry_run() const noexcept { return status_ & dry_run().status_; }
123  constexpr bool has_invalid_phase_overlap() const noexcept { return status_ & invalid_phase_overlap().status_; }
125  constexpr bool has_max_values_for_key_reached() const noexcept { return status_ & max_values_for_key_reached().status_; }
127  constexpr bool has_invalid_value() const noexcept { return status_ & invalid_value().status_; }
128 
130  constexpr Status& operator=(const Status& a) noexcept
131  {
132  status_ = a.status_;
133  return *this;
134  }
135 
137  constexpr Status operator~() const noexcept
138  {
139  return Status((~status_) ^ mask);
140  }
141 
143  constexpr Status& operator+=(const Status& a) noexcept
144  {
145  status_ |= a.status_;
146  return *this;
147  }
148 
150  constexpr Status operator+(const Status& a) noexcept
151  {
152  return Status(status_ | a.status_);
153  }
154 
156  constexpr Status operator-(const Status& a) noexcept
157  {
158  return Status(status_ - (status_ & a.status_));
159  }
160 
162  constexpr Status& operator-=(const Status& a) noexcept
163  {
164  status_ -= status_ & a.status_;
165  return *this;
166  }
167 
169  constexpr bool operator==(const Status& a) const noexcept
170  {
171  return status_ == a.status_;
172  }
173 
175  constexpr bool operator!=(const Status& a) const noexcept
176  {
177  return status_ != a.status_;
178  }
179 
181  void atomic_assign(Status s) noexcept
182  {
184  }
185 
187  void atomic_join(Status s) noexcept
188  {
189  if(!has_all(s))
190  {
192  }
193  }
194 
195  template<class Group>
198  {
199  return Status(group.shfl(status_, src));
200  }
201 
202 private:
204  explicit constexpr Status(base_type s) noexcept : status_{s} {}
205 
206  static constexpr base_type one = 1;
207  static constexpr base_type mask = 0xFFF; // INFO change when adding new status
208 
209  base_type status_;
210 
211  // some handlers need to access a private constructor
212  template<base_type> friend class status_handlers::ReturnBoolean;
213 
214 }; // class Status
215 
216 template<class OStream>
217 OStream& operator<<(OStream& os, Status status)
218 {
219  std::vector<std::string> msg;
220 
221  if(status.has_duplicate_key())
222  msg.push_back("duplicate key");
223  if(status.has_unknown_error())
224  msg.push_back("unknown error");
225  if(status.has_probing_length_exceeded())
226  msg.push_back("probing length exceeded");
227  if(status.has_invalid_configuration())
228  msg.push_back("invalid configuration");
229  if(status.has_invalid_key())
230  msg.push_back("invalid key");
231  if(status.has_key_not_found())
232  msg.push_back("key not found");
233  if(status.has_index_overflow())
234  msg.push_back("index overflow");
235  if(status.has_out_of_memory())
236  msg.push_back("out of memory");
237  if(status.has_not_initialized())
238  msg.push_back("not initialized");
239  if(status.has_dry_run())
240  msg.push_back("dry run");
241  if(status.has_invalid_phase_overlap())
242  msg.push_back("invalid phase overlap");
243  if(status.has_max_values_for_key_reached())
244  msg.push_back("max values for key reached");
245  if(status.has_invalid_value())
246  msg.push_back("invalid value");
247  // if(!status.has_any())
248  // msg.push_back("none");
249 
250  switch(msg.size())
251  {
252  case 0: os << "[]"; break;
253  case 1: os << "[" << msg[0] << "]"; break;
254  default:
255  os << "[";
256 
257  std::uint64_t i = 0;
258  while(i < msg.size() - 1)
259  {
260  os << msg[i] << ", ";
261  i++;
262  }
263 
264  os << msg[i] << "]";
265  break;
266  }
267 
268  return os;
269 }
270 
271 /*! \brief status handlers to use for per key status information
272  */
273 namespace status_handlers
274 {
275 
276 /*! \brief do not use per key status handling
277  */
279 {
280 public:
281  using base_type = void;
283 
284  DEVICEQUALIFIER INLINEQUALIFIER
285  static void handle(
286  Status /* status */,
287  base_type * /* out */,
288  index_t /* index */) noexcept
289  {
290  // no op
291  }
292 }; // class ReturnNothing
293 
294 /*! \brief get status per key
295  */
297 {
298 public:
299  using base_type = Status;
301 
302  DEVICEQUALIFIER INLINEQUALIFIER
303  static void handle(
304  Status status,
305  base_type * out,
306  index_t index) noexcept
307  {
308  if(out != nullptr){
309  out[index] = status;
310  }
311  }
312 }; // class ReturnStatus
313 
314 /*! \brief get boolean error indicator per key
315  */
316 template<Status::base_type Ignore = Status::none()>
318 {
319 public:
320  using base_type = bool;
322 
323  DEVICEQUALIFIER INLINEQUALIFIER
324  static void handle(
325  Status status,
326  base_type * out,
327  index_t index) noexcept
328  {
329  if(out != nullptr){
331  }
332  }
333 }; // class ReturnBoolean
334 
335 } // namespace status_handlers
336 
337 } // namespace warpcore
338 
339 #endif /* WARPCORE_STATUS_CUH */