Instantly share code, notes, and snippets.
Last active
December 20, 2015 14:59
-
Star
(0)
0
You must be signed in to star a gist -
Fork
(0)
0
You must be signed in to fork a gist
-
Save Oberon00/6151412 to your computer and use it in GitHub Desktop.
Workaround for incorrect `use_count()`s with `shared_ptr_converter`. To be integrated in Oberon00/luabind.
This file contains 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
// Copyright Daniel Wallin 2009. Use, modification and distribution is | |
// subject to the Boost Software License, Version 1.0. (See accompanying | |
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) | |
#ifndef LUABIND_SHARED_PTR_CONVERTER_090211_HPP | |
# define LUABIND_SHARED_PTR_CONVERTER_090211_HPP | |
# include <luabind/detail/decorate_type.hpp> // for LUABIND_DECORATE_TYPE | |
# include <luabind/detail/policy.hpp> // for default_converter, etc | |
# include <luabind/detail/yes_no.hpp> | |
# include <luabind/get_main_thread.hpp> // for get_main_thread | |
# include <luabind/handle.hpp> // for handle | |
# include <boost/mpl/bool.hpp> // for bool_, false_ | |
# include <boost/smart_ptr/shared_ptr.hpp> // for shared_ptr, get_deleter | |
namespace luabind { | |
namespace detail | |
{ | |
struct shared_ptr_deleter | |
{ | |
shared_ptr_deleter(lua_State* L, int index) | |
: life_support(get_main_thread(L), L, index) | |
{} | |
void operator()(void const*) | |
{ | |
handle().swap(life_support); | |
} | |
handle life_support; | |
}; | |
// From http://stackoverflow.com/a/1007175/2128694 | |
// (by Johannes Schaub - litb, "based on a brilliant idea of someone on | |
// usenet") | |
template <typename T> | |
struct has_shared_from_this_aux | |
{ | |
private: | |
struct fallback { int shared_from_this; }; // introduce member name | |
struct derived : T, fallback | |
{ | |
derived(); // not implemented; silence MSVC warnings C4510 and C4610 | |
}; | |
template<typename C, C> struct check; | |
template<typename C> static no_t f( | |
check<int fallback::*, &C::shared_from_this>*); | |
template<typename C> static yes_t f(...); | |
public: | |
BOOST_STATIC_CONSTANT(bool, value = | |
sizeof(f<derived>(0)) == sizeof(yes_t)); | |
}; | |
template <typename T> | |
struct has_shared_from_this: | |
boost::mpl::bool_<has_shared_from_this_aux<T>::value> | |
{}; | |
} // namespace detail | |
template <class T> | |
struct default_converter<boost::shared_ptr<T> > | |
: default_converter<T*> | |
{ | |
private: | |
typedef boost::shared_ptr<T> ptr_t; | |
detail::value_converter m_val_cv; | |
int m_val_score; | |
// no shared_from_this() available | |
ptr_t shared_from_raw(T* raw, lua_State* L, int index, boost::mpl::false_) | |
{ | |
return boost::shared_ptr<T>( | |
raw, detail::shared_ptr_deleter(L, index)); | |
} | |
// shared_from_this() available. | |
ptr_t shared_from_raw(T* raw, lua_State*, int, boost::mpl::true_) | |
{ | |
return raw->shared_from_this(); | |
} | |
public: | |
default_converter(): m_val_score(-1) {} | |
typedef boost::mpl::false_ is_native; | |
template <class U> | |
int match(lua_State* L, U, int index) | |
{ | |
// Check if the value on the stack is a holder with exactly ptr_t | |
// as pointer type. | |
m_val_score = m_val_cv.match(L, LUABIND_DECORATE_TYPE(ptr_t), index); | |
if (m_val_score >= 0) | |
return m_val_score; | |
// Fall back to raw_ptr. | |
return default_converter<T*>::match( | |
L, LUABIND_DECORATE_TYPE(T*), index); | |
} | |
template <class U> | |
boost::shared_ptr<T> apply(lua_State* L, U, int index) | |
{ | |
// First, check if we got away without upcasting. | |
if (m_val_score >= 0) | |
{ | |
ptr_t ptr = m_val_cv.apply( | |
L, LUABIND_DECORATE_TYPE(ptr_t), index); | |
return ptr; | |
} | |
// If not obtain, a raw pointer and construct are shared one from it. | |
T* raw_ptr = default_converter<T*>::apply( | |
L, LUABIND_DECORATE_TYPE(T*), index); | |
if (!raw_ptr) | |
return boost::shared_ptr<T>(); | |
return shared_from_raw( | |
raw_ptr, L, index, detail::has_shared_from_this<T>()); | |
} | |
void apply(lua_State* L, boost::shared_ptr<T> const& p) | |
{ | |
if (detail::shared_ptr_deleter* d = | |
boost::get_deleter<detail::shared_ptr_deleter>(p)) | |
{ | |
d->life_support.push(L); | |
} | |
else | |
{ | |
detail::value_converter().apply(L, p); | |
} | |
} | |
template <class U> | |
void converter_postcall(lua_State*, U const&, int) | |
{} | |
}; | |
template <class T> | |
struct default_converter<boost::shared_ptr<T> const&> | |
: default_converter<boost::shared_ptr<T> > | |
{}; | |
#ifdef BOOST_HAS_RVALUE_REFS | |
template <class T> | |
struct default_converter<boost::shared_ptr<T>&&> | |
: default_converter<boost::shared_ptr<T> > | |
{}; | |
#endif | |
} // namespace luabind | |
#endif // LUABIND_SHARED_PTR_CONVERTER_090211_HPP |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment