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