cuDDL
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#include <cuda/stream>
6
7#include <concepts>
8#include <cstdint>
9#include <cstdio>
10#include <format>
11#include <source_location>
12#include <stdexcept>
13#include <string>
14#include <type_traits>
15#include <utility>
16#include <variant>
17
18namespace cuddl {
19
22 std::string file;
23 uint32_t line{};
24 uint32_t column{};
25
26 [[nodiscard]] static SourceLocation from(std::source_location location) {
27 return SourceLocation{
28 location.file_name(),
29 static_cast<uint32_t>(location.line()),
30 static_cast<uint32_t>(location.column()),
31 };
32 }
33
34 [[nodiscard]] std::string to_string() const {
35 return std::format("{}:{}:{}", file, line, column);
36 }
37};
38
45
48 std::string message;
49};
50
53 std::string message;
54};
55
57enum class ErrorCategory : uint8_t {
58 cuda,
61};
62
64struct Error {
65 std::variant<CudaError, InvalidArgumentError, ResourceError> kind;
66
67 [[nodiscard]] ErrorCategory category() const noexcept {
68 return static_cast<ErrorCategory>(kind.index());
69 }
70
71 [[nodiscard]] const std::string& message() const noexcept {
72 return std::visit(
73 [](const auto& error) -> const std::string& { return error.message; }, kind
74 );
75 }
76
77 [[nodiscard]] const CudaError* as_cuda() const noexcept {
78 return std::get_if<CudaError>(&kind);
79 }
80
81 [[nodiscard]] const InvalidArgumentError* as_invalid_argument() const noexcept {
82 return std::get_if<InvalidArgumentError>(&kind);
83 }
84
85 [[nodiscard]] const ResourceError* as_resource() const noexcept {
86 return std::get_if<ResourceError>(&kind);
87 }
88
89 [[nodiscard]] static Error
90 cuda(cudaError_t code, std::source_location location = std::source_location::current()) {
91 const SourceLocation site = SourceLocation::from(location);
92 return Error{CudaError{
93 code,
94 site,
95 std::format("{}: {}", site.to_string(), cudaGetErrorString(code)),
96 }};
97 }
98
99 [[nodiscard]] static Error invalid_argument(std::string message) {
100 return Error{InvalidArgumentError{std::move(message)}};
101 }
102
103 [[nodiscard]] static Error resource(std::string message) {
104 return Error{ResourceError{std::move(message)}};
105 }
106};
107static_assert(static_cast<size_t>(ErrorCategory::cuda) == 0);
108static_assert(static_cast<size_t>(ErrorCategory::invalid_argument) == 1);
109static_assert(static_cast<size_t>(ErrorCategory::resource) == 2);
110
117template <typename T>
118struct [[nodiscard]] Result : cuda::std::expected<T, Error> {
119 using cuda::std::expected<T, Error>::expected;
120
121 [[nodiscard]] static Result ok(T value) {
122 return Result(std::move(value));
123 }
124
125 [[nodiscard]] static Result err(Error error) {
126 return Result(cuda::std::unexpect, std::move(error));
127 }
128};
129
130template <>
131struct [[nodiscard]] Result<void> : cuda::std::expected<void, Error> {
132 using cuda::std::expected<void, Error>::expected;
133
134 [[nodiscard]] static Result ok() {
135 return {};
136 }
137
138 [[nodiscard]] static Result err(Error error) {
139 return Result(cuda::std::unexpect, std::move(error));
140 }
141};
142
145 cudaError_t error,
146 std::source_location location = std::source_location::current()
147) {
148 if (error == cudaSuccess) {
149 return;
150 }
151 const Error err = Error::cuda(error, location);
152 std::fputs(err.message().c_str(), stderr);
153 std::fputc('\n', stderr);
154 std::abort();
155}
156
157namespace detail {
158
159template <typename T>
160[[nodiscard]] T try_unwrap_success(Result<T>& result) {
161 return std::move(*result);
162}
163
164inline void try_unwrap_success(Result<void>& result) {
165 (void)result;
166}
167
169[[nodiscard]] inline cuda::std::unexpected<Error> propagate_error(const Error& error) {
170 return cuda::std::unexpected<Error>(Error{error});
171}
172
173} // namespace detail
174
176[[nodiscard]] inline cuda::std::unexpected<Error> Err(Error error) {
177 return cuda::std::unexpected<Error>(std::move(error));
178}
179
181[[nodiscard]] inline Result<void> Ok() noexcept {
182 return {};
183}
184
186[[nodiscard]] inline Result<void>
187cuda_try(cudaError_t error, std::source_location location = std::source_location::current()) {
188 if (error == cudaSuccess) {
189 return Ok();
190 }
191 return Err(Error::cuda(error, location));
192}
193
195template <std::invocable Operation>
196[[nodiscard]] auto
197cuda_try(Operation&& operation, std::source_location location = std::source_location::current()) {
198 using Value = std::invoke_result_t<Operation>;
200 try {
201 if constexpr (std::is_void_v<Value>) {
202 std::forward<Operation>(operation)();
203 return Return::ok();
204 } else if constexpr (std::is_same_v<Value, cudaError_t>) {
205 return cuda_try(std::forward<Operation>(operation)(), location);
206 } else {
207 return Return::ok(std::forward<Operation>(operation)());
208 }
209 } catch (cuda::cuda_error const& error) {
210 return Return::err(Error::cuda(static_cast<cudaError_t>(error.status()), location));
211 } catch (std::bad_alloc const& error) {
212 return Return::err(Error::resource(error.what()));
213 }
214}
215
216} // namespace cuddl
217
225#define CUDDL_TRY(expr) \
226 ({ \
227 auto _cuddl_result = (expr); \
228 if (!_cuddl_result) { \
229 return ::cuddl::detail::propagate_error(_cuddl_result.error()); \
230 } \
231 ::cuddl::detail::try_unwrap_success(_cuddl_result); \
232 })
233
235#define CUDDL_UNWRAP(expr) \
236 ({ \
237 auto _cuddl_result = (expr); \
238 if (!_cuddl_result) { \
239 throw std::runtime_error(_cuddl_result.error().message()); \
240 } \
241 ::cuddl::detail::try_unwrap_success(_cuddl_result); \
242 })
243
245#define CUDDL_CUDA_ABORT(expr) ::cuddl::cuda_abort_on_error((expr))
246
248#define CUDDL_CUDA_TRY(...) CUDDL_TRY(::cuddl::cuda_try([&] { return (__VA_ARGS__); }))
T try_unwrap_success(Result< T > &result)
Definition error.hpp:160
cuda::std::unexpected< Error > propagate_error(const Error &error)
Copies error for propagation (avoids moving out of expected::error()).
Definition error.hpp:169
Batch operations over contiguous device rows.
Definition a48.hpp:14
Result< void > Ok() noexcept
Success return for Result<void>; same as return {}.
Definition error.hpp:181
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:144
ErrorCategory
Error category for Result failures.
Definition error.hpp:57
cuda::std::unexpected< Error > Err(Error error)
Failure return; converts to any Result<T> via cuda::std::unexpected.
Definition error.hpp:176
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:187
CUDA failure payload: status code, call site, and formatted message.
Definition error.hpp:40
cudaError_t code
Definition error.hpp:41
std::string message
Definition error.hpp:43
SourceLocation location
Definition error.hpp:42
Error payload carried in Result on failure.
Definition error.hpp:64
static Error cuda(cudaError_t code, std::source_location location=std::source_location::current())
Definition error.hpp:90
const std::string & message() const noexcept
Definition error.hpp:71
static Error invalid_argument(std::string message)
Definition error.hpp:99
std::variant< CudaError, InvalidArgumentError, ResourceError > kind
Definition error.hpp:65
ErrorCategory category() const noexcept
Definition error.hpp:67
static Error resource(std::string message)
Definition error.hpp:103
const InvalidArgumentError * as_invalid_argument() const noexcept
Definition error.hpp:81
const CudaError * as_cuda() const noexcept
Definition error.hpp:77
const ResourceError * as_resource() const noexcept
Definition error.hpp:85
Invalid-argument failure payload.
Definition error.hpp:47
Resource failure payload: allocation, I/O, or capacity errors.
Definition error.hpp:52
std::string message
Definition error.hpp:53
static Result err(Error error)
Definition error.hpp:138
static Result ok()
Definition error.hpp:134
Fallible API result: cuda::std::expected<T, Error> with cuDDL factories.
Definition error.hpp:118
static Result err(Error error)
Definition error.hpp:125
static Result ok(T value)
Definition error.hpp:121
File, line, and column for a C++ call site or FASTX input position.
Definition error.hpp:21
static SourceLocation from(std::source_location location)
Definition error.hpp:26
std::string file
Definition error.hpp:22
std::string to_string() const
Definition error.hpp:34