Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
235 changes: 235 additions & 0 deletions include/mir/rcptr.h
Original file line number Diff line number Diff line change
Expand Up @@ -192,6 +192,241 @@ struct mir_rcptr
explicit operator bool() const noexcept { return _payload != nullptr; }
};

// Does not support allocators for now
template <typename T>
struct mir_rcptr<T* const>
{
private:

T* _payload = nullptr;
mir_rc_context* _context = nullptr;
using U = typename std::remove_all_extents<T>::type;
static constexpr void (*destr)(U&) = std::is_destructible<T>::value ? &mir::Destructor<U>::destroy : nullptr;
static constexpr mir::type_info_g<U> 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<class ...Args>
static mir_rcptr make_shared(Args&& ...args)
{
using U = typename std::remove_const<T>::type;
static_assert( std::is_constructible<U, Args...>::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>(args)...);
return ret;
}

void __reset() { _payload = nullptr; _context = nullptr; }

template<class Q, class = typename std::enable_if<!std::is_same<Q, T>::value>::type>
mir_rcptr& operator=(const mir_rcptr<Q>& rhs) noexcept
{
auto rhsv = rhs.template get<T>();
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<class Q, class = typename std::enable_if<!std::is_same<Q, T>::value>::type>
mir_rcptr(const mir_rcptr<Q>& rhs) noexcept : _payload(rhs.template get<T>()), _context((mir_rc_context*)rhs.getContext())
{
if (_context) mir_rc_increase_counter(_context);
}

template<class Q, class = typename std::enable_if<!std::is_same<Q, T>::value>::type>
mir_rcptr(mir_rcptr<Q>&& rhs) noexcept : _payload(rhs.template get<T>()), _context(rhs.getContext())
{
rhs.__reset();
}

mir_rcptr<const T> light_const() const noexcept { return *(mir_rcptr<const T>*)this; }

template<class Q>
Q* get()
{
if (_payload == nullptr)
return nullptr;
auto ret = dynamic_cast<Q*>(_payload);
if (ret != nullptr)
return ret;
throw std::bad_cast();
}

template<class Q>
Q* get() const
{
if (_payload == nullptr)
return nullptr;
auto ret = dynamic_cast<Q*>(_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<class Y> bool operator==(const mir_rcptr<Y>& rhs) const noexcept { return _payload == rhs._payload; }
template<class Y> bool operator!=(const mir_rcptr<Y>& rhs) const noexcept { return _payload != rhs._payload; }
template<class Y> bool operator<=(const mir_rcptr<Y>& rhs) const noexcept { return _payload <= rhs._payload; }
template<class Y> bool operator>=(const mir_rcptr<Y>& rhs) const noexcept { return _payload >= rhs._payload; }
template<class Y> bool operator<(const mir_rcptr<Y>& rhs) const noexcept { return _payload < rhs._payload; }
template<class Y> bool operator>(const mir_rcptr<Y>& rhs) const noexcept { return _payload > rhs._payload; }
explicit operator bool() const noexcept { return _payload != nullptr; }
};

template <typename T>
struct mir_rcptr<T*>
{
private:

T* _payload = nullptr;
mir_rc_context* _context = nullptr;
using U = typename std::remove_all_extents<T>::type;
static constexpr void (*destr)(U&) = std::is_destructible<T>::value ? &mir::Destructor<U>::destroy : nullptr;
static constexpr mir::type_info_g<U> 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<class ...Args>
static mir_rcptr make_shared(Args&& ...args)
{
using U = typename std::remove_const<T>::type;
static_assert( std::is_constructible<U, Args...>::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>(args)...);
return ret;
}

void __reset() { _payload = nullptr; _context = nullptr; }

template<class Q, class = typename std::enable_if<!std::is_same<Q, T>::value>::type>
mir_rcptr& operator=(const mir_rcptr<Q>& rhs) noexcept
{
auto rhsv = rhs.template get<T>();
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<class Q, class = typename std::enable_if<!std::is_same<Q, T>::value>::type>
mir_rcptr(const mir_rcptr<Q>& rhs) noexcept : _payload(rhs.template get<T>()), _context((mir_rc_context*)rhs.getContext())
{
if (_context) mir_rc_increase_counter(_context);
}

template<class Q, class = typename std::enable_if<!std::is_same<Q, T>::value>::type>
mir_rcptr(mir_rcptr<Q>&& rhs) noexcept : _payload(rhs.template get<T>()), _context(rhs.getContext())
{
rhs.__reset();
}

mir_rcptr<const T> light_const() const noexcept { return *(mir_rcptr<const T>*)this; }

template<class Q>
Q* get()
{
if (_payload == nullptr)
return nullptr;
auto ret = dynamic_cast<Q*>(_payload);
if (ret != nullptr)
return ret;
throw std::bad_cast();
}

template<class Q>
Q* get() const
{
if (_payload == nullptr)
return nullptr;
auto ret = dynamic_cast<Q*>(_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<class Y> bool operator==(const mir_rcptr<Y>& rhs) const noexcept { return _payload == rhs._payload; }
template<class Y> bool operator!=(const mir_rcptr<Y>& rhs) const noexcept { return _payload != rhs._payload; }
template<class Y> bool operator<=(const mir_rcptr<Y>& rhs) const noexcept { return _payload <= rhs._payload; }
template<class Y> bool operator>=(const mir_rcptr<Y>& rhs) const noexcept { return _payload >= rhs._payload; }
template<class Y> bool operator<(const mir_rcptr<Y>& rhs) const noexcept { return _payload < rhs._payload; }
template<class Y> bool operator>(const mir_rcptr<Y>& rhs) const noexcept { return _payload > rhs._payload; }
explicit operator bool() const noexcept { return _payload != nullptr; }
};

namespace mir
{
template<class T, class ...Args>
Expand Down
27 changes: 27 additions & 0 deletions source/mir/rc/array.d
Original file line number Diff line number Diff line change
Expand Up @@ -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
{
Expand Down
27 changes: 0 additions & 27 deletions source/mir/rc/context.d
Original file line number Diff line number Diff line change
Expand Up @@ -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
{
Expand Down
Loading