xref: /netbsd-src/external/bsd/zstd/dist/contrib/pzstd/ErrorHolder.h (revision 3117ece4fc4a4ca4489ba793710b60b0d26bab6c)
1*3117ece4Schristos /*
2*3117ece4Schristos  * Copyright (c) Meta Platforms, Inc. and affiliates.
3*3117ece4Schristos  * All rights reserved.
4*3117ece4Schristos  *
5*3117ece4Schristos  * This source code is licensed under both the BSD-style license (found in the
6*3117ece4Schristos  * LICENSE file in the root directory of this source tree) and the GPLv2 (found
7*3117ece4Schristos  * in the COPYING file in the root directory of this source tree).
8*3117ece4Schristos  */
9*3117ece4Schristos #pragma once
10*3117ece4Schristos 
11*3117ece4Schristos #include <atomic>
12*3117ece4Schristos #include <cassert>
13*3117ece4Schristos #include <stdexcept>
14*3117ece4Schristos #include <string>
15*3117ece4Schristos 
16*3117ece4Schristos namespace pzstd {
17*3117ece4Schristos 
18*3117ece4Schristos // Coordinates graceful shutdown of the pzstd pipeline
19*3117ece4Schristos class ErrorHolder {
20*3117ece4Schristos   std::atomic<bool> error_;
21*3117ece4Schristos   std::string message_;
22*3117ece4Schristos 
23*3117ece4Schristos  public:
24*3117ece4Schristos   ErrorHolder() : error_(false) {}
25*3117ece4Schristos 
26*3117ece4Schristos   bool hasError() noexcept {
27*3117ece4Schristos     return error_.load();
28*3117ece4Schristos   }
29*3117ece4Schristos 
30*3117ece4Schristos   void setError(std::string message) noexcept {
31*3117ece4Schristos     // Given multiple possibly concurrent calls, exactly one will ever succeed.
32*3117ece4Schristos     bool expected = false;
33*3117ece4Schristos     if (error_.compare_exchange_strong(expected, true)) {
34*3117ece4Schristos       message_ = std::move(message);
35*3117ece4Schristos     }
36*3117ece4Schristos   }
37*3117ece4Schristos 
38*3117ece4Schristos   bool check(bool predicate, std::string message) noexcept {
39*3117ece4Schristos     if (!predicate) {
40*3117ece4Schristos       setError(std::move(message));
41*3117ece4Schristos     }
42*3117ece4Schristos     return !hasError();
43*3117ece4Schristos   }
44*3117ece4Schristos 
45*3117ece4Schristos   std::string getError() noexcept {
46*3117ece4Schristos     error_.store(false);
47*3117ece4Schristos     return std::move(message_);
48*3117ece4Schristos   }
49*3117ece4Schristos 
50*3117ece4Schristos   ~ErrorHolder() {
51*3117ece4Schristos     assert(!hasError());
52*3117ece4Schristos   }
53*3117ece4Schristos };
54*3117ece4Schristos }
55