From 20d4f4c5cabcdc636c439f3bd4e9e6ac6f68973b Mon Sep 17 00:00:00 2001 From: Ilya Yaroshenko Date: Mon, 3 Jun 2019 16:47:28 +0700 Subject: [PATCH 1/6] update C++ headers (#195) --- cpp_example/main.cpp | 22 ++++----- include/mir/ndslice.h | 16 ++++--- include/mir/rcarray.h | 103 ++++++++++++++++++++++-------------------- include/mir/rcptr.h | 84 +++++++++++++++++++++++++++------- include/mir/series.h | 92 +++++++++++++++++++------------------ 5 files changed, 187 insertions(+), 130 deletions(-) diff --git a/cpp_example/main.cpp b/cpp_example/main.cpp index d41e9668..841dc8c9 100644 --- a/cpp_example/main.cpp +++ b/cpp_example/main.cpp @@ -112,7 +112,7 @@ void testSeries() map[5] = 10.0; map[10] = 11.0; - auto series = mir_make_series(map); + auto series = mir::make_series(map); assert(series[1].first == 2); assert(series[1].second == 5); @@ -165,8 +165,8 @@ struct C : S { double j = 3; C(double d, double k) : S(d) { k = j; }; }; void testRCPtr() { - auto s = mir_make_shared(3.0); - auto e = mir_make_shared(5.0); + auto s = mir::make_shared(3.0); + auto e = mir::make_shared(5.0); s = e; (*e).d = 4; assert(s->d == 4); @@ -177,7 +177,7 @@ void testRCPtr() void testPM() { - auto c = mir_make_shared(3.0, 4); + auto c = mir::make_shared(3.0, 4); assert(c.getContext()->counter == 1); auto s = mir_rcptr(c); assert(c.getContext()->counter == 2); @@ -200,13 +200,13 @@ void testFindRoot() void testStringView() { auto ref = std::string_view("Hi"); - auto b = mir_rcarray_from_string(ref); - mir_rcarray c = mir_rcarray_from_string(std::string("Hi")); - mir_rcarray d = mir_rcarray_from_string("Hi"); - assert(ref == mir_get_string_view(b)); - assert(ref == mir_get_string_view(c)); - assert(ref == mir_get_string_view(d)); - assert(typeid((mir_get_string_view(c))) == typeid((mir_get_string_view(d)))); + auto b = mir::rcarray_from_string(ref); + mir_rcarray c = mir::rcarray_from_string(std::string("Hi")); + mir_rcarray d = mir::rcarray_from_string("Hi"); + assert(ref == mir::get_string_view(b)); + assert(ref == mir::get_string_view(c)); + assert(ref == mir::get_string_view(d)); + assert(typeid((mir::get_string_view(c))) == typeid((mir::get_string_view(d)))); ref = c; // implicit conversion ref = d; // implicit conversion } diff --git a/include/mir/ndslice.h b/include/mir/ndslice.h index ec446491..96d70d9d 100644 --- a/include/mir/ndslice.h +++ b/include/mir/ndslice.h @@ -309,12 +309,14 @@ struct mir_slice } }; -template < - typename T, - mir_size_t N, - mir_slice_kind kind -> -mir_slice mir_light_const(const mir_slice s) { return *(mir_slice*)&s; } - +namespace mir +{ + template < + typename T, + mir_size_t N, + mir_slice_kind kind + > + mir_slice light_const(const mir_slice s) { return *(mir_slice*)&s; } +} #endif diff --git a/include/mir/rcarray.h b/include/mir/rcarray.h index 62755153..11ad879e 100644 --- a/include/mir/rcarray.h +++ b/include/mir/rcarray.h @@ -27,7 +27,7 @@ struct mir_rcarray T* _payload = nullptr; using U = typename std::remove_all_extents::type; static constexpr void (*destr)(U&) = std::is_destructible::value ? &mir::Destructor::destroy : nullptr; - static constexpr mir_type_info_g typeInfoT = {destr, sizeof(T)}; + static constexpr mir::type_info_g typeInfoT = {destr, sizeof(T)}; void _cpp_copy_constructor(const mir_rcarray& rhs) noexcept; mir_rcarray& _cpp_assign(const mir_rcarray& rhs) noexcept; @@ -149,7 +149,7 @@ struct mir_rcarray template::value>::type> operator std::basic_string_view() const noexcept { - return mir_get_string_view(*this); + return std::basic_string_view(data(), size()); } mir_rcarray light_const() const noexcept { return *(mir_rcarray*)this; } @@ -304,61 +304,64 @@ struct mir_rci bool operator<=(const mir_rci& rhs) const { return _iterator <= rhs._iterator; } }; -template < - typename T, - mir_size_t N, - mir_slice_kind kind -> -mir_slice, N, kind> mir_light_const(const mir_slice, N, kind>& s) { return *(mir_slice, N, kind>*)&s; } - -template< - class CharT, - class Traits -> -mir_rcarray mir_rcarray_from_string(std::basic_string_view str) +namespace mir { - mir_rcarray ret; - size_t length = str.size(); - if (length != 0) + template < + typename T, + mir_size_t N, + mir_slice_kind kind + > + mir_slice, N, kind> light_const(const mir_slice, N, kind>& s) { return *(mir_slice, N, kind>*)&s; } + + template< + class CharT, + class Traits + > + mir_rcarray rcarray_from_string(std::basic_string_view str) { - ret = mir_rcarray(length, false); - std::memcpy(ret.data(), str.data(), length); + mir_rcarray ret; + size_t length = str.size(); + if (length != 0) + { + ret = mir_rcarray(length, false); + std::memcpy(ret.data(), str.data(), length); + } + return ret; } - return ret; -} -template< - class CharT -> -mir_rcarray mir_rcarray_from_string(const CharT* str) -{ - return mir_rcarray_from_string(std::basic_string_view(str)); -} + template< + class CharT + > + mir_rcarray rcarray_from_string(const CharT* str) + { + return rcarray_from_string(std::basic_string_view(str)); + } -template< - class CharT, - class Traits, - class Allocator -> -mir_rcarray mir_rcarray_from_string(const std::basic_string& str) -{ - return mir_rcarray_from_string((std::basic_string_view)str); -} + template< + class CharT, + class Traits, + class Allocator + > + mir_rcarray rcarray_from_string(const std::basic_string& str) + { + return rcarray_from_string((std::basic_string_view)str); + } -template< - class CharT -> -std::basic_string_view mir_get_string_view(mir_rcarray str) -{ - return std::basic_string_view(str.data(), str.size()); -} + template< + class CharT + > + std::basic_string_view get_string_view(const mir_rcarray& str) + { + return std::basic_string_view(str.data(), str.size()); + } -template< - class CharT -> -std::basic_string_view mir_get_string_view(mir_rcarray str) -{ - return std::basic_string_view(str.data(), str.size()); + template< + class CharT + > + std::basic_string_view get_string_view(const mir_rcarray& str) + { + return std::basic_string_view(str.data(), str.size()); + } } #endif diff --git a/include/mir/rcptr.h b/include/mir/rcptr.h index 3f0ab6c0..3cc52e75 100644 --- a/include/mir/rcptr.h +++ b/include/mir/rcptr.h @@ -9,13 +9,6 @@ #include #include -template -struct mir_type_info_g -{ - void (*destructor)(T&); - int size; -}; - struct mir_type_info { void (*destructor)(void*); @@ -46,6 +39,13 @@ extern "C" } namespace mir { + template + struct type_info_g + { + void (*destructor)(T&); + int size; + }; + template::value> struct Destructor { @@ -84,22 +84,25 @@ struct mir_rcptr mir_rc_context* _context = nullptr; using U = typename std::remove_all_extents::type; static constexpr void (*destr)(U&) = std::is_destructible::value ? &mir::Destructor::destroy : nullptr; - static constexpr mir_type_info_g typeInfoT = {destr, sizeof(T)}; + static constexpr mir::type_info_g typeInfoT = {destr, sizeof(T)}; public: + using element_type = T; + mir_rcptr() noexcept {} mir_rcptr(std::nullptr_t) noexcept {} + mir_rcptr(const mir_rc_context* context, T* payload) noexcept : _payload(payload), _context((mir_rc_context*)context) { if (_context) mir_rc_increase_counter(_context); } ~mir_rcptr() noexcept { if (_context) mir_rc_decrease_counter(_context); } - mir_rcptr(const mir_rcptr& rhs) noexcept : _payload(rhs._payload), _context((mir_rc_context*)rhs._context) { if (_context) mir_rc_increase_counter(_context); } - mir_rcptr(mir_rcptr&& rhs) noexcept : _payload(rhs._payload), _context(rhs._context) { rhs.__reset(); } + mir_rcptr(const mir_rcptr& rhs) noexcept : _payload(rhs._payload), _context((mir_rc_context*)rhs.getContext()) { if (_context) mir_rc_increase_counter(_context); } + mir_rcptr(mir_rcptr&& rhs) noexcept : _payload(rhs._payload), _context(rhs.getContext()) { rhs.__reset(); } mir_rcptr& operator=(const mir_rcptr& rhs) noexcept { if (_payload != rhs._payload) { if (_context) mir_rc_decrease_counter(_context); _payload = (T*) rhs._payload; - _context = (mir_rc_context*) rhs._context; + _context = (mir_rc_context*) rhs.getContext(); if (_context) mir_rc_increase_counter(_context);; } return *this; @@ -115,7 +118,7 @@ struct mir_rcptr if (ret._context == nullptr) throw std::bad_alloc(); ret._payload = (T*)(ret._context + 1); - ::new(ret.get()) U(std::forward(args)...); + ::new((U*)ret._payload) U(std::forward(args)...); return ret; } @@ -129,7 +132,7 @@ struct mir_rcptr { if (_context) mir_rc_decrease_counter(_context); _payload = rhsv; - _context = (mir_rc_context*) rhs._context; + _context = (mir_rc_context*) rhs.getContext(); if (_context) mir_rc_increase_counter(_context); } return *this; @@ -149,12 +152,23 @@ struct mir_rcptr mir_rcptr light_const() const noexcept { return *(mir_rcptr*)this; } + template + Q* get() + { + if (_payload == nullptr) + return nullptr; + auto ret = dynamic_cast(_payload); + if (ret != nullptr) + return ret; + throw std::bad_cast(); + } + template Q* get() const { if (_payload == nullptr) return nullptr; - auto ret = dynamic_cast((T*)_payload); + auto ret = dynamic_cast(_payload); if (ret != nullptr) return ret; throw std::bad_cast(); @@ -164,6 +178,8 @@ struct mir_rcptr mir_rcptr& operator=(std::nullptr_t) noexcept { if (_context) mir_rc_decrease_counter(_context); __reset(); return *this; } T& operator*() noexcept { assert(_payload != nullptr); return *_payload; } T* operator->() noexcept { assert(_payload != nullptr); return _payload; } + T* get() noexcept { return _payload; } + const T* get() const noexcept { return _payload; } const mir_rc_context* getContext() const noexcept { return _context; } const T& operator*() const noexcept { assert(_payload != nullptr); return *_payload; } const T* operator->() const noexcept { assert(_payload != nullptr); return _payload; } @@ -176,10 +192,44 @@ struct mir_rcptr explicit operator bool() const noexcept { return _payload != nullptr; } }; -template -mir_rcptr mir_make_shared(Args&& ...args) +namespace mir { - return mir_rcptr::make_shared(std::forward(args)...); + template + mir_rcptr make_shared(Args&& ...args) + { + return mir_rcptr::make_shared(std::forward(args)...); + } + + template< class T, class U > + mir_rcptr static_pointer_cast( const mir_rcptr& r ) noexcept + { + auto p = static_cast::element_type*>(r.get()); + return mir_rcptr(r.getContext(), p); + } + + template< class T, class U > + mir_rcptr dynamic_pointer_cast( const mir_rcptr& r ) noexcept + { + if (auto p = dynamic_cast::element_type*>(r.get())) { + return mir_rcptr(r.getContext(), p); + } else { + return mir_rcptr(); + } + } + + template< class T, class U > + mir_rcptr const_pointer_cast( const mir_rcptr& r ) noexcept + { + auto p = const_cast::element_type*>(r.get()); + return mir_rcptr(r.getContext(), p); + } + + template< class T, class U > + mir_rcptr reinterpret_pointer_cast( const mir_rcptr& r ) noexcept + { + auto p = reinterpret_cast::element_type*>(r.get()); + return mir_rcptr(r.getContext(), p); + } } namespace std diff --git a/include/mir/series.h b/include/mir/series.h index 4731f0b0..2d915d7c 100644 --- a/include/mir/series.h +++ b/include/mir/series.h @@ -275,55 +275,57 @@ struct mir_series ThisIterator cend() const noexcept { return {_data.size(), *this}; } }; -// don't sort -template < - typename IndexIterator, - typename Iterator, - mir_size_t N = 1, - mir_slice_kind kind = mir_slice_kind::contiguous -> -mir_series - mir_make_series(mir_slice index, mir_slice data) +namespace mir { - assert(data._lengths[0] == index._lengths[0]); - return { data, index._iterator }; -} - -template< - class Key, - class Value, - class Allocator -> -mir_series,mir_rci> - mir_make_series(const std::map, Allocator>& map) -{ - auto index = mir_rcarray(map.size()).asSlice(); - auto data = mir_rcarray(map.size()).asSlice(); - size_t i = 0; - for (const auto&[key, value] : map) + // don't sort + template < + typename IndexIterator, + typename Iterator, + mir_size_t N = 1, + mir_slice_kind kind = mir_slice_kind::contiguous + > + mir_series + make_series(mir_slice index, mir_slice data) { - index[i] = key; - data[i] = value; - i++; + assert(data._lengths[0] == index._lengths[0]); + return { data, index._iterator }; } - return mir_make_series(index, data); -} -template < - typename I, - typename T, - mir_size_t N, - mir_slice_kind kind -> -mir_series mir_light_const(const mir_series s) { return *(mir_series*)&s; } - -template < - typename I, - typename T, - mir_size_t N, - mir_slice_kind kind -> -mir_series, mir_rci, N, kind> mir_light_const(const mir_series, mir_rci, N, kind> s) { return *(mir_series, mir_rci, N, kind>*)&s; } + template< + class Key, + class Value, + class Allocator + > + mir_series,mir_rci> + make_series(const std::map, Allocator>& map) + { + auto index = mir_rcarray(map.size()).asSlice(); + auto data = mir_rcarray(map.size()).asSlice(); + size_t i = 0; + for (const auto&[key, value] : map) + { + index[i] = key; + data[i] = value; + i++; + } + return make_series(index, data); + } + template < + typename I, + typename T, + mir_size_t N, + mir_slice_kind kind + > + mir_series light_const(const mir_series s) { return *(mir_series*)&s; } + + template < + typename I, + typename T, + mir_size_t N, + mir_slice_kind kind + > + mir_series, mir_rci, N, kind> light_const(const mir_series, mir_rci, N, kind> s) { return *(mir_series, mir_rci, N, kind>*)&s; } +} #endif From 50a42dfe7ac7ffd6449efb76e285571eb6acc13a Mon Sep 17 00:00:00 2001 From: Ilya Yaroshenko Date: Thu, 6 Jun 2019 08:24:36 +0700 Subject: [PATCH 2/6] rework rcarray (#196) --- include/mir/rcptr.h | 235 ++++++++++++++++++++++++++++++++++++++++ source/mir/rc/array.d | 27 +++++ source/mir/rc/context.d | 27 ----- source/mir/rc/ptr.d | 168 ++++++++++++++++------------ 4 files changed, 359 insertions(+), 98 deletions(-) diff --git a/include/mir/rcptr.h b/include/mir/rcptr.h index 3cc52e75..e5a18e0f 100644 --- a/include/mir/rcptr.h +++ b/include/mir/rcptr.h @@ -192,6 +192,241 @@ struct mir_rcptr explicit operator bool() const noexcept { return _payload != nullptr; } }; +// Does not support allocators for now +template +struct mir_rcptr +{ +private: + + T* _payload = nullptr; + mir_rc_context* _context = nullptr; + using U = typename std::remove_all_extents::type; + static constexpr void (*destr)(U&) = std::is_destructible::value ? &mir::Destructor::destroy : nullptr; + static constexpr mir::type_info_g typeInfoT = {destr, sizeof(T)}; + +public: + + using element_type = T; + + mir_rcptr() noexcept {} + mir_rcptr(std::nullptr_t) noexcept {} + mir_rcptr(const mir_rc_context* context, T* payload) noexcept : _payload(payload), _context((mir_rc_context*)context) { if (_context) mir_rc_increase_counter(_context); } + ~mir_rcptr() noexcept { if (_context) mir_rc_decrease_counter(_context); } + mir_rcptr(const mir_rcptr& rhs) noexcept : _payload(rhs._payload), _context((mir_rc_context*)rhs.getContext()) { if (_context) mir_rc_increase_counter(_context); } + mir_rcptr(mir_rcptr&& rhs) noexcept : _payload(rhs._payload), _context(rhs.getContext()) { rhs.__reset(); } + mir_rcptr& operator=(const mir_rcptr& rhs) noexcept + { + if (_payload != rhs._payload) + { + if (_context) mir_rc_decrease_counter(_context); + _payload = (T*) rhs._payload; + _context = (mir_rc_context*) rhs.getContext(); + if (_context) mir_rc_increase_counter(_context);; + } + return *this; + } + + template + static mir_rcptr make_shared(Args&& ...args) + { + using U = typename std::remove_const::type; + static_assert( std::is_constructible::value, "Can't construct object in mir_rcptr constructor" ); + mir_rcptr ret; + ret._context = mir_rc_create((const mir_type_info*)&typeInfoT, 1); + if (ret._context == nullptr) + throw std::bad_alloc(); + ret._payload = (T*)(ret._context + 1); + ::new((U*)ret._payload) U(std::forward(args)...); + return ret; + } + + void __reset() { _payload = nullptr; _context = nullptr; } + + template::value>::type> + mir_rcptr& operator=(const mir_rcptr& rhs) noexcept + { + auto rhsv = rhs.template get(); + if (_payload != rhsv) + { + if (_context) mir_rc_decrease_counter(_context); + _payload = rhsv; + _context = (mir_rc_context*) rhs.getContext(); + if (_context) mir_rc_increase_counter(_context); + } + return *this; + } + + template::value>::type> + mir_rcptr(const mir_rcptr& rhs) noexcept : _payload(rhs.template get()), _context((mir_rc_context*)rhs.getContext()) + { + if (_context) mir_rc_increase_counter(_context); + } + + template::value>::type> + mir_rcptr(mir_rcptr&& rhs) noexcept : _payload(rhs.template get()), _context(rhs.getContext()) + { + rhs.__reset(); + } + + mir_rcptr light_const() const noexcept { return *(mir_rcptr*)this; } + + template + Q* get() + { + if (_payload == nullptr) + return nullptr; + auto ret = dynamic_cast(_payload); + if (ret != nullptr) + return ret; + throw std::bad_cast(); + } + + template + Q* get() const + { + if (_payload == nullptr) + return nullptr; + auto ret = dynamic_cast(_payload); + if (ret != nullptr) + return ret; + throw std::bad_cast(); + } + + mir_rc_context* getContext() noexcept { return _context; } + mir_rcptr& operator=(std::nullptr_t) noexcept { if (_context) mir_rc_decrease_counter(_context); __reset(); return *this; } + T& operator*() noexcept { assert(_payload != nullptr); return *_payload; } + T* operator->() noexcept { assert(_payload != nullptr); return _payload; } + T* get() noexcept { return _payload; } + const T* get() const noexcept { return _payload; } + const mir_rc_context* getContext() const noexcept { return _context; } + const T& operator*() const noexcept { assert(_payload != nullptr); return *_payload; } + const T* operator->() const noexcept { assert(_payload != nullptr); return _payload; } + template bool operator==(const mir_rcptr& rhs) const noexcept { return _payload == rhs._payload; } + template bool operator!=(const mir_rcptr& rhs) const noexcept { return _payload != rhs._payload; } + template bool operator<=(const mir_rcptr& rhs) const noexcept { return _payload <= rhs._payload; } + template bool operator>=(const mir_rcptr& rhs) const noexcept { return _payload >= rhs._payload; } + template bool operator<(const mir_rcptr& rhs) const noexcept { return _payload < rhs._payload; } + template bool operator>(const mir_rcptr& rhs) const noexcept { return _payload > rhs._payload; } + explicit operator bool() const noexcept { return _payload != nullptr; } +}; + +template +struct mir_rcptr +{ +private: + + T* _payload = nullptr; + mir_rc_context* _context = nullptr; + using U = typename std::remove_all_extents::type; + static constexpr void (*destr)(U&) = std::is_destructible::value ? &mir::Destructor::destroy : nullptr; + static constexpr mir::type_info_g typeInfoT = {destr, sizeof(T)}; + +public: + + using element_type = T; + + mir_rcptr() noexcept {} + mir_rcptr(std::nullptr_t) noexcept {} + mir_rcptr(const mir_rc_context* context, T* payload) noexcept : _payload(payload), _context((mir_rc_context*)context) { if (_context) mir_rc_increase_counter(_context); } + ~mir_rcptr() noexcept { if (_context) mir_rc_decrease_counter(_context); } + mir_rcptr(const mir_rcptr& rhs) noexcept : _payload(rhs._payload), _context((mir_rc_context*)rhs.getContext()) { if (_context) mir_rc_increase_counter(_context); } + mir_rcptr(mir_rcptr&& rhs) noexcept : _payload(rhs._payload), _context(rhs.getContext()) { rhs.__reset(); } + mir_rcptr& operator=(const mir_rcptr& rhs) noexcept + { + if (_payload != rhs._payload) + { + if (_context) mir_rc_decrease_counter(_context); + _payload = (T*) rhs._payload; + _context = (mir_rc_context*) rhs.getContext(); + if (_context) mir_rc_increase_counter(_context);; + } + return *this; + } + + template + static mir_rcptr make_shared(Args&& ...args) + { + using U = typename std::remove_const::type; + static_assert( std::is_constructible::value, "Can't construct object in mir_rcptr constructor" ); + mir_rcptr ret; + ret._context = mir_rc_create((const mir_type_info*)&typeInfoT, 1); + if (ret._context == nullptr) + throw std::bad_alloc(); + ret._payload = (T*)(ret._context + 1); + ::new((U*)ret._payload) U(std::forward(args)...); + return ret; + } + + void __reset() { _payload = nullptr; _context = nullptr; } + + template::value>::type> + mir_rcptr& operator=(const mir_rcptr& rhs) noexcept + { + auto rhsv = rhs.template get(); + if (_payload != rhsv) + { + if (_context) mir_rc_decrease_counter(_context); + _payload = rhsv; + _context = (mir_rc_context*) rhs.getContext(); + if (_context) mir_rc_increase_counter(_context); + } + return *this; + } + + template::value>::type> + mir_rcptr(const mir_rcptr& rhs) noexcept : _payload(rhs.template get()), _context((mir_rc_context*)rhs.getContext()) + { + if (_context) mir_rc_increase_counter(_context); + } + + template::value>::type> + mir_rcptr(mir_rcptr&& rhs) noexcept : _payload(rhs.template get()), _context(rhs.getContext()) + { + rhs.__reset(); + } + + mir_rcptr light_const() const noexcept { return *(mir_rcptr*)this; } + + template + Q* get() + { + if (_payload == nullptr) + return nullptr; + auto ret = dynamic_cast(_payload); + if (ret != nullptr) + return ret; + throw std::bad_cast(); + } + + template + Q* get() const + { + if (_payload == nullptr) + return nullptr; + auto ret = dynamic_cast(_payload); + if (ret != nullptr) + return ret; + throw std::bad_cast(); + } + + mir_rc_context* getContext() noexcept { return _context; } + mir_rcptr& operator=(std::nullptr_t) noexcept { if (_context) mir_rc_decrease_counter(_context); __reset(); return *this; } + T& operator*() noexcept { assert(_payload != nullptr); return *_payload; } + T* operator->() noexcept { assert(_payload != nullptr); return _payload; } + T* get() noexcept { return _payload; } + const T* get() const noexcept { return _payload; } + const mir_rc_context* getContext() const noexcept { return _context; } + const T& operator*() const noexcept { assert(_payload != nullptr); return *_payload; } + const T* operator->() const noexcept { assert(_payload != nullptr); return _payload; } + template bool operator==(const mir_rcptr& rhs) const noexcept { return _payload == rhs._payload; } + template bool operator!=(const mir_rcptr& rhs) const noexcept { return _payload != rhs._payload; } + template bool operator<=(const mir_rcptr& rhs) const noexcept { return _payload <= rhs._payload; } + template bool operator>=(const mir_rcptr& rhs) const noexcept { return _payload >= rhs._payload; } + template bool operator<(const mir_rcptr& rhs) const noexcept { return _payload < rhs._payload; } + template bool operator>(const mir_rcptr& rhs) const noexcept { return _payload > rhs._payload; } + explicit operator bool() const noexcept { return _payload != nullptr; } +}; + namespace mir { template diff --git a/source/mir/rc/array.d b/source/mir/rc/array.d index 48a5e3da..38ded14e 100644 --- a/source/mir/rc/array.d +++ b/source/mir/rc/array.d @@ -49,6 +49,33 @@ struct mir_rcarray(T) /// mixin CommonRCImpl; + /// + ~this() nothrow + { + static if (hasDestructor!T) + { + if (false) // break @safe and pure attributes + { + Unqual!T* object; + (*object).__xdtor(); + } + } + if (this) + { + (() @trusted { mir_rc_decrease_counter(context); })(); + debug _reset; + } + } + + /// + this(this) scope @trusted pure nothrow @nogc + { + if (this) + { + mir_rc_increase_counter(context); + } + } + /// size_t length() @trusted scope pure nothrow @nogc const @property { diff --git a/source/mir/rc/context.d b/source/mir/rc/context.d index 8312ac4c..0acc15a3 100644 --- a/source/mir/rc/context.d +++ b/source/mir/rc/context.d @@ -161,33 +161,6 @@ package mixin template CommonRCImpl() { } - /// - ~this() nothrow - { - static if (hasDestructor!T) - { - if (false) // break @safe and pure attributes - { - Unqual!T* object; - (*object).__xdtor(); - } - } - if (this) - { - (() @trusted { mir_rc_decrease_counter(context); })(); - debug _reset; - } - } - - /// - this(this) scope @trusted pure nothrow @nogc - { - if (this) - { - mir_rc_increase_counter(context); - } - } - /// ref opAssign(typeof(null)) scope return { diff --git a/source/mir/rc/ptr.d b/source/mir/rc/ptr.d index bb1811f9..bab44b70 100644 --- a/source/mir/rc/ptr.d +++ b/source/mir/rc/ptr.d @@ -5,6 +5,7 @@ module mir.rc.ptr; import mir.rc.context; import mir.type_info; +import std.traits; private static immutable allocationExcMsg = "mir_rcptr: out of memory error."; private static immutable getExcMsg = "mir_rcptr: trying to use null value."; @@ -24,8 +25,6 @@ The implementation never adds roots into the GC. +/ struct mir_rcptr(T) { - import std.traits; - static if (is(T == class) || is(T == interface) || is(T == struct) || is(T == union)) static assert(!__traits(isNested, T), "mir_rcptr does not support nested types."); @@ -87,80 +86,36 @@ struct mir_rcptr(T) rhs._context = t1; } - /++ - +/ - auto _shareMember(string member, Args...)(auto ref Args args) + /// + mixin CommonRCImpl; + + /// + ~this() nothrow { - void foo(A)(auto ref A) {} - static if (args.length) + static if (hasDestructor!T) { - // breaks safaty - if (false) foo(__traits(getMember, _get_value, member)(forward!args)); - - return (()@trusted => _withContext(__traits(getMember, _get_value, member)(forward!args)))(); + if (false) // break @safe and pure attributes + { + Unqual!T* object; + (*object).__xdtor(); + } } - else + if (this) { - // breaks safaty - if (false) foo(__traits(getMember, _get_value, member)); - - return (()@trusted => _withContext(__traits(getMember, _get_value, member)))(); + (() @trusted { mir_rc_decrease_counter(context); })(); + debug _reset; } } - /++ - Construct a shared pointer of a required type with a current context. - Provides polymorphism abilities for classes and structures with `alias this` syntax. - +/ - .mir_rcptr!R _shareAs(R)() @trusted - if (isImplicitlyConvertible!(T, R)) - { - return _withContext(cast(R)_get_value); - } - - /// ditto - .mir_rcptr!(const R) _shareAs(R)() @trusted const - if (isImplicitlyConvertible!(const T, const R)) - { - return _withContext(cast(const R)_get_value); - } - - /// ditto - .mir_rcptr!(immutable R) _shareAs(R)() @trusted immutable - if (isImplicitlyConvertible!(immutable T, immutable R)) - { - return _withContext(cast(immutable R)_get_value); - } - - /++ - Returns: shared pointer constructed with current context. - +/ - @system .mir_rcptr!R _withContext(R)(return R value) return const - if (is(R == class) || is(R == interface)) - { - static if (__VERSION__ >= 2085) import core.lifetime: move; else import std.algorithm.mutation: move; - typeof(return) ret; - ret._value = cast()value; - ret._context = cast(mir_rc_context*)_context; - ret.__postblit; - return ret.move; - } - - ///ditto - @system .mir_rcptr!R _withContext(R)(return ref R value) return const - if (!is(R == class) && !is(R == interface)) + /// + this(this) scope @trusted pure nothrow @nogc { - import std.algorithm.mutation: move; - typeof(return) ret; - ret._value = &value; - ret._context = cast(mir_rc_context*)_context; - ret.__postblit; - return ret.move; + if (this) + { + mir_rc_increase_counter(context); + } } - /// - mixin CommonRCImpl; - static if (!is(T == interface) && !__traits(isAbstractClass, T)) { private this(Args...)(auto ref Args args) @trusted @@ -186,6 +141,76 @@ struct mir_rcptr(T) /// alias RCPtr = mir_rcptr; +/++ ++/ +auto shareMember(string member, T, Args...)(return mir_rcptr!T context, auto ref Args args) +{ + void foo(A)(auto ref A) {} + static if (args.length) + { + // breaks safaty + if (false) foo(__traits(getMember, context._get_value, member)(forward!args)); + return (()@trusted => createRCWithContext(context, __traits(getMember, context._get_value, member)(forward!args)))(); + } + else + { + // breaks safaty + if (false) foo(__traits(getMember, context._get_value, member)); + return (()@trusted => createRCWithContext(context, __traits(getMember, context._get_value, member)))(); + } +} + +/++ +Returns: shared pointer constructed with current context. ++/ +@system .mir_rcptr!R createRCWithContext(R, F)(return const mir_rcptr!F context, return R value) + if (is(R == class) || is(R == interface)) +{ + typeof(return) ret; + ret._value = cast()value; + ret._context = cast(mir_rc_context*)context._context; + (*cast(mir_rcptr!F*)&context)._value = null; + (*cast(mir_rcptr!F*)&context)._context = null; + return ret; +} + +///ditto +@system .mir_rcptr!R createRCWithContext(R, F)(return const mir_rcptr!F context, return ref R value) + if (!is(R == class) && !is(R == interface)) +{ + typeof(return) ret; + ret._value = &value; + ret._context = cast(mir_rc_context*)context._context; + (*cast(mir_rcptr!F*)&context)._value = null; + (*cast(mir_rcptr!F*)&context)._context = null; + return ret; +} + +/++ +Construct a shared pointer of a required type with a current context. +Provides polymorphism abilities for classes and structures with `alias this` syntax. ++/ +mir_rcptr!R castTo(R, T)(return mir_rcptr!T context) @trusted + if (isImplicitlyConvertible!(T, R)) +{ + return createRCWithContext(context, cast(R)context._get_value); +} + +/// ditto +mir_rcptr!(const R) castTo(R, T)(return const mir_rcptr!T context) @trusted const + if (isImplicitlyConvertible!(const T, const R)) +{ + return createRCWithContext(*cast(mir_rcptr!T*)&context, cast(const R)context._get_value); +} + +/// ditto +mir_rcptr!(immutable R) castTo(R, T)(return immutable mir_rcptr!T context) @trusted immutable + if (isImplicitlyConvertible!(immutable T, immutable R)) +{ + return createRCWithContext(*cast(mir_rcptr!T*)&context, cast(immutable R)context._get_value); +} + + /// template createRC(T) { @@ -229,18 +254,19 @@ unittest assert((*b).value == 10); b.value = 100; // access via alias this syntax assert(a.value == 100); + assert(a._counter == 2); - auto d = a._shareAs!D; //RCPtr!D + auto d = a.castTo!D; //RCPtr!D import std.stdio; assert(d._counter == 3); d.index = 234; assert(a.index == 234); - auto i = a._shareAs!I; //RCPtr!I + auto i = a.castTo!I; //RCPtr!I assert(i.bar == 100); assert(i._counter == 4); - auto v = a._shareMember!"value"; //RCPtr!double - auto w = a._shareMember!"bar"; //RCPtr!double + auto v = a.shareMember!"value"; //RCPtr!double + auto w = a.shareMember!"bar"; //RCPtr!double assert(i._counter == 6); assert(*v == 100); ()@trusted{assert(&*w is &*v);}(); @@ -265,7 +291,7 @@ unittest } auto a = createRC!C(10, S(3)); - auto s = a._shareAs!S; // RCPtr!S + auto s = a.castTo!S; // RCPtr!S assert(s._counter == 2); assert(s.e == 3); } From 264d07bf43871f606ebc8cf56bace3876c76c2d3 Mon Sep 17 00:00:00 2001 From: Ilya Yaroshenko Date: Mon, 10 Jun 2019 17:54:49 +0700 Subject: [PATCH 3/6] fix unionSeriesImplPrivate --- source/mir/series.d | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/source/mir/series.d b/source/mir/series.d index 7a477e73..fd024824 100644 --- a/source/mir/series.d +++ b/source/mir/series.d @@ -1550,7 +1550,7 @@ Series!(K*, V*) series(RK, RV, K = RK, V = RV)(RV[RK] aa) static if (is(typeof(ret) == typeof(return))) return ret; else - return ()@trusted{ return cast(R) ret; }(); + return ()@trusted{ return *cast(R*) &ret; }(); } import mir.ndslice.allocation: uninitSlice; Series!(Unqual!K*, Unqual!V*) ret = series(length.uninitSlice!(Unqual!K), length.uninitSlice!(Unqual!V)); @@ -1566,7 +1566,7 @@ Series!(K*, V*) series(RK, RV, K = RK, V = RV)(RV[RK] aa) static if (is(typeof(ret) == typeof(return))) return ret; else - return ()@trusted{ return cast(R) ret; }(); + return ()@trusted{ return *cast(R*) &ret; }(); } /// ditto @@ -2508,12 +2508,12 @@ private auto unionSeriesImplPrivate(bool rc, IndexIterator, Iterator, size_t N, .sliced(shape)))(); } - static if (N == 2) // fast path + static if (C == 2) // fast path { alias algo = troykaSeriesImpl!( - (auto scope ref key, auto scope return ref left) => left, - (auto scope ref key, auto scope return ref left, auto scope return ref right) => left, - (auto scope ref key, auto scope return ref right) => right, + ref (scope ref key, scope return ref left) => left, + ref (scope ref key, scope return ref left, scope return ref right) => left, + ref (scope ref key, scope return ref right) => right, ); algo!(I, E)(seriesTuple[0], seriesTuple[1], ret.lightScope); } @@ -2522,7 +2522,7 @@ private auto unionSeriesImplPrivate(bool rc, IndexIterator, Iterator, size_t N, unionSeriesImpl!(I, E)(seriesTuple, ret.lightScope); } - return () @trusted {return cast(R) ret; }(); + return () @trusted {return *cast(R*) &ret; }(); } /** From 7880e7b4c9c973b2bd1c9eaba23f349604a24fc1 Mon Sep 17 00:00:00 2001 From: Ilya Yaroshenko Date: Mon, 17 Jun 2019 13:15:10 +0700 Subject: [PATCH 4/6] fix import in C++ headers --- include/mir/ndslice.h | 1 + include/mir/rcarray.h | 1 - 2 files changed, 1 insertion(+), 1 deletion(-) diff --git a/include/mir/ndslice.h b/include/mir/ndslice.h index 96d70d9d..1a5259c2 100644 --- a/include/mir/ndslice.h +++ b/include/mir/ndslice.h @@ -15,6 +15,7 @@ Authors: Ilya Yaroshenko #include #include +#include #if INTPTR_MAX == INT32_MAX #define mir_size_t unsigned int diff --git a/include/mir/rcarray.h b/include/mir/rcarray.h index 11ad879e..dcc963fb 100644 --- a/include/mir/rcarray.h +++ b/include/mir/rcarray.h @@ -14,7 +14,6 @@ #include #include #include -#include template struct mir_rci; From 5efef9d469f86f90ed53a9f7633d64075fefaa1f Mon Sep 17 00:00:00 2001 From: Ilya Yaroshenko Date: Wed, 19 Jun 2019 17:53:52 +0700 Subject: [PATCH 5/6] restore older compiler support (#199) --- source/mir/series.d | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/source/mir/series.d b/source/mir/series.d index fd024824..8016e88c 100644 --- a/source/mir/series.d +++ b/source/mir/series.d @@ -2511,9 +2511,9 @@ private auto unionSeriesImplPrivate(bool rc, IndexIterator, Iterator, size_t N, static if (C == 2) // fast path { alias algo = troykaSeriesImpl!( - ref (scope ref key, scope return ref left) => left, - ref (scope ref key, scope return ref left, scope return ref right) => left, - ref (scope ref key, scope return ref right) => right, + (scope ref key, scope return ref left) => left, + (scope ref key, scope return ref left, scope return ref right) => left, + (scope ref key, scope return ref right) => right, ); algo!(I, E)(seriesTuple[0], seriesTuple[1], ret.lightScope); } From 07f87b2d50fef67f322047a3e77a2bd1f49348f0 Mon Sep 17 00:00:00 2001 From: Ilya Yaroshenko Date: Wed, 19 Jun 2019 17:57:51 +0700 Subject: [PATCH 6/6] update travis --- .travis.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.travis.yml b/.travis.yml index 2b48030c..4cac2c99 100644 --- a/.travis.yml +++ b/.travis.yml @@ -8,6 +8,7 @@ d: branches: only: - master + - stable env: - ARCH="x86" - ARCH="x86_64"