Skip to content

Commit

Permalink
Fixes #586: Factored out the span class into its own file
Browse files Browse the repository at this point in the history
  • Loading branch information
eyalroz committed Mar 1, 2024
1 parent 5b0e27f commit 7fcb951
Show file tree
Hide file tree
Showing 2 changed files with 79 additions and 57 deletions.
78 changes: 78 additions & 0 deletions src/cuda/api/detail/span.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
/**
* @file
*
* @brief Contains an implementation of an std::span-like class, @ref `cuda::span`
*
* @note When compiling with C++20 or later, the actual std::span is used instead
*/

#pragma once
#ifndef CUDA_API_WRAPPERS_SPAN_HPP_
#define CUDA_API_WRAPPERS_SPAN_HPP_

#if __cplusplus >= 202002L
#include <span>
#else
#include <type_traits>
#include <cstdlib>
#endif

/**
* @brief All definitions and functionality wrapping the CUDA Runtime API.
*/
namespace cuda {

#if __cplusplus >= 202002L
using ::std::span;
#else
/**
* @brief A "poor man's" span class
*
* @todo: Replace this with a more proper implementation.
*
* @note Remember a span is a reference type. That means that changes to the
* pointed-to data are _not_considered changes to the span, hence you can get
* to that data with const methods.
*/
template<typename T>
struct span {
using value_type = T;
using element_type = T;
using size_type = ::std::size_t;
using difference_type = ::std::ptrdiff_t;
using pointer = T*;
using const_pointer = T const *;
using reference = T&;
using const_reference = const T&;

pointer data_;
size_type size_;

pointer data() const noexcept { return data_; }
size_type size() const noexcept { return size_; }

// About cbegin() and cend() for spans, see:
// https://stackoverflow.com/q/62757700/1593077
// (for which reason, they're not implemented here)
pointer begin() const noexcept { return data(); }
pointer end() const noexcept { return data() + size_; }

reference operator[](size_type idx) const noexcept { return data_[idx]; }

// Allows a non-const-element span to be used as its const-element equivalent. With pointers,
// we get a T* to const T* casting for free, but the span has to take care of this for itself.
template<
typename U = value_type,
typename = typename ::std::enable_if<! ::std::is_const<U>::value>::type
>
operator span<const U>()
{
static_assert(::std::is_same<U,T>::value, "Invalid type specified");
return { data_, size_ };
}
};
#endif

} // namespace cuda

#endif // CUDA_API_WRAPPERS_SPAN_HPP_
58 changes: 1 addition & 57 deletions src/cuda/api/types.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -24,16 +24,13 @@
#endif

#include "detail/optional.hpp"
#include "detail/span.hpp"

#ifndef __CUDACC__
#include <builtin_types.h>
#endif
#include <cuda.h>

#if __cplusplus >= 202002L
#include <span>
#endif

#include <type_traits>
#include <utility>
#include <cassert>
Expand Down Expand Up @@ -128,59 +125,6 @@ struct is_kinda_like_contiguous_container :

} // namespace detail_

#if __cplusplus >= 202002L
using ::std::span;
#else

/**
* @brief A "poor man's" span class
*
* @todo: Replace this with a more proper span, possibly in a file of its own.
*
* @note Remember a span is a reference type. That means that changes to the
* pointed-to data are _not_considered changes to the span, hence you can get
* to that data with const methods.
*/
template<typename T>
struct span {
using value_type = T;
using element_type = T;
using size_type = size_t;
using difference_type = ::std::ptrdiff_t;
using pointer = T*;
using const_pointer = T const *;
using reference = T&;
using const_reference = const T&;

pointer data_;
size_t size_;

pointer data() const noexcept { return data_; }
size_type size() const noexcept { return size_; }

// About cbegin() and cend() for spans, see:
// https://stackoverflow.com/q/62757700/1593077
// (for which reason, they're not implemented here)
pointer begin() const noexcept { return data(); }
pointer end() const noexcept { return data() + size_; }

reference operator[](size_t idx) const noexcept { return data_[idx]; }

// Allows a non-const-element span to be used as its const-element equivalent. With pointers,
// we get a T* to const T* casting for free, but the span has to take care of this for itself.
template<
typename U = value_type,
typename = typename ::std::enable_if<not ::std::is_const<U>::value>::type
>
operator span<const U>()
{
static_assert(::std::is_same<U,T>::value, "Invalid type specified");
return { data_, size_ };
}
};

#endif

/**
* Indicates either the result (success or error index) of a CUDA Runtime or Driver API call,
* or the overall status of the API (which is typically the last triggered error).
Expand Down

0 comments on commit 7fcb951

Please sign in to comment.