FazBrowse GitHub Viewer | Trending |
URL:
| Home
Tools: [Download Repo ZIP]   [Original HTTPS Page]

add smart pointer adaptor · xtensor-stack/xtensor@4be0861 · GitHub

Repository navigation

Commit 4be0861

Browse files
committed
add smart pointer adaptor
1 parent edfafe7 commit 4be0861

7 files changed

Lines changed: 285 additions & 16 deletions

File tree

‎docs/source/missing.rst‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -84,7 +84,7 @@ of the two expressions while the last one holds a reference on at least one of t
8484
{ true, false }};
8585
8686
xoptional_assembly<xarray<double>, xarray<bool>>
87-
assembly(v, vh);
87+
assembly(v, hv);
8888
std::cout << assembly << std::endl;
8989
9090
outputs:

‎include/xtensor/xadapt.hpp‎

Lines changed: 92 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -400,6 +400,98 @@ namespace xt
400400
return adapt(std::forward<C>(ptr), xtl::forward_sequence<shape_type, decltype(shape)>(shape));
401401
}
402402
#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
403495
}
404496

405497
#endif

‎include/xtensor/xbuffer_adaptor.hpp‎

Lines changed: 126 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,8 @@ namespace xt
2929
{
3030
};
3131

32+
using smart_ownership = no_ownership;
33+
3234
struct acquire_ownership
3335
{
3436
};
@@ -49,6 +51,7 @@ namespace xt
4951

5052
using self_type = xbuffer_storage<CP, A>;
5153
using allocator_type = A;
54+
using destructor_type = allocator_type;
5255
using value_type = typename allocator_type::value_type;
5356
using reference = std::conditional_t<std::is_const<std::remove_pointer_t<std::remove_reference_t<CP>>>::value,
5457
typename allocator_type::const_reference,
@@ -80,13 +83,54 @@ namespace xt
8083
size_type m_size;
8184
};
8285

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+
83126
template <class CP, class A>
84127
class xbuffer_owner_storage
85128
{
86129
public:
87130

88131
using self_type = xbuffer_owner_storage<CP, A>;
89132
using allocator_type = A;
133+
using destructor_type = allocator_type;
90134
using value_type = typename allocator_type::value_type;
91135
using reference = std::conditional_t<std::is_const<std::remove_pointer_t<std::remove_reference_t<CP>>>::value,
92136
typename allocator_type::const_reference,
@@ -130,10 +174,24 @@ namespace xt
130174
allocator_type m_allocator;
131175
};
132176

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+
133189
template <class CP, class A, class O>
134190
struct get_buffer_storage
135191
{
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>>>;
137195
};
138196

139197
template <class CP, class A>
@@ -142,6 +200,18 @@ namespace xt
142200
using type = xbuffer_owner_storage<CP, A>;
143201
};
144202

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+
145215
template <class CP, class A, class O>
146216
using buffer_storage_t = typename get_buffer_storage<CP, A, O>::type;
147217
}
@@ -154,6 +224,7 @@ namespace xt
154224
using base_type = detail::buffer_storage_t<CP, A, O>;
155225
using self_type = xbuffer_adaptor<CP, O, A>;
156226
using allocator_type = typename base_type::allocator_type;
227+
using destructor_type = typename base_type::destructor_type;
157228
using value_type = typename base_type::value_type;
158229
using reference = typename base_type::reference;
159230
using const_reference = typename base_type::const_reference;
@@ -171,8 +242,8 @@ namespace xt
171242

172243
xbuffer_adaptor() = default;
173244

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());
176247

177248
~xbuffer_adaptor() = default;
178249

@@ -428,14 +499,63 @@ namespace xt
428499
}
429500
}
430501

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+
431551
/**********************************
432552
* xbuffer_adaptor implementation *
433553
**********************************/
434554

435555
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))
439559
{
440560
}
441561

‎include/xtensor/xfunction.hpp‎

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,12 @@ namespace xt
3939

4040
namespace detail
4141
{
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+
};
4248

4349
/********************
4450
* common_size_type *
@@ -134,12 +140,6 @@ namespace xt
134140
{
135141
};
136142

137-
template <class T>
138-
struct meta_identity
139-
{
140-
using type = T;
141-
};
142-
143143
// This meta struct checks wether SIMD should be activated for our
144144
// functor "F"
145145
template <class V, class F, class... CT>

‎include/xtensor/xutils.hpp‎

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -113,6 +113,16 @@ namespace xt
113113
template <class T, class R>
114114
using disable_integral_t = std::enable_if_t<!std::is_integral<T>::value, R>;
115115

116+
/********************************
117+
* meta identity implementation *
118+
********************************/
119+
120+
template <class T>
121+
struct meta_identity
122+
{
123+
using type = T;
124+
};
125+
116126
/*******************************
117127
* remove_class implementation *
118128
*******************************/

0 commit comments

Comments
 (0)

Back | FazBrowse Home | New Git URL