Skip to content

Instantly share code, notes, and snippets.

@Oberon00
Last active December 20, 2015 14:59
Show Gist options
  • Save Oberon00/6151412 to your computer and use it in GitHub Desktop.
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.
// 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