cuSBF
Loading...
Searching...
No Matches
error.hpp
Go to the documentation of this file.
1#pragma once
2
3#include <cuda_runtime.h>
4#include <cuda/std/expected>
5
6#include <cstdint>
7#include <cstdio>
8#include <format>
9#include <source_location>
10#include <stdexcept>
11#include <string>
12#include <string_view>
13#include <type_traits>
14#include <utility>
15#include <variant>
16
17namespace cusbf {
18
21 std::string file;
22 uint32_t line{};
23 uint32_t column{};
24
25 [[nodiscard]] static SourceLocation from(std::source_location location) {
26 return SourceLocation{
27 location.file_name(),
28 static_cast<uint32_t>(location.line()),
29 static_cast<uint32_t>(location.column()),
30 };
31 }
32
33 [[nodiscard]] static SourceLocation
34 fastx(std::string_view file, uint32_t line, uint32_t column) {
35 return SourceLocation{std::string(file), line, column};
36 }
37
38 [[nodiscard]] std::string to_string() const {
39 return std::format("{}:{}:{}", file, line, column);
40 }
41};
42
43struct CudaError {
44 cudaError_t code{};
46 std::string message;
47};
48
49struct IoError {
50 std::string message;
51};
52
57
59 std::string message;
60};
61
63 std::string message;
64};
65
67enum class ErrorCategory : uint8_t {
68 cuda,
69 io,
73};
74
76struct Error {
77 std::variant<CudaError, IoError, FastxParseError, InvalidArgumentError, ResourceError> kind;
78
79 [[nodiscard]] ErrorCategory category() const noexcept {
80 return static_cast<ErrorCategory>(kind.index());
81 }
82
83 [[nodiscard]] const std::string& message() const noexcept {
84 return std::visit(
85 [](const auto& error) -> const std::string& { return error.message; }, kind
86 );
87 }
88
89 [[nodiscard]] const CudaError* as_cuda() const noexcept {
90 return std::get_if<CudaError>(&kind);
91 }
92
93 [[nodiscard]] const IoError* as_io() const noexcept {
94 return std::get_if<IoError>(&kind);
95 }
96
97 [[nodiscard]] const FastxParseError* as_fastx_parse() const noexcept {
98 return std::get_if<FastxParseError>(&kind);
99 }
100
101 [[nodiscard]] const InvalidArgumentError* as_invalid_argument() const noexcept {
102 return std::get_if<InvalidArgumentError>(&kind);
103 }
104
105 [[nodiscard]] const ResourceError* as_resource() const noexcept {
106 return std::get_if<ResourceError>(&kind);
107 }
108
109 [[nodiscard]] static Error
110 cuda(cudaError_t code, std::source_location location = std::source_location::current()) {
111 const SourceLocation site = SourceLocation::from(location);
112 return Error{CudaError{
113 code,
114 site,
115 std::format("{}: {}", site.to_string(), cudaGetErrorString(code)),
116 }};
117 }
118
119 [[nodiscard]] static Error io(std::string message) {
120 return Error{IoError{std::move(message)}};
121 }
122
123 [[nodiscard]] static Error fastx_parse(SourceLocation site, std::string_view detail) {
124 const std::string location_text = site.to_string();
125 return Error{FastxParseError{
126 std::move(site),
127 std::format("{}: {}", location_text, detail),
128 }};
129 }
130
131 [[nodiscard]] static Error invalid_argument(std::string message) {
132 return Error{InvalidArgumentError{std::move(message)}};
133 }
134
135 [[nodiscard]] static Error resource(std::string message) {
136 return Error{ResourceError{std::move(message)}};
137 }
138};
139static_assert(static_cast<size_t>(ErrorCategory::cuda) == 0);
140static_assert(static_cast<size_t>(ErrorCategory::io) == 1);
141static_assert(static_cast<size_t>(ErrorCategory::fastx_parse) == 2);
142static_assert(static_cast<size_t>(ErrorCategory::invalid_argument) == 3);
143static_assert(static_cast<size_t>(ErrorCategory::resource) == 4);
144
151template <typename T>
152struct [[nodiscard]] Result : cuda::std::expected<T, Error> {
153 using cuda::std::expected<T, Error>::expected;
154
155 [[nodiscard]] static Result ok(T value) {
156 return Result(std::move(value));
157 }
158
159 [[nodiscard]] static Result err(Error error) {
160 return Result(cuda::std::unexpect, std::move(error));
161 }
162};
163
164template <>
165struct [[nodiscard]] Result<void> : cuda::std::expected<void, Error> {
166 using cuda::std::expected<void, Error>::expected;
167
168 [[nodiscard]] static Result ok() {
169 return {};
170 }
171
172 [[nodiscard]] static Result err(Error error) {
173 return Result(cuda::std::unexpect, std::move(error));
174 }
175};
176
178inline void require_void(const Result<void>& result) {
179 if (!result) {
180 std::fputs(result.error().message().c_str(), stderr);
181 std::fputc('\n', stderr);
182 std::abort();
183 }
184}
185
188 cudaError_t error,
189 std::source_location location = std::source_location::current()
190) {
191 if (error == cudaSuccess) {
192 return;
193 }
194 const Error err = Error::cuda(error, location);
195 std::fputs(err.message().c_str(), stderr);
196 std::fputc('\n', stderr);
197 std::abort();
198}
199
200namespace detail {
201
202template <typename T>
204 return std::move(*result);
205}
206
210
212[[nodiscard]] inline cuda::std::unexpected<Error> propagate_error(const Error& error) {
213 return cuda::std::unexpected<Error>(Error{error});
214}
215
216} // namespace detail
217
219[[nodiscard]] inline cuda::std::unexpected<Error> Err(Error error) {
220 return cuda::std::unexpected<Error>(std::move(error));
221}
222
224[[nodiscard]] inline Result<void> Ok() noexcept {
225 return Result<void>::ok();
226}
227
229[[nodiscard]] inline Result<void>
230cuda_try(cudaError_t error, std::source_location location = std::source_location::current()) {
231 if (error == cudaSuccess) {
232 return Ok();
233 }
234 return Err(Error::cuda(error, location));
235}
236
237} // namespace cusbf
238
246#define CUSBF_TRY(expr) \
247 ({ \
248 auto _cusbf_result = (expr); \
249 if (!_cusbf_result) { \
250 return ::cusbf::detail::propagate_error(_cusbf_result.error()); \
251 } \
252 ::cusbf::detail::try_unwrap_success(_cusbf_result); \
253 })
254
256#define CUSBF_UNWRAP(expr) \
257 ({ \
258 auto _cusbf_result = (expr); \
259 if (!_cusbf_result) { \
260 throw std::runtime_error(_cusbf_result.error().message()); \
261 } \
262 ::cusbf::detail::try_unwrap_success(_cusbf_result); \
263 })
264
266#define CUSBF_CUDA_ABORT(expr) ::cusbf::cuda_abort_on_error((expr))
267
269#define CUSBF_CUDA_TRY(expr) CUSBF_TRY(::cusbf::cuda_try((expr)))
T try_unwrap_success(Result< T > &result)
Definition error.hpp:203
cuda::std::unexpected< Error > propagate_error(const Error &error)
Copies error for propagation (avoids moving out of expected::error()).
Definition error.hpp:212
consteval bool separatorPositionAlwaysEncodesInvalid(char *input, uint64_t separatorPosition, uint64_t index)
Recursively tests whether placing the separator byte at any position in an input of valid bytes alway...
Definition Alphabet.cuh:37
Result< void > cuda_try(cudaError_t error, std::source_location location=std::source_location::current())
Checks a CUDA runtime call and returns an error on failure.
Definition error.hpp:230
void cuda_abort_on_error(cudaError_t error, std::source_location location=std::source_location::current())
Terminates the process when error is not cudaSuccess (for RAII teardown only).
Definition error.hpp:187
void require_void(const Result< void > &result)
Aborts when a Result is unsuccessful (benchmarks and tests).
Definition error.hpp:178
cuda::std::unexpected< Error > Err(Error error)
Failure return; converts to any Result<T> via cuda::std::unexpected.
Definition error.hpp:219
Result< void > Ok() noexcept
Success return for Result<void>; same as return {}.
Definition error.hpp:224
ErrorCategory
Error category for Result failures.
Definition error.hpp:67
cudaError_t code
Definition error.hpp:44
std::string message
Definition error.hpp:46
SourceLocation location
Definition error.hpp:45
Error payload carried in Result on failure.
Definition error.hpp:76
const FastxParseError * as_fastx_parse() const noexcept
Definition error.hpp:97
static Error invalid_argument(std::string message)
Definition error.hpp:131
static Error cuda(cudaError_t code, std::source_location location=std::source_location::current())
Definition error.hpp:110
std::variant< CudaError, IoError, FastxParseError, InvalidArgumentError, ResourceError > kind
Definition error.hpp:77
const ResourceError * as_resource() const noexcept
Definition error.hpp:105
const CudaError * as_cuda() const noexcept
Definition error.hpp:89
ErrorCategory category() const noexcept
Definition error.hpp:79
static Error io(std::string message)
Definition error.hpp:119
const IoError * as_io() const noexcept
Definition error.hpp:93
static Error resource(std::string message)
Definition error.hpp:135
const std::string & message() const noexcept
Definition error.hpp:83
const InvalidArgumentError * as_invalid_argument() const noexcept
Definition error.hpp:101
static Error fastx_parse(SourceLocation site, std::string_view detail)
Definition error.hpp:123
std::string message
Definition error.hpp:55
SourceLocation location
Definition error.hpp:54
std::string message
Definition error.hpp:50
std::string message
Definition error.hpp:63
static Result err(Error error)
Definition error.hpp:172
static Result ok()
Definition error.hpp:168
Fallible API result: cuda::std::expected<T, Error> with cuSBF factories.
Definition error.hpp:152
static Result ok(T value)
Definition error.hpp:155
static Result err(Error error)
Definition error.hpp:159
File, line, and column for a C++ call site or FASTX input position.
Definition error.hpp:20
std::string file
Definition error.hpp:21
static SourceLocation from(std::source_location location)
Definition error.hpp:25
static SourceLocation fastx(std::string_view file, uint32_t line, uint32_t column)
Definition error.hpp:34
std::string to_string() const
Definition error.hpp:38