This repository has been archived by the owner on Mar 21, 2024. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 187
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Implement
cuda::resource
and cuda::resource_with
concepts
This also adds the necessary framework for concept emulation
- Loading branch information
Showing
4 changed files
with
531 additions
and
0 deletions.
There are no files selected for viewing
147 changes: 147 additions & 0 deletions
147
.upstream-tests/test/cuda/memory_resource/memory_resource.concepts/memory_resource.pass.cpp
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,147 @@ | ||
//===----------------------------------------------------------------------===// | ||
// | ||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. | ||
// See https://llvm.org/LICENSE.txt for license information. | ||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception | ||
// | ||
//===----------------------------------------------------------------------===// | ||
|
||
// UNSUPPORTED: c++03, c++11 | ||
|
||
// cuda::resource, cuda::resource_with | ||
#include <cuda/memory_resource> | ||
|
||
#include <cuda/std/cstdint> | ||
|
||
struct invalid_argument {}; | ||
|
||
namespace test_resource { | ||
struct valid_resource { | ||
void* allocate(std::size_t, std::size_t) { return nullptr; } | ||
void deallocate(void*, std::size_t, std::size_t) {} | ||
bool operator==(const valid_resource&) { return true; } | ||
}; | ||
static_assert(cuda::resource<valid_resource>, ""); | ||
|
||
struct invalid_allocate_argument { | ||
void* allocate(invalid_argument, std::size_t) { return nullptr; } | ||
void deallocate(void*, std::size_t, std::size_t) {} | ||
bool operator==(const valid_resource&) { return true; } | ||
}; | ||
static_assert(!cuda::resource<invalid_allocate_argument>, ""); | ||
|
||
struct invalid_allocate_return { | ||
int allocate(std::size_t, std::size_t) { return 42; } | ||
void deallocate(void*, std::size_t, std::size_t) {} | ||
bool operator==(const valid_resource&) { return true; } | ||
}; | ||
static_assert(!cuda::resource<invalid_allocate_return>, ""); | ||
|
||
struct invalid_deallocate_argument { | ||
void* allocate(std::size_t, std::size_t) { return nullptr; } | ||
void deallocate(void*, invalid_argument, std::size_t) {} | ||
bool operator==(const valid_resource&) { return true; } | ||
}; | ||
static_assert(!cuda::resource<invalid_deallocate_argument>, ""); | ||
|
||
struct non_comparable { | ||
void* allocate(std::size_t, std::size_t) { return nullptr; } | ||
void deallocate(void*, std::size_t, std::size_t) {} | ||
}; | ||
// TODO: Implement equality_comparable | ||
static_assert(cuda::resource<non_comparable>, ""); | ||
} // namespace test_resource | ||
|
||
namespace test_has_property { | ||
struct prop_with_value { | ||
using value_type = int; | ||
}; | ||
struct prop {}; | ||
|
||
struct valid_property { | ||
friend void get_property(const valid_property&, prop) {} | ||
}; | ||
static_assert(!cuda::has_property<valid_property, prop_with_value>, ""); | ||
static_assert(cuda::has_property<valid_property, prop>, ""); | ||
static_assert(!cuda::has_property_with<valid_property, prop, int>, ""); | ||
|
||
struct valid_property_with_value { | ||
friend int get_property(const valid_property_with_value&, prop_with_value) { | ||
return 42; | ||
} | ||
}; | ||
static_assert(cuda::has_property<valid_property_with_value, prop_with_value>, | ||
""); | ||
static_assert(!cuda::has_property<valid_property_with_value, prop>, ""); | ||
static_assert( | ||
cuda::has_property_with<valid_property_with_value, prop_with_value, int>, | ||
""); | ||
static_assert(!cuda::has_property_with<valid_property_with_value, | ||
prop_with_value, double>, | ||
""); | ||
|
||
struct derived_from_property : public valid_property { | ||
friend int get_property(const derived_from_property&, prop_with_value) { | ||
return 42; | ||
} | ||
}; | ||
static_assert(cuda::has_property<derived_from_property, prop_with_value>, ""); | ||
static_assert(cuda::has_property<derived_from_property, prop>, ""); | ||
static_assert( | ||
cuda::has_property_with<derived_from_property, prop_with_value, int>, ""); | ||
static_assert( | ||
!cuda::has_property_with<derived_from_property, prop_with_value, double>, | ||
""); | ||
} // namespace test_has_property | ||
|
||
namespace test_resource_with { | ||
struct prop_with_value {}; | ||
struct prop {}; | ||
|
||
struct valid_resource_with_property { | ||
void* allocate(std::size_t, std::size_t) { return nullptr; } | ||
void deallocate(void*, std::size_t, std::size_t) {} | ||
bool operator==(const valid_resource_with_property&) { return true; } | ||
friend void get_property(const valid_resource_with_property&, | ||
prop_with_value) {} | ||
}; | ||
static_assert( | ||
cuda::resource_with<valid_resource_with_property, prop_with_value>, ""); | ||
|
||
struct valid_resource_without_property { | ||
void* allocate(std::size_t, std::size_t) { return nullptr; } | ||
void deallocate(void*, std::size_t, std::size_t) {} | ||
bool operator==(const valid_resource_without_property&) { return true; } | ||
}; | ||
static_assert( | ||
!cuda::resource_with<valid_resource_without_property, prop_with_value>, ""); | ||
|
||
struct invalid_resource_with_property { | ||
friend void get_property(const invalid_resource_with_property&, | ||
prop_with_value) {} | ||
}; | ||
static_assert( | ||
!cuda::resource_with<invalid_resource_with_property, prop_with_value>, ""); | ||
|
||
struct resource_with_many_properties { | ||
void* allocate(std::size_t, std::size_t) { return nullptr; } | ||
void deallocate(void*, std::size_t, std::size_t) {} | ||
bool operator==(const resource_with_many_properties&) { return true; } | ||
friend void get_property(const resource_with_many_properties&, | ||
prop_with_value) {} | ||
friend void get_property(const resource_with_many_properties&, prop) {} | ||
}; | ||
static_assert( | ||
cuda::resource_with<resource_with_many_properties, prop_with_value, prop>, | ||
""); | ||
static_assert(!cuda::resource_with<resource_with_many_properties, | ||
prop_with_value, int, prop>, | ||
""); | ||
|
||
struct derived_with_property : public valid_resource_without_property { | ||
friend void get_property(const derived_with_property&, prop_with_value) {} | ||
}; | ||
static_assert(cuda::resource_with<derived_with_property, prop_with_value>, ""); | ||
} // namespace test_resource_with | ||
|
||
int main(int, char**) { return 0; } |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,98 @@ | ||
//===----------------------------------------------------------------------===// | ||
// | ||
// Part of the CUDA Toolkit, under the Apache License v2.0 with LLVM Exceptions. | ||
// See https://llvm.org/LICENSE.txt for license information. | ||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception | ||
// | ||
//===----------------------------------------------------------------------===// | ||
|
||
#ifndef _CUDA_MEMORY_RESOURCE | ||
#define _CUDA_MEMORY_RESOURCE | ||
|
||
#include <cuda/std/type_traits> | ||
|
||
#include <cuda/std/detail/__concepts> | ||
#include <cuda/std/detail/__config> | ||
|
||
#include <cuda/std/detail/__pragma_push> | ||
|
||
#if _LIBCUDACXX_STD_VER > 11 | ||
_LIBCUDACXX_BEGIN_NAMESPACE_CUDA | ||
|
||
/////////////////////////////////////////////////////////////////////////////// | ||
// memory_resource | ||
_LIBCUDACXX_TEMPLATE(class _Ret, class _Ptr) | ||
(requires _CUDA_VSTD::is_same_v<_Ptr, _Ret>)void _Returns_matching(_Ptr) {} | ||
|
||
/// \concept _Has_member_allocate | ||
/// \brief The \c _Has_member_allocate concept | ||
template <class _Resource> | ||
_LIBCUDACXX_CONCEPT_FRAGMENT( | ||
_Has_member_allocate_, | ||
requires(_Resource &__res, size_t __bytes, size_t __alignment) // | ||
(_Returns_matching<void *>(__res.allocate(__bytes, __alignment)))); | ||
template <class _Resource> | ||
_LIBCUDACXX_CONCEPT _Has_member_allocate = | ||
_LIBCUDACXX_FRAGMENT(_Has_member_allocate_, _Resource); | ||
|
||
/// \concept _Has_member_deallocate | ||
/// \brief The \c _Has_member_deallocate concept | ||
template <class _Resource> | ||
_LIBCUDACXX_CONCEPT_FRAGMENT(_Has_member_deallocate_, | ||
requires(_Resource &__res, void *__ptr, | ||
size_t __bytes, | ||
size_t __alignment) // | ||
(__res.deallocate(__ptr, __bytes, __alignment))); | ||
template <class _Resource> | ||
_LIBCUDACXX_CONCEPT _Has_member_deallocate = | ||
_LIBCUDACXX_FRAGMENT(_Has_member_deallocate_, _Resource); | ||
|
||
/// \concept resource | ||
/// \brief The \c resource concept | ||
template <class _Resource> | ||
_LIBCUDACXX_CONCEPT resource = | ||
_Has_member_allocate<_Resource> &&_Has_member_deallocate<_Resource> | ||
/* && _CUDA_VSTD::equality_comparable<_Resource> */; | ||
|
||
/// \concept has_property | ||
/// \brief The \c has_property concept | ||
template <class _Resource, class _Property> | ||
_LIBCUDACXX_CONCEPT_FRAGMENT(_Has_property_, | ||
requires(const _Resource &__res) // | ||
(get_property(__res, _Property{}))); | ||
template <class _Resource, class _Property> | ||
_LIBCUDACXX_CONCEPT has_property = _LIBCUDACXX_FRAGMENT(_Has_property_, | ||
_Resource, _Property); | ||
|
||
/// \concept has_property_with | ||
/// \brief The \c has_property_with concept | ||
template <class _Resource, class _Property, class _Return> | ||
_LIBCUDACXX_CONCEPT_FRAGMENT( | ||
_Has_property_with_, | ||
requires(const _Resource &__res) // | ||
(_Returns_matching<_Return>(get_property(__res, _Property{})), | ||
_Returns_matching<_Return>( | ||
_CUDA_VSTD::declval<typename _Property::value_type>()))); | ||
template <class _Resource, class _Property, class _Return> | ||
_LIBCUDACXX_CONCEPT has_property_with = | ||
_LIBCUDACXX_FRAGMENT(_Has_property_with_, _Resource, _Property, _Return); | ||
|
||
/// \concept resource | ||
/// \brief The \c resource concept | ||
template <class _Resource, class... _Properties> | ||
#if _LIBCUDACXX_STD_VER < 17 | ||
_LIBCUDACXX_CONCEPT resource_with = | ||
resource<_Resource> &&_CUDA_VSTD::conjunction<_CUDA_VSTD::bool_constant< | ||
has_property<_Resource, _Properties>>...>::value; | ||
#else | ||
_LIBCUDACXX_CONCEPT resource_with = resource<_Resource> // | ||
&& (has_property<_Resource, _Properties> && | ||
...); | ||
#endif | ||
|
||
_LIBCUDACXX_END_NAMESPACE_CUDA | ||
#endif // _LIBCUDACXX_STD_VER > 11 | ||
|
||
#include <cuda/std/detail/__pragma_pop> | ||
|
||
#endif //_LIBCUDACXX_BEGIN_NAMESPACE_CUDA |
Oops, something went wrong.