Created
          September 6, 2013 09:37 
        
      - 
      
- 
        Save vittorioromeo/6461633 to your computer and use it in GitHub Desktop. 
    fastdelegatestatic
  
        
  
    
      This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
      Learn more about bidirectional Unicode characters
    
  
  
    
  | #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