11#pragma once
22
3+ #include " debug.hpp"
4+ #include < cuda_runtime.h>
5+ #include < version>
36#include < cstddef>
47#include < cstdio>
58#include < cstdlib>
69#include < cstdarg>
7- #include < cuda_runtime.h>
810#include < memory>
911#include < new>
1012#include < string>
1113#include < system_error>
1214#include < utility>
1315#include < vector>
16+ #if __cpp_lib_source_location
17+ #include < source_location>
18+ #endif
19+ // #if __cpp_lib_memory_resource
20+ // #include <memory_resource>
21+ // #endif
1422
1523namespace cudapp {
1624
17- std::error_category const &cudaErrorCategory () noexcept {
25+ inline std::error_category const &cudaErrorCategory () noexcept {
1826 static struct : std::error_category {
1927 char const *name () const noexcept override {
2028 return " cuda" ;
@@ -28,15 +36,40 @@ std::error_category const &cudaErrorCategory() noexcept {
2836 return category;
2937}
3038
31- std::error_code makeCudaErrorCode (cudaError_t e) noexcept {
39+ inline std::error_code makeCudaErrorCode (cudaError_t e) noexcept {
3240 return std::error_code (static_cast <int >(e), cudaErrorCategory ());
3341}
3442
35- void throwCudaError (cudaError_t err, char const *file, int line) {
43+ inline void throwCudaError (cudaError_t err, char const *file, int line) {
3644 throw std::system_error (makeCudaErrorCode (err),
37- std::string (file) + " :" + std::to_string (line));
45+ std::string (file ? file : " ?? " ) + " :" + std::to_string (line));
3846}
3947
48+ struct CheckCuda {
49+ const char *file = nullptr ;
50+ int line = 0 ;
51+
52+ #if __cpp_lib_source_location
53+ constexpr CheckCuda (std::source_location const &loc = std::source_location::current())
54+ : file(loc.file_name()), line(loc.line())
55+ {}
56+ #else
57+ #if defined(__GNUC__) && defined(__has_builtin)
58+ #if __has_builtin(__builtin_FILE) && __has_builtin(__builtin_LINE)
59+ constexpr CheckCuda (const char *file = __builtin_FILE(), int line = __builtin_LINE())
60+ : file(file), line(line)
61+ {}
62+ #endif
63+ #endif
64+ #endif
65+
66+ void operator =(cudaError_t err) {
67+ if (err != cudaSuccess) [[unlikely]] {
68+ ::cudapp::throwCudaError (err, file, line);
69+ }
70+ }
71+ };
72+
4073#define CHECK_CUDA (expr ) \
4174 do { \
4275 cudaError_t err = (expr); \
@@ -47,7 +80,7 @@ void throwCudaError(cudaError_t err, char const *file, int line) {
4780
4881struct CudaHostArena {
4982 static cudaError_t doMalloc (void **ptr, size_t size) noexcept {
50- return cudaMallocHost (& ptr, size);
83+ return cudaMallocHost (ptr, size);
5184 }
5285
5386 static cudaError_t doFree (void *ptr) noexcept {
@@ -57,7 +90,7 @@ struct CudaHostArena {
5790
5891struct CudaDeviceArena {
5992 static cudaError_t doMalloc (void **ptr, size_t size) noexcept {
60- return cudaMalloc (& ptr, size);
93+ return cudaMalloc (ptr, size);
6194 }
6295
6396 static cudaError_t doFree (void *ptr) noexcept {
@@ -67,7 +100,7 @@ struct CudaDeviceArena {
67100
68101struct CudaManagedArena {
69102 static cudaError_t doMalloc (void **ptr, size_t size) noexcept {
70- return cudaMallocManaged (& ptr, size);
103+ return cudaMallocManaged (ptr, size);
71104 }
72105
73106 static cudaError_t doFree (void *ptr) noexcept {
@@ -423,7 +456,7 @@ struct CudaAllocator : private Arena {
423456
424457 T *allocate (size_t size) {
425458 void *ptr = nullptr ;
426- if (sizeof (T) <= 1 || size > std::numeric_limits<size_t >::max () /
459+ if (sizeof (T) > 1 && size > std::numeric_limits<size_t >::max () /
427460 sizeof (T)) [[unlikely]] {
428461 throw std::bad_array_new_length ();
429462 }
@@ -439,21 +472,41 @@ struct CudaAllocator : private Arena {
439472 CHECK_CUDA (Arena::doFree (ptr));
440473 }
441474
475+ #if __cpp_constexpr_dynamic_alloc && __cpp_if_constexpr
442476 template <class ... Args>
443- static constexpr std::enable_if_t <sizeof ...(Args)>
477+ static std::enable_if_t <sizeof ...(Args)>
444478 construct (T *p, Args &&...args) noexcept (noexcept (
445- ::new (static_cast <void *>(p)) T(std::forward<Args>(args)...))) {
479+ std::construct_at (p, std::forward<Args>(args)...))) {
480+ std::construct_at (p, std::forward<Args>(args)...);
481+ }
482+
483+ static void
484+ construct (T *p) noexcept (noexcept (std::construct_at(p))) {
485+ if constexpr (!std::is_trivial_v<T>) {
486+ std::construct_at (p);
487+ }
488+ }
489+
490+ static void destroy (T *p) noexcept (noexcept (std::destroy_at(p))) {
491+ std::destroy_at (p);
492+ }
493+ #else
494+ template <class ... Args>
495+ static std::enable_if_t <sizeof ...(Args)>
496+ construct(T *p, Args &&...args) noexcept (noexcept (
497+ ::new (static_cast <void *>(p)) T(std::forward<Args>(args)...))) {
446498 ::new (static_cast <void *>(p)) T (std::forward<Args>(args)...);
447499 }
448500
449- static constexpr void
450- construct (T *p) noexcept (noexcept (::new (static_cast <void *>(p)) T)) {
501+ static void
502+ construct (T *p) noexcept (noexcept (::new (static_cast <void *>(p)) T)) {
451503 ::new (static_cast <void *>(p)) T;
452504 }
453505
454- static constexpr void destroy (T *p) noexcept (noexcept (p->~T ())) {
506+ static void destroy (T *p) noexcept (noexcept (p->~T ())) {
455507 p->~T ();
456508 }
509+ #endif
457510
458511 template <class U >
459512 constexpr CudaAllocator (CudaAllocator<U> const &other) noexcept {}
@@ -487,6 +540,36 @@ __host__ __device__ static void printf(const char *fmt, ...) {
487540using ::printf ;
488541#endif
489542
543+ template <class Vector >
544+ struct CudaVectorResizer {
545+ private:
546+ Vector &m_vec;
547+ size_t m_size;
548+
549+ public:
550+ explicit CudaVectorResizer (Vector &vec) noexcept
551+ : m_vec(vec), m_size(vec.size()) {}
552+
553+ CudaVectorResizer &operator =(CudaVectorResizer &&) = delete ;
554+
555+ operator size_t &() noexcept {
556+ return m_size;
557+ }
558+
559+ operator size_t *() noexcept {
560+ return &m_size;
561+ }
562+
563+ ~CudaVectorResizer () noexcept (noexcept (m_vec.resize(m_size))) {
564+ m_vec.resize (m_size);
565+ }
566+ };
567+
568+ #if __cpp_deduction_guides
569+ template <class Vector >
570+ CudaVectorResizer (Vector &vec) -> CudaVectorResizer<Vector>;
571+ #endif
572+
490573// #if __cpp_lib_memory_resource
491574// template <class Arena>
492575// struct CudaResource : std::pmr::memory_resource, private Arena {
0 commit comments