| FazBrowse GitHub Viewer | Trending | | Home |
| Tools: [Download Repo ZIP] [Original HTTPS Page] |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -84,7 +84,7 @@ of the two expressions while the last one holds a reference on at least one of t | |||
| 84 | 84 | { true, false }}; | |
| 85 | 85 | ||
| 86 | 86 | xoptional_assembly<xarray<double>, xarray<bool>> | |
| 87 | - assembly(v, vh); | ||
| 87 | + assembly(v, hv); | ||
| 88 | 88 | std::cout << assembly << std::endl; | |
| 89 | 89 | ||
| 90 | 90 | outputs: | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -400,6 +400,98 @@ namespace xt | |||
| 400 | 400 | return adapt(std::forward<C>(ptr), xtl::forward_sequence<shape_type, decltype(shape)>(shape)); | |
| 401 | 401 | } | |
| 402 | 402 | #endif | |
| 403 | + | ||
| 404 | + #ifndef X_OLD_CLANG | ||
| 405 | + /** | ||
| 406 | + * Adapt a smart pointer to a typed memory block (unique_ptr or shared_ptr) | ||
| 407 | + * | ||
| 408 | + * \code{.cpp} | ||
| 409 | + * #include <xtensor/xadapt.hpp> | ||
| 410 | + * #include <xtensor/xio.hpp> | ||
| 411 | + * | ||
| 412 | + * std::shared_ptr<double> sptr(new double[8], std::default_delete<double[]>()); | ||
| 413 | + * sptr.get()[2] = 321.; | ||
| 414 | + * auto xptr = adapt_smart_ptr(sptr, {4, 2}); | ||
| 415 | + * xptr(1, 3) = 123.; | ||
| 416 | + * std::cout << xptr; | ||
| 417 | + * \endcode | ||
| 418 | + * | ||
| 419 | + * @param smart_ptr<T[]> a smart pointer to a memory block of T[] | ||
| 420 | + * @param shape The desired shape | ||
| 421 | + * | ||
| 422 | + * @return xtensor_adaptor for memory | ||
| 423 | + */ | ||
| 424 | + template <class P, class I, std::size_t N> | ||
| 425 | + auto adapt_smart_ptr(P&& smart_ptr, const I(&shape)[N]) | ||
| 426 | + { | ||
| 427 | + using buffer_adaptor = xbuffer_adaptor<decltype(smart_ptr.get()), smart_ownership, | ||
| 428 | + std::decay_t<P>>; | ||
| 429 | + std::array<std::size_t, N> fshape = xtl::forward_sequence<std::array<std::size_t, N>, decltype(shape)>(shape); | ||
| 430 | + return xtensor_adaptor<buffer_adaptor, N>( | ||
| 431 | + buffer_adaptor(smart_ptr.get(), compute_size(fshape), | ||
| 432 | + std::forward<P>(smart_ptr)), | ||
| 433 | + std::move(fshape) | ||
| 434 | + ); | ||
| 435 | + } | ||
| 436 | + | ||
| 437 | + /** | ||
| 438 | + * Adapt a smart pointer (shared_ptr or unique_ptr) | ||
| 439 | + * | ||
| 440 | + * This function allows to automatically adapt a shared or unique pointer to | ||
| 441 | + * a given shape and operate naturally on it. Memory will be automatically | ||
| 442 | + * handled by the smart pointer implementation. | ||
| 443 | + * | ||
| 444 | + * \code{.cpp} | ||
| 445 | + * #include <xtensor/xadapt.hpp> | ||
| 446 | + * #include <xtensor/xio.hpp> | ||
| 447 | + * | ||
| 448 | + * struct Buffer { | ||
| 449 | + * Buffer(std::vector<double>& buf) : m_buf(buf) {} | ||
| 450 | + * ~Buffer() { std::cout << "deleted" << std::endl; } | ||
| 451 | + * std::vector<double> m_buf; | ||
| 452 | + * }; | ||
| 453 | + * | ||
| 454 | + * auto data = std::vector<double>{1,2,3,4,5,6,7,8}; | ||
| 455 | + * auto shared_buf = std::make_shared<Buffer>(data); | ||
| 456 | + * auto unique_buf = std::make_unique<Buffer>(data); | ||
| 457 | + * | ||
| 458 | + * std::cout << shared_buf.use_count() << std::endl; | ||
| 459 | + * { | ||
| 460 | + * auto obj = adapt_smart_ptr(shared_buf.get()->buf.data(), | ||
| 461 | + * {2, 4}, shared_buf); | ||
| 462 | + * // Use count increased to 2 | ||
| 463 | + * std::cout << shared_buf.use_count() << std::endl; | ||
| 464 | + * std::cout << obj << std::endl; | ||
| 465 | + * } | ||
| 466 | + * // Use count reset to 1 | ||
| 467 | + * std::cout << shared_buf.use_count() << std::endl; | ||
| 468 | + * | ||
| 469 | + * { | ||
| 470 | + * auto obj = adapt_smart_ptr(unique_buf.get()->buf.data(), | ||
| 471 | + * {2, 4}, std::move(unique_buf)); | ||
| 472 | + * std::cout << obj << std::endl; | ||
| 473 | + * } | ||
| 474 | + * \endcode | ||
| 475 | + * | ||
| 476 | + * @param A pointer to a typed data block (e.g. double*) | ||
| 477 | + * @param shape The desired shape | ||
| 478 | + * @param A smart pointer to move or copy, in order to manage memory | ||
| 479 | + * | ||
| 480 | + * @return xtensor_adaptor on the memory | ||
| 481 | + */ | ||
| 482 | + template <class P, class I, std::size_t N, class D> | ||
| 483 | + auto adapt_smart_ptr(P&& data_ptr, const I(&shape)[N], D&& smart_ptr) | ||
| 484 | + { | ||
| 485 | + using buffer_adaptor = xbuffer_adaptor<P, smart_ownership, | ||
| 486 | + std::decay_t<D>>; | ||
| 487 | + std::array<std::size_t, N> fshape = xtl::forward_sequence<std::array<std::size_t, N>, decltype(shape)>(shape); | ||
| 488 | + | ||
| 489 | + return xtensor_adaptor<buffer_adaptor, N>( | ||
| 490 | + buffer_adaptor(data_ptr, compute_size(fshape), std::forward<D>(smart_ptr)), | ||
| 491 | + std::move(fshape) | ||
| 492 | + ); | ||
| 493 | + } | ||
| 494 | + #endif | ||
| 403 | 495 | } | |
| 404 | 496 | ||
| 405 | 497 | #endif | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -29,6 +29,8 @@ namespace xt | |||
| 29 | 29 | { | |
| 30 | 30 | }; | |
| 31 | 31 | ||
| 32 | + using smart_ownership = no_ownership; | ||
| 33 | + | ||
| 32 | 34 | struct acquire_ownership | |
| 33 | 35 | { | |
| 34 | 36 | }; | |
@@ -49,6 +51,7 @@ namespace xt | |||
| 49 | 51 | ||
| 50 | 52 | using self_type = xbuffer_storage<CP, A>; | |
| 51 | 53 | using allocator_type = A; | |
| 54 | + using destructor_type = allocator_type; | ||
| 52 | 55 | using value_type = typename allocator_type::value_type; | |
| 53 | 56 | using reference = std::conditional_t<std::is_const<std::remove_pointer_t<std::remove_reference_t<CP>>>::value, | |
| 54 | 57 | typename allocator_type::const_reference, | |
@@ -80,13 +83,54 @@ namespace xt | |||
| 80 | 83 | size_type m_size; | |
| 81 | 84 | }; | |
| 82 | 85 | ||
| 86 | + template <class CP, class D> | ||
| 87 | + class xbuffer_smart_pointer | ||
| 88 | + { | ||
| 89 | + public: | ||
| 90 | + | ||
| 91 | + using self_type = xbuffer_storage<CP, D>; | ||
| 92 | + using destructor_type = D; | ||
| 93 | + using value_type = std::remove_const_t<std::remove_pointer_t<std::remove_reference_t<CP>>>; | ||
| 94 | + using allocator_type = std::allocator<value_type>; | ||
| 95 | + using reference = std::conditional_t<std::is_const<std::remove_pointer_t<std::remove_reference_t<CP>>>::value, | ||
| 96 | + typename allocator_type::const_reference, | ||
| 97 | + typename allocator_type::reference>; | ||
| 98 | + using const_reference = typename allocator_type::const_reference; | ||
| 99 | + using pointer = std::conditional_t<std::is_const<std::remove_pointer_t<std::remove_reference_t<CP>>>::value, | ||
| 100 | + typename allocator_type::const_pointer, | ||
| 101 | + typename allocator_type::pointer>; | ||
| 102 | + using const_pointer = typename allocator_type::const_pointer; | ||
| 103 | + using size_type = typename allocator_type::size_type; | ||
| 104 | + using difference_type = typename allocator_type::difference_type; | ||
| 105 | + | ||
| 106 | + xbuffer_smart_pointer(); | ||
| 107 | + | ||
| 108 | + template <class P, class DT> | ||
| 109 | + xbuffer_smart_pointer(P&& data_ptr, size_type size, DT&& destruct); | ||
| 110 | + | ||
| 111 | + size_type size() const noexcept; | ||
| 112 | + void resize(size_type size); | ||
| 113 | + | ||
| 114 | + pointer data() noexcept; | ||
| 115 | + const_pointer data() const noexcept; | ||
| 116 | + | ||
| 117 | + void swap(self_type& rhs) noexcept; | ||
| 118 | + | ||
| 119 | + private: | ||
| 120 | + | ||
| 121 | + pointer p_data; | ||
| 122 | + size_type m_size; | ||
| 123 | + destructor_type m_destruct; | ||
| 124 | + }; | ||
| 125 | + | ||
| 83 | 126 | template <class CP, class A> | |
| 84 | 127 | class xbuffer_owner_storage | |
| 85 | 128 | { | |
| 86 | 129 | public: | |
| 87 | 130 | ||
| 88 | 131 | using self_type = xbuffer_owner_storage<CP, A>; | |
| 89 | 132 | using allocator_type = A; | |
| 133 | + using destructor_type = allocator_type; | ||
| 90 | 134 | using value_type = typename allocator_type::value_type; | |
| 91 | 135 | using reference = std::conditional_t<std::is_const<std::remove_pointer_t<std::remove_reference_t<CP>>>::value, | |
| 92 | 136 | typename allocator_type::const_reference, | |
@@ -130,10 +174,24 @@ namespace xt | |||
| 130 | 174 | allocator_type m_allocator; | |
| 131 | 175 | }; | |
| 132 | 176 | ||
| 177 | + template <class E, class = void> | ||
| 178 | + struct is_lambda_type : std::false_type | ||
| 179 | + { | ||
| 180 | + }; | ||
| 181 | + | ||
| 182 | + // check if operator() is available | ||
| 183 | + template <class E> | ||
| 184 | + struct is_lambda_type<E, void_t<decltype(&E::operator())>> | ||
| 185 | + : std::true_type | ||
| 186 | + { | ||
| 187 | + }; | ||
| 188 | + | ||
| 133 | 189 | template <class CP, class A, class O> | |
| 134 | 190 | struct get_buffer_storage | |
| 135 | 191 | { | |
| 136 | - using type = xbuffer_storage<CP, A>; | ||
| 192 | + using type = xtl::mpl::eval_if_t<is_lambda_type<A>, | ||
| 193 | + meta_identity<xbuffer_smart_pointer<CP, A>>, | ||
| 194 | + meta_identity<xbuffer_storage<CP, A>>>; | ||
| 137 | 195 | }; | |
| 138 | 196 | ||
| 139 | 197 | template <class CP, class A> | |
@@ -142,6 +200,18 @@ namespace xt | |||
| 142 | 200 | using type = xbuffer_owner_storage<CP, A>; | |
| 143 | 201 | }; | |
| 144 | 202 | ||
| 203 | + template <class CP, class T> | ||
| 204 | + struct get_buffer_storage<CP, std::shared_ptr<T>, no_ownership> | ||
| 205 | + { | ||
| 206 | + using type = xbuffer_smart_pointer<CP, std::shared_ptr<T>>; | ||
| 207 | + }; | ||
| 208 | + | ||
| 209 | + template <class CP, class T> | ||
| 210 | + struct get_buffer_storage<CP, std::unique_ptr<T>, no_ownership> | ||
| 211 | + { | ||
| 212 | + using type = xbuffer_smart_pointer<CP, std::unique_ptr<T>>; | ||
| 213 | + }; | ||
| 214 | + | ||
| 145 | 215 | template <class CP, class A, class O> | |
| 146 | 216 | using buffer_storage_t = typename get_buffer_storage<CP, A, O>::type; | |
| 147 | 217 | } | |
@@ -154,6 +224,7 @@ namespace xt | |||
| 154 | 224 | using base_type = detail::buffer_storage_t<CP, A, O>; | |
| 155 | 225 | using self_type = xbuffer_adaptor<CP, O, A>; | |
| 156 | 226 | using allocator_type = typename base_type::allocator_type; | |
| 227 | + using destructor_type = typename base_type::destructor_type; | ||
| 157 | 228 | using value_type = typename base_type::value_type; | |
| 158 | 229 | using reference = typename base_type::reference; | |
| 159 | 230 | using const_reference = typename base_type::const_reference; | |
@@ -171,8 +242,8 @@ namespace xt | |||
| 171 | 242 | ||
| 172 | 243 | xbuffer_adaptor() = default; | |
| 173 | 244 | ||
| 174 | - template <class P> | ||
| 175 | - xbuffer_adaptor(P&& data, size_type size, const allocator_type& alloc = allocator_type()); | ||
| 245 | + template <class P, class AT = allocator_type> | ||
| 246 | + xbuffer_adaptor(P&& data, size_type size, AT&& alloc = allocator_type()); | ||
| 176 | 247 | ||
| 177 | 248 | ~xbuffer_adaptor() = default; | |
| 178 | 249 | ||
@@ -428,14 +499,63 @@ namespace xt | |||
| 428 | 499 | } | |
| 429 | 500 | } | |
| 430 | 501 | ||
| 502 | + /**************************************** | ||
| 503 | + * xbuffer_smart_pointer implementation * | ||
| 504 | + ****************************************/ | ||
| 505 | + | ||
| 506 | + namespace detail | ||
| 507 | + { | ||
| 508 | + template <class CP, class D> | ||
| 509 | + template <class P, class DT> | ||
| 510 | + xbuffer_smart_pointer<CP, D>::xbuffer_smart_pointer(P&& data_ptr, size_type size, DT&& destruct) | ||
| 511 | + : p_data(data_ptr), m_size(size), m_destruct(std::forward<DT>(destruct)) | ||
| 512 | + { | ||
| 513 | + } | ||
| 514 | + | ||
| 515 | + template <class CP, class D> | ||
| 516 | + auto xbuffer_smart_pointer<CP, D>::size() const noexcept -> size_type | ||
| 517 | + { | ||
| 518 | + return m_size; | ||
| 519 | + } | ||
| 520 | + | ||
| 521 | + template <class CP, class D> | ||
| 522 | + void xbuffer_smart_pointer<CP, D>::resize(size_type size) | ||
| 523 | + { | ||
| 524 | + if (m_size != size) | ||
| 525 | + { | ||
| 526 | + throw std::runtime_error("xbuffer_storage not resizable"); | ||
| 527 | + } | ||
| 528 | + } | ||
| 529 | + | ||
| 530 | + template <class CP, class D> | ||
| 531 | + auto xbuffer_smart_pointer<CP, D>::data() noexcept -> pointer | ||
| 532 | + { | ||
| 533 | + return p_data; | ||
| 534 | + } | ||
| 535 | + template <class CP, class D> | ||
| 536 | + auto xbuffer_smart_pointer<CP, D>::data() const noexcept -> const_pointer | ||
| 537 | + { | ||
| 538 | + return p_data; | ||
| 539 | + } | ||
| 540 | + | ||
| 541 | + template <class CP, class D> | ||
| 542 | + void xbuffer_smart_pointer<CP, D>::swap(self_type& rhs) noexcept | ||
| 543 | + { | ||
| 544 | + using std::swap; | ||
| 545 | + swap(p_data, rhs.p_data); | ||
| 546 | + swap(m_size, rhs.m_size); | ||
| 547 | + swap(m_destruct, rhs.m_destruct); | ||
| 548 | + } | ||
| 549 | + } | ||
| 550 | + | ||
| 431 | 551 | /********************************** | |
| 432 | 552 | * xbuffer_adaptor implementation * | |
| 433 | 553 | **********************************/ | |
| 434 | 554 | ||
| 435 | 555 | template <class CP, class O, class A> | |
| 436 | - template <class P> | ||
| 437 | - inline xbuffer_adaptor<CP, O, A>::xbuffer_adaptor(P&& data, size_type size, const allocator_type& alloc) | ||
| 438 | - : base_type(std::forward<P>(data), size, alloc) | ||
| 556 | + template <class P, class AT> | ||
| 557 | + inline xbuffer_adaptor<CP, O, A>::xbuffer_adaptor(P&& data, size_type size, AT&& alloc) | ||
| 558 | + : base_type(std::forward<P>(data), size, std::forward<AT>(alloc)) | ||
| 439 | 559 | { | |
| 440 | 560 | } | |
| 441 | 561 | ||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -39,6 +39,12 @@ namespace xt | |||
| 39 | 39 | ||
| 40 | 40 | namespace detail | |
| 41 | 41 | { | |
| 42 | + // need to have a copy of meta_identity here for MSVC | ||
| 43 | + template <class T> | ||
| 44 | + struct meta_identity | ||
| 45 | + { | ||
| 46 | + using type = T; | ||
| 47 | + }; | ||
| 42 | 48 | ||
| 43 | 49 | /******************** | |
| 44 | 50 | * common_size_type * | |
@@ -134,12 +140,6 @@ namespace xt | |||
| 134 | 140 | { | |
| 135 | 141 | }; | |
| 136 | 142 | ||
| 137 | - template <class T> | ||
| 138 | - struct meta_identity | ||
| 139 | - { | ||
| 140 | - using type = T; | ||
| 141 | - }; | ||
| 142 | - | ||
| 143 | 143 | // This meta struct checks wether SIMD should be activated for our | |
| 144 | 144 | // functor "F" | |
| 145 | 145 | template <class V, class F, class... CT> | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -113,6 +113,16 @@ namespace xt | |||
| 113 | 113 | template <class T, class R> | |
| 114 | 114 | using disable_integral_t = std::enable_if_t<!std::is_integral<T>::value, R>; | |
| 115 | 115 | ||
| 116 | + /******************************** | ||
| 117 | + * meta identity implementation * | ||
| 118 | + ********************************/ | ||
| 119 | + | ||
| 120 | + template <class T> | ||
| 121 | + struct meta_identity | ||
| 122 | + { | ||
| 123 | + using type = T; | ||
| 124 | + }; | ||
| 125 | + | ||
| 116 | 126 | /******************************* | |
| 117 | 127 | * remove_class implementation * | |
| 118 | 128 | *******************************/ | |
| Back | FazBrowse Home | New Git URL |
0 commit comments