File: memory_resource

package info (click to toggle)
nvidia-cuda-toolkit 12.4.1-3
  • links: PTS, VCS
  • area: non-free
  • in suites: forky, sid
  • size: 18,505,836 kB
  • sloc: ansic: 203,477; cpp: 64,769; python: 34,699; javascript: 22,006; xml: 13,410; makefile: 3,085; sh: 2,343; perl: 352
file content (632 lines) | stat: -rw-r--r-- 24,678 bytes parent folder | download | duplicates (7)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
//===----------------------------------------------------------------------===//
//
// 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
// SPDX-FileCopyrightText: Copyright (c) 2023 NVIDIA CORPORATION & AFFILIATES.
//
//===----------------------------------------------------------------------===//

#ifndef _CUDA_MEMORY_RESOURCE
#define _CUDA_MEMORY_RESOURCE

// clang-format off
/*
    memory_resource synopsis
namespace cuda {
namespace mr {
template <class Resource>
concept resource = equality_comparable<Resource>
                && requires(Resource& res, void* ptr, size_t size, size_t alignment) {
    { res.allocate(size, alignment) } -> same_as<void*>;
    { res.deallocate(ptr, size, alignment) } -> same_as<void>;
};

template <class Resource>
concept async_resource = resource<Resource>
                      && requires(Resource& res, void* ptr, size_t size, size_t alignment, cuda_stream_ref stream) {
    { res.allocate_async(size, alignment, stream) } -> same_as<void*>;
    { res.deallocate_async(ptr, size, alignment, stream) } -> same_as<void>;
};

template <class Resource, class Property>
concept has_property = resource<Resource> && requires(const Resource& res, Property prop) {
    get_property(res, prop);
};

template <class Property>
concept property_with_value = requires {
    typename Property::value_type;
};

template <class Resource, class Property, class Return>
concept has_property_with = resource<Resource>
                         && property_with_value<Property>
                         && same_as<Return, typename Property::value_type>
                         && requires(const Resource& res, Property prop) {
    get_property(res, prop) -> Return;
};

template <class Resource, class... Properties>
concept resource_with = resource<Resource> && (has_property<Resource, Properties> && ...);

template <class Resource, class... Properties>
concept async_resource_with = async_resource<Resource> && (has_property<Resource, Properties> && ...);

template <class... Properties>
class resource_ref {
    template <resource_with<Properties...> Resource>
    resource_ref(Resource&) noexcept;

    void* allocate(size_t size, size_t alignment);
    void deallocate(void* ptr, size_t size, size_t alignment);

    template <class... OtherProperties>
        requires resource_with<resource_ref, OtherProperties...>
              && resource_with<resource_ref<OtherProperties...>, Properties...>
    friend bool operator==(const resource_ref& left, const resource_ref<OtherProperties...>& right);

    template <property_with_value Property>
        requires has_property<resource_ref, Property>
    friend typename Property::value_type get_property(const resource_ref& ref, Property) noexcept;

    template <class Property>
        requires (has_property<resource_ref, Property> && !property_with_value<Property>)
    friend void get_property(const resource_ref& ref, Property) noexcept;
};

}  // mr
}  // cuda
*/
// clang-format on

#ifdef LIBCUDACXX_ENABLE_EXPERIMENTAL_MEMORY_RESOURCE

#include <cuda/stream_ref>

#include <cuda/std/concepts>
#include <cuda/std/type_traits>

#include <cuda/std/detail/__config>

#include <cuda/std/detail/__pragma_push>

#if _LIBCUDACXX_STD_VER > 11
_LIBCUDACXX_BEGIN_NAMESPACE_CUDA

///////////////////////////////////////////////////////////////////////////////
// properties

/// \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 property_with_value
/// \brief The \c property_with_value concept
template <class _Property>
using __property_value_t = typename _Property::value_type;

template <class _Property>
_LIBCUDACXX_CONCEPT_FRAGMENT(
  __property_with_value_,
  requires()(
    typename(__property_value_t<_Property>)
  ));
template <class _Property>
_LIBCUDACXX_CONCEPT property_with_value = _LIBCUDACXX_FRAGMENT(__property_with_value_, _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)(
    requires(property_with_value<_Property>),
    requires(_CUDA_VSTD::same_as<_Return, decltype(get_property(__res, _Property{}))>)
  ));
template <class _Resource, class _Property, class _Return>
_LIBCUDACXX_CONCEPT has_property_with = _LIBCUDACXX_FRAGMENT(__has_property_with_, _Resource, _Property, _Return);

/// \concept __has_upstream_resource
/// \brief The \c __has_upstream_resource concept
template <class _Resource, class _Upstream>
_LIBCUDACXX_CONCEPT_FRAGMENT(
  __has_upstream_resource_,
  requires(const _Resource& __res)(
    requires(_CUDA_VSTD::same_as<_CUDA_VSTD::__remove_const_ref_t<decltype(__res.upstream_resource())>, _Upstream>)
  ));
template <class _Resource, class _Upstream>
_LIBCUDACXX_CONCEPT __has_upstream_resource = _LIBCUDACXX_FRAGMENT(__has_upstream_resource_, _Resource, _Upstream);

/// class forward_property
/// \brief The \c forward_property crtp template simplifies the user facing side of forwarding properties
///        We can just derive from it to properly forward all properties
_LIBCUDACXX_BEGIN_NAMESPACE_CPO(__forward_property)
template <class _Derived, class _Upstream>
struct __fn {
  _LIBCUDACXX_DISABLE_EXEC_CHECK
  _LIBCUDACXX_TEMPLATE(class _Property)
    _LIBCUDACXX_REQUIRES( (!property_with_value<_Property>) _LIBCUDACXX_AND has_property<_Upstream, _Property>)
  _LIBCUDACXX_INLINE_VISIBILITY friend constexpr void get_property(const _Derived&, _Property) noexcept {}

  // The indirection is needed, otherwise the compiler might believe that _Derived is an incomplete type
  _LIBCUDACXX_DISABLE_EXEC_CHECK
  _LIBCUDACXX_TEMPLATE(class _Property, class _Derived2 = _Derived)
    _LIBCUDACXX_REQUIRES( property_with_value<_Property> _LIBCUDACXX_AND has_property<_Upstream, _Property> _LIBCUDACXX_AND
              __has_upstream_resource<_Derived2, _Upstream>)
  _LIBCUDACXX_INLINE_VISIBILITY friend constexpr __property_value_t<_Property> get_property(
    const _Derived& __res, _Property __prop) {
    return get_property(__res.upstream_resource(), __prop);
  }
};
_LIBCUDACXX_END_NAMESPACE_CPO

template <class _Derived, class _Upstream>
using forward_property = __forward_property::__fn<_Derived, _Upstream>;

/// class get_property
/// \brief The \c get_property crtp temaplate simplifies the user facing side of forwarding properties
///        We can always tell people to just derive from it to properly forward all properties
_LIBCUDACXX_BEGIN_NAMESPACE_CPO(__get_property)
struct __fn {
  _LIBCUDACXX_DISABLE_EXEC_CHECK
  _LIBCUDACXX_TEMPLATE(class _Upstream, class _Property)
    _LIBCUDACXX_REQUIRES( (!property_with_value<_Property>) _LIBCUDACXX_AND has_property<_Upstream, _Property>)
  _LIBCUDACXX_INLINE_VISIBILITY constexpr void operator()(const _Upstream&, _Property) const noexcept {}

  _LIBCUDACXX_DISABLE_EXEC_CHECK
  _LIBCUDACXX_TEMPLATE(class _Upstream, class _Property)
    _LIBCUDACXX_REQUIRES( (property_with_value<_Property>) _LIBCUDACXX_AND has_property<_Upstream, _Property>)
  _LIBCUDACXX_INLINE_VISIBILITY constexpr __property_value_t<_Property> operator()(
    const _Upstream& __res, _Property __prop) const {
    return get_property(__res, __prop);
  }
};
_LIBCUDACXX_END_NAMESPACE_CPO

inline namespace __cpo {
  _LIBCUDACXX_CPO_ACCESSIBILITY auto get_property = __get_property::__fn{};
} // namespace __cpo

namespace mr
{

///////////////////////////////////////////////////////////////////////////////
// memory_resource

/// \concept resource
/// \brief The \c resource concept
template <class _Resource>
_LIBCUDACXX_CONCEPT_FRAGMENT(
  __resource_,
  requires(_Resource& __res, void* __ptr, size_t __bytes, size_t __alignment) (
    requires(_CUDA_VSTD::same_as<void*, decltype(__res.allocate(__bytes, __alignment))>),
    requires(_CUDA_VSTD::same_as<void, decltype(__res.deallocate(__ptr, __bytes, __alignment))>),
    requires(_CUDA_VSTD::equality_comparable<_Resource>)
  ));

template <class _Resource>
_LIBCUDACXX_CONCEPT resource = _LIBCUDACXX_FRAGMENT(__resource_, _Resource);

/// \concept async_resource
/// \brief The \c async_resource concept
template <class _Resource>
_LIBCUDACXX_CONCEPT_FRAGMENT(
  __async_resource_,
  requires(_Resource& __res, void* __ptr, size_t __bytes, size_t __alignment, cuda::stream_ref __stream) (
    requires(resource<_Resource>),
    requires(_CUDA_VSTD::same_as<void*, decltype(__res.allocate_async(__bytes, __alignment, __stream))>),
    requires(_CUDA_VSTD::same_as<void, decltype(__res.deallocate_async(__ptr, __bytes, __alignment, __stream))>),
    requires(_CUDA_VSTD::equality_comparable<_Resource>)
  ));

template <class _Resource>
_LIBCUDACXX_CONCEPT async_resource = _LIBCUDACXX_FRAGMENT(__async_resource_, _Resource);

/// \concept resource_with
/// \brief The \c resource_with concept
template <class _Resource, class... _Properties>
#if _LIBCUDACXX_STD_VER < 17
_LIBCUDACXX_CONCEPT resource_with =
  resource<_Resource>&& _CUDA_VSTD::conjunction_v<_CUDA_VSTD::bool_constant<has_property<_Resource, _Properties>>...>;
#else
_LIBCUDACXX_CONCEPT resource_with = resource<_Resource> && (has_property<_Resource, _Properties> && ...);
#endif

/// \concept async_resource_with
/// \brief The \c async_resource_with concept
template <class _Resource, class... _Properties>
#if _LIBCUDACXX_STD_VER < 17
_LIBCUDACXX_CONCEPT async_resource_with = async_resource<_Resource> &&
  _CUDA_VSTD::conjunction_v<_CUDA_VSTD::bool_constant<has_property<_Resource, _Properties>>...>;
#else
_LIBCUDACXX_CONCEPT async_resource_with = async_resource<_Resource> &&
  (has_property<_Resource, _Properties> && ...);
#endif

///////////////////////////////////////////////////////////////////////////////
/// class resource_ref
/// class async_resource_ref
enum class _AllocType
{
  _Default,
  _Async,
};

struct _Alloc_vtable
{
  using _AllocFn   = void* (*)(void*, size_t, size_t);
  using _DeallocFn = void (*)(void*, void*, size_t, size_t);
  using _EqualFn   = bool (*)(void*, void*);

  _AllocFn __alloc_fn;
  _DeallocFn __dealloc_fn;
  _EqualFn __equal_fn;

  constexpr _Alloc_vtable(_AllocFn __alloc_fn_, _DeallocFn __dealloc_fn_, _EqualFn __equal_fn_) noexcept
      : __alloc_fn(__alloc_fn_)
      , __dealloc_fn(__dealloc_fn_)
      , __equal_fn(__equal_fn_)
  {}
};

struct _Async_alloc_vtable : public _Alloc_vtable
{
  using _AsyncAllocFn   = void* (*)(void*, size_t, size_t, cuda::stream_ref);
  using _AsyncDeallocFn = void (*)(void*, void*, size_t, size_t, cuda::stream_ref);

  _AsyncAllocFn __async_alloc_fn;
  _AsyncDeallocFn __async_dealloc_fn;

  constexpr _Async_alloc_vtable(_Alloc_vtable::_AllocFn __alloc_fn_,
                                _Alloc_vtable::_DeallocFn __dealloc_fn_,
                                _Alloc_vtable::_EqualFn __equal_fn_,
                                _AsyncAllocFn __async_alloc_fn_,
                                _AsyncDeallocFn __async_dealloc_fn_) noexcept
      : _Alloc_vtable(__alloc_fn_, __dealloc_fn_, __equal_fn_)
      , __async_alloc_fn(__async_alloc_fn_)
      , __async_dealloc_fn(__async_dealloc_fn_)
  {}
};

// clang-format off
struct _Resource_vtable_builder
{
    template <class _Resource, class _Property>
    static __property_value_t<_Property> _Get_property(void* __res) noexcept {
        return get_property(*static_cast<const _Resource *>(__res), _Property{});
    }

    template <class _Resource>
    static void* _Alloc(void* __object, size_t __bytes, size_t __alignment) {
        return static_cast<_Resource *>(__object)->allocate(__bytes, __alignment);
    }

    template <class _Resource>
    static void _Dealloc(void* __object, void* __ptr, size_t __bytes, size_t __alignment) {
        return static_cast<_Resource *>(__object)->deallocate(__ptr, __bytes, __alignment);
    }

    template <class _Resource>
    static void* _Alloc_async(void* __object, size_t __bytes, size_t __alignment, cuda::stream_ref __stream) {
        return static_cast<_Resource *>(__object)->allocate_async(__bytes, __alignment, __stream);
    }

    template <class _Resource>
    static void _Dealloc_async(void* __object, void* __ptr, size_t __bytes, size_t __alignment, cuda::stream_ref __stream) {
        return static_cast<_Resource *>(__object)->deallocate_async(__ptr, __bytes, __alignment, __stream);
    }

    template <class _Resource>
    static bool _Equal(void* __left, void* __right) {
        return *static_cast<_Resource *>(__left) == *static_cast<_Resource *>(__right);
    }

    _LIBCUDACXX_TEMPLATE(class _Resource, _AllocType _Alloc_type)
      _LIBCUDACXX_REQUIRES((_Alloc_type == _AllocType::_Default)) //
     static constexpr _Alloc_vtable _Create() noexcept
    {
      return {&_Resource_vtable_builder::_Alloc<_Resource>,
              &_Resource_vtable_builder::_Dealloc<_Resource>,
              &_Resource_vtable_builder::_Equal<_Resource>};
    }

    _LIBCUDACXX_TEMPLATE(class _Resource, _AllocType _Alloc_type)
      _LIBCUDACXX_REQUIRES((_Alloc_type == _AllocType::_Async)) //
     static constexpr _Async_alloc_vtable _Create() noexcept
    {
      return {&_Resource_vtable_builder::_Alloc<_Resource>,
              &_Resource_vtable_builder::_Dealloc<_Resource>,
              &_Resource_vtable_builder::_Equal<_Resource>,
              &_Resource_vtable_builder::_Alloc_async<_Resource>,
              &_Resource_vtable_builder::_Dealloc_async<_Resource>};
    }
};
// clang-format on

template <class _Property>
struct _Property_vtable
{
  using _PropertyFn         = __property_value_t<_Property> (*)(void*);
  _PropertyFn __property_fn = nullptr;

  constexpr _Property_vtable(_PropertyFn __property_fn_) noexcept
      : __property_fn(__property_fn_)
  {}
};

template <_AllocType _Alloc_type, class... _Properties> //
class basic_resource_ref;

template <class... _Properties>
struct _Resource_vtable : public _Property_vtable<_Properties>...
{
  template <class... _PropertyFns>
  constexpr _Resource_vtable(_PropertyFns... __property_fn_) noexcept
      : _Property_vtable<_Properties>(__property_fn_)...
  {}

  template <_AllocType _Alloc_type, class... _OtherProperties>
  constexpr _Resource_vtable(basic_resource_ref<_Alloc_type, _OtherProperties...>& __ref) noexcept
      : _Property_vtable<_Properties>(__ref._Property_vtable<_Properties>::__property_fn)...
  {}

  template <class _Resource>
  static constexpr _Resource_vtable _Create() noexcept
  {
    return {&_Resource_vtable_builder::_Get_property<_Resource, _Properties>...};
  }
};

template <class... _Properties>
struct _Filtered;

template <bool _IsUniqueProperty>
struct _Property_filter
{
  template <class _Property, class... _Properties>
  using _Filtered_properties =
    typename _Filtered<_Properties...>::_Filtered_vtable::template _Append_property<_Property>;
};
template <>
struct _Property_filter<false>
{
  template <class _Property, class... _Properties>
  using _Filtered_properties = typename _Filtered<_Properties...>::_Filtered_vtable;
};

template <class _Property, class... _Properties>
struct _Filtered<_Property, _Properties...>
{
  using _Filtered_vtable =
    typename _Property_filter<property_with_value<_Property> && !_CUDA_VSTD::_One_of<_Property, _Properties...>>::
      template _Filtered_properties<_Property, _Properties...>;

  template <class _OtherPropery>
  using _Append_property = _Filtered<_OtherPropery, _Property, _Properties...>;

  using _Vtable = _Resource_vtable<_Property, _Properties...>;
};

template <>
struct _Filtered<>
{
  using _Filtered_vtable = _Filtered<>;

  template <class _OtherPropery>
  using _Append_property = _Filtered<_OtherPropery>;

  using _Vtable = _Resource_vtable<>;
};

template <class... _Properties>
using _Filtered_vtable = typename _Filtered<_Properties...>::_Filtered_vtable::_Vtable;

template <class _Vtable>
struct _Alloc_base
{
  static_assert(_CUDA_VSTD::is_base_of_v<_Alloc_vtable, _Vtable>, "");

  _Alloc_base(void* __object_, const _Vtable* __static_vtabl_) noexcept
      : __object(__object_)
      , __static_vtable(__static_vtabl_)
  {}

  void* allocate(size_t __bytes, size_t __alignment = alignof(max_align_t))
  {
    return __static_vtable->__alloc_fn(__object, __bytes, __alignment);
  }

  void deallocate(void* _Ptr, size_t __bytes, size_t __alignment = alignof(max_align_t))
  {
    __static_vtable->__dealloc_fn(__object, _Ptr, __bytes, __alignment);
  }

protected:
  void* __object                 = nullptr;
  const _Vtable* __static_vtable = nullptr;
};

template <class _Vtable>
struct _Async_alloc_base : public _Alloc_base<_Vtable>
{
  static_assert(_CUDA_VSTD::is_base_of_v<_Async_alloc_vtable, _Vtable>, "");

  _Async_alloc_base(void* __object_, const _Vtable* __static_vtabl_) noexcept
      : _Alloc_base<_Vtable>(__object_, __static_vtabl_)
  {}

  void* allocate_async(size_t __bytes, size_t __alignment, cuda::stream_ref __stream)
  {
    return this->__static_vtable->__async_alloc_fn(this->__object, __bytes, __alignment, __stream);
  }

  void* allocate_async(size_t __bytes, cuda::stream_ref __stream)
  {
    return this->__static_vtable->__async_alloc_fn(this->__object, __bytes, alignof(max_align_t), __stream);
  }

  void deallocate_async(void* _Ptr, size_t __bytes, cuda::stream_ref __stream)
  {
    this->__static_vtable->__async_dealloc_fn(this->__object, _Ptr, __bytes, alignof(max_align_t), __stream);
  }

  void deallocate_async(void* _Ptr, size_t __bytes, size_t __alignment, cuda::stream_ref __stream)
  {
    this->__static_vtable->__async_dealloc_fn(this->__object, _Ptr, __bytes, __alignment, __stream);
  }
};

template <_AllocType _Alloc_type>
using _Resource_ref_base = _CUDA_VSTD::
  _If<_Alloc_type == _AllocType::_Default, _Alloc_base<_Alloc_vtable>, _Async_alloc_base<_Async_alloc_vtable>>;

template <_AllocType _Alloc_type>
using _Vtable_store = _CUDA_VSTD::_If<_Alloc_type == _AllocType::_Default, _Alloc_vtable, _Async_alloc_vtable>;

template <_AllocType _Alloc_type, class _Resource>
_LIBCUDACXX_INLINE_VAR constexpr _Vtable_store<_Alloc_type>
  __alloc_vtable = _Resource_vtable_builder::template _Create<_Resource, _Alloc_type>();

template <class>
_LIBCUDACXX_INLINE_VAR constexpr bool _Is_basic_resource_ref = false;

template <_AllocType _Alloc_type, class... _Properties> //
class basic_resource_ref
    : public _Resource_ref_base<_Alloc_type>
    , private _Filtered_vtable<_Properties...>
{
private:
  template <_AllocType, class...>
  friend class basic_resource_ref;

  template <class...>
  friend struct _Resource_vtable;

public:
  // clang-format off
    _LIBCUDACXX_TEMPLATE(class _Resource)
        _LIBCUDACXX_REQUIRES( (!_Is_basic_resource_ref<_Resource>
          && (((_Alloc_type == _AllocType::_Default) && resource_with<_Resource, _Properties...>) //
            ||((_Alloc_type == _AllocType::_Async) && async_resource_with<_Resource, _Properties...>)))) //
     basic_resource_ref(_Resource& __res) noexcept
        : _Resource_ref_base<_Alloc_type>(_CUDA_VSTD::addressof(__res), &__alloc_vtable<_Alloc_type, _Resource>)
        , _Filtered_vtable<_Properties...>(_Filtered_vtable<_Properties...>::template _Create<_Resource>())
    {}

    _LIBCUDACXX_TEMPLATE(class _Resource)
        _LIBCUDACXX_REQUIRES( (!_Is_basic_resource_ref<_Resource>
          && (((_Alloc_type == _AllocType::_Default) && resource_with<_Resource, _Properties...>) //
            ||((_Alloc_type == _AllocType::_Async) && async_resource_with<_Resource, _Properties...>)))) //
     basic_resource_ref(_Resource* __res) noexcept
        : _Resource_ref_base<_Alloc_type>(__res, &__alloc_vtable<_Alloc_type, _Resource>)
        , _Filtered_vtable<_Properties...>(_Filtered_vtable<_Properties...>::template _Create<_Resource>())
    {}

    #if _LIBCUDACXX_STD_VER > 14
    _LIBCUDACXX_TEMPLATE(class... _OtherProperties)
      _LIBCUDACXX_REQUIRES( (_CUDA_VSTD::_One_of<_Properties, _OtherProperties...> && ...))
    #else
    _LIBCUDACXX_TEMPLATE(class... _OtherProperties)
      _LIBCUDACXX_REQUIRES( _CUDA_VSTD::conjunction_v<_CUDA_VSTD::bool_constant<
            _CUDA_VSTD::_One_of<_Properties, _OtherProperties...>>...>)
    #endif
     basic_resource_ref(
      basic_resource_ref<_Alloc_type, _OtherProperties...> __ref) noexcept
        : _Resource_ref_base<_Alloc_type>(__ref.__object, __ref.__static_vtable)
        , _Filtered_vtable<_Properties...>(__ref)
    {}

    #if _LIBCUDACXX_STD_VER > 14
    _LIBCUDACXX_TEMPLATE(class... _OtherProperties)
      _LIBCUDACXX_REQUIRES( (_Alloc_type == _AllocType::_Default)
        && (_CUDA_VSTD::_One_of<_Properties, _OtherProperties...> && ...))
    #else
    _LIBCUDACXX_TEMPLATE(class... _OtherProperties)
      _LIBCUDACXX_REQUIRES( (_Alloc_type == _AllocType::_Default)
        && _CUDA_VSTD::conjunction_v<_CUDA_VSTD::bool_constant<
            _CUDA_VSTD::_One_of<_Properties, _OtherProperties...>>...>)
    #endif
     basic_resource_ref(
      basic_resource_ref<_AllocType::_Async, _OtherProperties...> __ref) noexcept
        : _Resource_ref_base<_Alloc_type>(__ref.__object, __ref.__static_vtable)
        , _Filtered_vtable<_Properties...>(__ref)
    {}

    #if _LIBCUDACXX_STD_VER > 14
    _LIBCUDACXX_TEMPLATE(class... _OtherProperties)
      _LIBCUDACXX_REQUIRES((sizeof...(_Properties) == sizeof...(_OtherProperties))
            && (_CUDA_VSTD::_One_of<_Properties, _OtherProperties...> && ...))
    #else
    _LIBCUDACXX_TEMPLATE(class... _OtherProperties)
      _LIBCUDACXX_REQUIRES( (sizeof...(_Properties) == sizeof...(_OtherProperties))
          && _CUDA_VSTD::conjunction_v<_CUDA_VSTD::bool_constant<
          _CUDA_VSTD::_One_of<_Properties, _OtherProperties...>>...>)
    #endif
     bool operator==(
        const basic_resource_ref<_Alloc_type, _OtherProperties...> &__right) const {
        return (this->__static_vtable->__equal_fn == __right.__static_vtable->__equal_fn) //
            && this->__static_vtable->__equal_fn(this->__object, __right.__object);
    }

    #if _LIBCUDACXX_STD_VER > 14
    _LIBCUDACXX_TEMPLATE(class... _OtherProperties)
      _LIBCUDACXX_REQUIRES( (sizeof...(_Properties) == sizeof...(_OtherProperties))
            && (_CUDA_VSTD::_One_of<_Properties, _OtherProperties...> && ...))
    #else
    _LIBCUDACXX_TEMPLATE(class... _OtherProperties)
      _LIBCUDACXX_REQUIRES( (sizeof...(_Properties) == sizeof...(_OtherProperties))
          && _CUDA_VSTD::conjunction_v<_CUDA_VSTD::bool_constant<
          _CUDA_VSTD::_One_of<_Properties, _OtherProperties...>>...>)
    #endif
     bool operator!=(
        const basic_resource_ref<_Alloc_type, _OtherProperties...> &__right) const {
        return !(*this == __right);
    }

    _LIBCUDACXX_TEMPLATE(class _Property)
        _LIBCUDACXX_REQUIRES( (!property_with_value<_Property>) _LIBCUDACXX_AND  _CUDA_VSTD::_One_of<_Property, _Properties...>) //
     friend void get_property(const basic_resource_ref &, _Property) noexcept {}

    _LIBCUDACXX_TEMPLATE(class _Property)
        _LIBCUDACXX_REQUIRES(  property_with_value<_Property> _LIBCUDACXX_AND _CUDA_VSTD::_One_of<_Property, _Properties...>) //
     friend __property_value_t<_Property> get_property(
        const basic_resource_ref &__res, _Property) noexcept {
        return __res._Property_vtable<_Property>::__property_fn(__res.__object);
    }
  // clang-format on
};

template <_AllocType _Alloc_type, class... _Properties>
_LIBCUDACXX_INLINE_VAR constexpr bool _Is_basic_resource_ref<basic_resource_ref<_Alloc_type, _Properties...>> = true;

template <class... _Properties> //
using resource_ref = basic_resource_ref<_AllocType::_Default, _Properties...>;

template <class... _Properties> //
using async_resource_ref = basic_resource_ref<_AllocType::_Async, _Properties...>;

/// \struct device_accessible
/// \brief The \c device_accessible property signals that the allocated memory is device accessible
struct device_accessible{};

/// \struct host_accessible
/// \brief The \c host_accessible property signals that the allocated memory is host accessible
struct host_accessible{};

} // namespace mr
_LIBCUDACXX_END_NAMESPACE_CUDA
#endif // _LIBCUDACXX_STD_VER > 11

#include <cuda/std/detail/__pragma_pop>

#endif // LIBCUDACXX_ENABLE_EXPERIMENTAL_MEMORY_RESOURCE

#endif //_LIBCUDACXX_BEGIN_NAMESPACE_CUDA