Skip to content

Instantly share code, notes, and snippets.

@vittorioromeo
Created September 6, 2013 09:37
Show Gist options
  • Save vittorioromeo/6461633 to your computer and use it in GitHub Desktop.
Save vittorioromeo/6461633 to your computer and use it in GitHub Desktop.
fastdelegatestatic
#ifndef LIGHTPTR_HPP
#define LIGHTPTR_HPP
#include <atomic>
#include <cassert>
#include <bitset>
#include <memory>
#include <new>
#include <type_traits>
#include <utility>
namespace detail
{
using counter_type = ::std::size_t;
using atomic_type = ::std::atomic<counter_type>;
template<typename T> using deleter_type = void(*)(T*);
template<typename U> struct ref_type { using type = U&; };
template<> struct ref_type<void> { using type = void; };
template<typename T> inline void dec_ref(atomic_type* const counter_ptr, T* const ptr, deleter_type<T> const deleter)
{
if(counter_ptr && (counter_type(1) == counter_ptr->fetch_sub(counter_type(1), ::std::memory_order_relaxed)))
{
delete counter_ptr;
deleter(ptr);
}
}
inline void inc_ref(atomic_type* const counter_ptr)
{
assert(counter_ptr);
counter_ptr->fetch_add(counter_type(1), ::std::memory_order_relaxed);
}
}
template<typename T> class light_ptr
{
public:
template<typename U, typename V> struct deletion_type { using type = V; };
template<typename U, typename V> struct deletion_type<U[], V> { using type = V[]; };
template<typename U, typename V, ::std::size_t N> struct deletion_type<U[N], V> { using type = V[]; };
template<typename U> struct remove_array { using type = U; };
template<typename U> struct remove_array<U[]> { using type = U; };
template<typename U, ::std::size_t N> struct remove_array<U[N]> { using type = U; };
using element_type = typename remove_array<T>::type;
using deleter_type = ::detail::deleter_type<element_type>;
light_ptr() = default;
template<typename U> explicit light_ptr(U* const p, deleter_type const d = default_deleter<U>) { reset(p, d); }
~light_ptr() { ::detail::dec_ref(counter_ptr_, ptr_, deleter_); }
light_ptr(light_ptr const& other) { *this = other; }
light_ptr(light_ptr&& other) noexcept { *this = ::std::move(other); }
light_ptr& operator=(light_ptr const& rhs)
{
if(*this != rhs)
{
::detail::dec_ref(counter_ptr_, ptr_, deleter_);
counter_ptr_ = rhs.counter_ptr_;
ptr_ = rhs.ptr_;
deleter_ = rhs.deleter_;
::detail::inc_ref(counter_ptr_);
}
return *this;
}
light_ptr& operator=(light_ptr&& rhs) noexcept
{
if(*this != rhs)
{
counter_ptr_ = rhs.counter_ptr_;
ptr_ = rhs.ptr_;
deleter_ = rhs.deleter_;
rhs.counter_ptr_ = nullptr;
rhs.ptr_ = nullptr;
}
return *this;
}
bool operator<(light_ptr const& rhs) const noexcept { return get() < rhs.get(); }
bool operator==(light_ptr const& rhs) const noexcept { return counter_ptr_ == rhs.counter_ptr_; }
bool operator!=(light_ptr const& rhs) const noexcept { return !operator==(rhs); }
bool operator==(::std::nullptr_t const) const noexcept { return !ptr_; }
bool operator!=(::std::nullptr_t const) const noexcept { return ptr_; }
explicit operator bool() const noexcept { return ptr_; }
typename ::detail::ref_type<T>::type operator*() const noexcept { return *static_cast<T*>(static_cast<void*>(ptr_)); }
T* operator->() const noexcept { return static_cast<T*>(static_cast<void*>(ptr_)); }
element_type* get() const noexcept { return ptr_; }
void reset() { reset(nullptr); }
void reset(::std::nullptr_t const)
{
::detail::dec_ref(counter_ptr_, ptr_, deleter_);
counter_ptr_ = nullptr;
ptr_ = nullptr;
}
template<typename U> void reset(U* const p, deleter_type const d = default_deleter<U>)
{
::detail::dec_ref(counter_ptr_, ptr_, deleter_);
counter_ptr_ = new ::detail::atomic_type(::detail::counter_type(1));
ptr_ = p;
deleter_ = d;
}
void swap(light_ptr& other) noexcept
{
::std::swap(counter_ptr_, other.counter_ptr_);
::std::swap(ptr_, other.ptr_);
::std::swap(deleter_, other.deleter_);
}
bool unique() const noexcept { return ::detail::counter_type(1) == use_count(); }
::detail::counter_type use_count() const noexcept { return counter_ptr_ ? counter_ptr_->load(::std::memory_order_relaxed) : ::detail::counter_type{}; }
template<typename U> static void default_deleter(element_type* const p) { ::std::default_delete<typename deletion_type<T, U>::type>()(static_cast<U*>(p)); }
private:
::detail::atomic_type* counter_ptr_{};
element_type* ptr_{};
deleter_type deleter_;
};
template<class T, class... Args> inline light_ptr<T> make_light(Args&&... args) { return light_ptr<T>(new T(::std::forward<Args>(args)...)); }
namespace std
{
template<typename T> struct hash<light_ptr<T>>
{
size_t operator()(light_ptr<T> const& l) const noexcept
{
return hash<typename light_ptr<T>::element_type*>(l.get());
}
};
}
namespace
{
template<typename T> constexpr const T &as_const(T &t) { return t; }
template<typename T> struct static_store
{
static constexpr ::std::size_t const max_instances = 16;
static ::std::bitset<max_instances> memory_map_;
static typename ::std::aligned_storage<sizeof(T), alignof(T)>::type store_[max_instances];
};
template<typename T> ::std::bitset<static_store<T>::max_instances> static_store<T>::memory_map_;
template<typename T> typename ::std::aligned_storage<sizeof(T), alignof(T)>::type static_store<T>::store_[static_store<T>::max_instances];
template<typename T, typename ...A> T* static_new(A&& ...args)
{
using static_store = static_store<T>;
for (::std::size_t i{}; i != static_store::max_instances; ++i)
{
if(!as_const(static_store::memory_map_)[i])
{
auto p(new (&static_store::store_[i]) T(::std::forward<A>(args)...));
static_store::memory_map_[i] = true;
return p;
}
}
assert(0);
return nullptr;
}
template<typename T> void static_delete(T const* const p)
{
using static_store = static_store<T>;
auto const i(p - static_cast<T const*>(static_cast<void const*>(static_store::store_)));
assert(as_const(static_store::memory_map_)[i]);
static_store::memory_map_[i] = false;
static_cast<T const*>(static_cast<void const*>(&static_store::store_[i]))->~T();
}
}
template<typename T> class FastFunc;
template<class R, class ...A> class FastFunc<R (A...)>
{
using stub_ptr_type = R (*)(void*, A&&...);
FastFunc(void* const o, stub_ptr_type const m) noexcept : object_ptr_(o), stub_ptr_(m) { }
public:
FastFunc() = default;
FastFunc(FastFunc const&) = default;
FastFunc(FastFunc&&) = default;
FastFunc(::std::nullptr_t const) noexcept : FastFunc() { }
template<class C> explicit FastFunc(C const* const o) noexcept : object_ptr_(const_cast<C*>(o)) { }
template<class C> explicit FastFunc(C const& o) noexcept : object_ptr_(const_cast<C*>(&o)) { }
FastFunc(R (* const function_ptr)(A...)) { *this = from(function_ptr); }
template<class C> FastFunc(C* const object_ptr, R (C::* const method_ptr)(A...)) { *this = from(object_ptr, method_ptr); }
template<class C> FastFunc(C* const object_ptr, R (C::* const method_ptr)(A...) const) { *this = from(object_ptr, method_ptr); }
template<class C> FastFunc(C& object, R (C::* const method_ptr)(A...)) { *this = from(object, method_ptr); }
template<class C> FastFunc(C const& object, R (C::* const method_ptr)(A...) const) { *this = from(object, method_ptr); }
template<typename T, typename = typename ::std::enable_if<!::std::is_same<FastFunc, typename ::std::decay<T>::type>{}>::type>FastFunc(T&& f) { *this = ::std::forward<T>(f); }
FastFunc& operator=(FastFunc const&) = default;
FastFunc& operator=(FastFunc&& rhs) = default;
FastFunc& operator=(R (* const rhs)(A...)) { return *this = from(rhs); }
template<class C> FastFunc& operator=(R (C::* const rhs)(A...)) { return *this = from(static_cast<C*>(object_ptr_), rhs); }
template<class C> FastFunc& operator=(R (C::* const rhs)(A...) const) { return *this = from(static_cast<C const*>(object_ptr_), rhs); }
template<typename T, typename = typename ::std::enable_if<!::std::is_same<FastFunc, typename ::std::decay<T>::type>{}>::type> FastFunc& operator=(T&& f)
{
using functor_type = typename ::std::decay<T>::type;
store_.reset(static_new<functor_type>(::std::forward<T>(f)), functor_deleter<functor_type>);
object_ptr_ = store_.get();
stub_ptr_ = functor_stub<functor_type>;
deleter_ = deleter_stub<functor_type>;
return *this;
}
template<R (* const function_ptr)(A...)> static FastFunc from() noexcept { return { nullptr, function_stub<function_ptr> }; }
template<class C, R (C::* const method_ptr)(A...)> static FastFunc from(C* const object_ptr) noexcept { return { object_ptr, method_stub<C, method_ptr> }; }
template<class C, R (C::* const method_ptr)(A...) const> static FastFunc from(C const* const object_ptr) noexcept { return { const_cast<C*>(object_ptr), const_method_stub<C, method_ptr> }; }
template<class C, R (C::* const method_ptr)(A...)> static FastFunc from(C& object) noexcept { return { &object, method_stub<C, method_ptr> }; }
template<class C, R (C::* const method_ptr)(A...) const> static FastFunc from(C const& object) noexcept { return { const_cast<C*>(&object), const_method_stub<C, method_ptr> }; }
template<typename T> static FastFunc from(T&& f) { return ::std::forward<T>(f); }
static FastFunc from(R (* const function_ptr)(A...)) { return [function_ptr](A&&... args) { return (*function_ptr)(::std::forward<A>(args)...); }; }
template<class C> static FastFunc from(C* const object_ptr, R (C::* const method_ptr)(A...)) { return [object_ptr, method_ptr](A&&... args) { return (object_ptr->*method_ptr)(::std::forward<A>(args)...); }; }
template<class C> static FastFunc from(C const* const object_ptr,R (C::* const method_ptr)(A...) const) { return [object_ptr, method_ptr](A&&... args) { return (object_ptr->*method_ptr)(::std::forward<A>(args)...); }; }
template<class C> static FastFunc from(C& object, R (C::* const method_ptr)(A...)) { return [&object, method_ptr](A&&... args) { return (object.*method_ptr)(::std::forward<A>(args)...); }; }
template<class C> static FastFunc from(C const& object, R (C::* const method_ptr)(A...) const) { return [&object, method_ptr](A&&... args) { return (object.*method_ptr)(::std::forward<A>(args)...); }; }
void reset() { stub_ptr_ = nullptr; store_.reset(); }
void reset_stub() noexcept { stub_ptr_ = nullptr; }
void swap(FastFunc& other) noexcept { ::std::swap(*this, other); }
bool operator==(FastFunc const& rhs) const noexcept { return (object_ptr_ == rhs.object_ptr_) && (stub_ptr_ == rhs.stub_ptr_); }
bool operator!=(FastFunc const& rhs) const noexcept { return !operator==(rhs); }
bool operator<(FastFunc const& rhs) const noexcept { return (object_ptr_ < rhs.object_ptr_) || ((object_ptr_ == rhs.object_ptr_) && (stub_ptr_ < rhs.stub_ptr_)); }
bool operator==(::std::nullptr_t const) const noexcept { return !stub_ptr_; }
bool operator!=(::std::nullptr_t const) const noexcept { return stub_ptr_; }
explicit operator bool() const noexcept { return stub_ptr_; }
R operator()(A... args) const { return stub_ptr_(object_ptr_, ::std::forward<A>(args)...); }
private:
friend class ::std::hash<FastFunc>;
using deleter_type = void (*)(void const*);
void* object_ptr_;
stub_ptr_type stub_ptr_{};
deleter_type deleter_;
light_ptr<void> store_;
template<class T> static void functor_deleter(void* const p) { static_cast<T const*>(p)->~T(); static_delete(static_cast<T const*>(p)); }
template<class T> static void deleter_stub(void const* const p) { static_cast<T const*>(p)->~T(); }
template<R (*function_ptr)(A...)> static R function_stub(void* const, A&&... args) { return function_ptr(::std::forward<A>(args)...); }
template<class C, R (C::*method_ptr)(A...)> static R method_stub(void* const object_ptr, A&&... args) { return (static_cast<C*>(object_ptr)->*method_ptr)( ::std::forward<A>(args)...); }
template<class C, R (C::*method_ptr)(A...) const> static R const_method_stub(void* const object_ptr, A&&... args) { return (static_cast<C const*>(object_ptr)->*method_ptr)( ::std::forward<A>(args)...); }
template<typename T> static R functor_stub(void* const object_ptr, A&&... args) { return (*static_cast<T*>(object_ptr))(::std::forward<A>(args)...); }
};
namespace std
{
template<typename R, typename ...A>
struct hash<FastFunc<R (A...)>>
{
size_t operator()(FastFunc<R (A...)> const& d) const noexcept
{
auto const seed(hash<void*>()(d.object_ptr_));
return hash<typename FastFunc<R (A...)>::stub_ptr_type>()(d.stub_ptr_) +
0x9e3779b9 + (seed << 6) + (seed >> 2);
}
};
}
#endif
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment