From 669a7033961ace1c89116d2ecbb1b57cc59c0b98 Mon Sep 17 00:00:00 2001 From: Daniel Wallin Date: Sat, 3 Apr 2004 01:05:00 +0000 Subject: [PATCH] added weak_ref --- doc/docs.rst | 10 +-- luabind/detail/call_member.hpp | 43 +++++---- luabind/detail/construct_rep.hpp | 5 +- luabind/detail/constructor.hpp | 7 +- luabind/detail/policy.hpp | 14 +++ luabind/weak_ref.hpp | 53 +++++++++++ src/Jamfile | 5 +- src/class_rep.cpp | 9 +- src/weak_ref.cpp | 185 +++++++++++++++++++++++++++++++++++++++ test/test_lua_classes.cpp | 4 +- 10 files changed, 293 insertions(+), 42 deletions(-) create mode 100755 luabind/weak_ref.hpp create mode 100755 src/weak_ref.cpp diff --git a/doc/docs.rst b/doc/docs.rst index 0f40952..32a636a 100755 --- a/doc/docs.rst +++ b/doc/docs.rst @@ -25,7 +25,7 @@ with lua 4. It is implemented utilizing template meta programming. That means that you don't need an extra preprocess pass to compile your project (it is done by the -compiler). It also means you don't (usually) have to know the exact signatureof +compiler). It also means you don't (usually) have to know the exact signature of each function you register, since the library will generate code depending on the compile-time type of the function (which includes the signature). The main drawback of this approach is that the compilation time will increase for the @@ -1894,14 +1894,6 @@ LUABIND_NO_ERROR_CHECKING If a functions throws an exception it will be caught by luabind and propagated with ``lua_error()``. -LUABIND_DONT_COPY_STRINGS - If this macro is defined, luabind will expect that all strings given to - the ``def()`` functions are static constant strings (given as string - constants for example). luabind will not copy the strings if you enable - this setting, but just keep the char pointers. - This may be especially useful for embedded systems or consoles where - heap allocations should be minimized. - LUABIND_NO_EXCEPTIONS This define will disable all usage of try, catch and throw in luabind. This will in many cases disable run-time errors, when performing invalid diff --git a/luabind/detail/call_member.hpp b/luabind/detail/call_member.hpp index 29c2e3b..589eae3 100644 --- a/luabind/detail/call_member.hpp +++ b/luabind/detail/call_member.hpp @@ -30,6 +30,7 @@ #include #include #include +#include namespace luabind { @@ -46,7 +47,7 @@ namespace luabind // friend class luabind::object; public: - proxy_member_caller(luabind::object const* o, const char* name, const Tuple args) + proxy_member_caller(weak_ref const* o, const char* name, const Tuple args) : m_obj(o) , m_member_name(name) , m_args(args) @@ -68,16 +69,16 @@ namespace luabind if (m_called) return; m_called = true; - lua_State* L = m_obj->lua_state(); + lua_State* L = m_obj->state(); detail::stack_pop(L, 1); // pop the self reference // get the function - m_obj->pushvalue(); + m_obj->get(); lua_pushstring(L, m_member_name); lua_gettable(L, -2); // push the self-object - m_obj->pushvalue(); + m_obj->get(); push_args_from_tuple<1>::apply(L, m_args); if (pcall(L, boost::tuples::length::value + 1, 0)) @@ -100,16 +101,16 @@ namespace luabind typename default_policy::template generate_converter::type converter; m_called = true; - lua_State* L = m_obj->lua_state(); + lua_State* L = m_obj->state(); detail::stack_pop p(L, 2); // pop the return value and the self reference // get the function - m_obj->pushvalue(); + m_obj->get(); lua_pushstring(L, m_member_name); lua_gettable(L, -2); // push the self-object - m_obj->pushvalue(); + m_obj->get(); push_args_from_tuple<1>::apply(L, m_args); if (pcall(L, boost::tuples::length::value + 1, 1)) @@ -152,16 +153,16 @@ namespace luabind typename converter_policy::template generate_converter::type converter; m_called = true; - lua_State* L = m_obj->lua_state(); + lua_State* L = m_obj->state(); detail::stack_pop popper(L, 2); // pop the return value and the self reference // get the function - m_obj->pushvalue(); + m_obj->get(); lua_pushstring(L, m_member_name); lua_gettable(L, -2); // push the self-object - m_obj->pushvalue(); + m_obj->get(); detail::push_args_from_tuple<1>::apply(L, m_args, p); if (pcall(L, boost::tuples::length::value + 1, 1)) @@ -198,8 +199,7 @@ namespace luabind } private: - - luabind::object const* m_obj; + weak_ref const* m_obj; const char* m_member_name; Tuple m_args; mutable bool m_called; @@ -213,7 +213,7 @@ namespace luabind friend class luabind::object; public: - proxy_member_void_caller(luabind::object const* o, const char* name, const Tuple args) + proxy_member_void_caller(weak_ref const* o, const char* name, const Tuple args) : m_obj(o) , m_member_name(name) , m_args(args) @@ -235,16 +235,16 @@ namespace luabind if (m_called) return; m_called = true; - lua_State* L = m_obj->lua_state(); + lua_State* L = m_obj->state(); detail::stack_pop(L, 1); // pop the self reference // get the function - m_obj->pushvalue(); + m_obj->get(); lua_pushstring(L, m_member_name); lua_gettable(L, -2); // push the self-object - m_obj->pushvalue(); + m_obj->get(); push_args_from_tuple<1>::apply(L, m_args); if (pcall(L, boost::tuples::length::value + 1, 0)) @@ -266,16 +266,16 @@ namespace luabind void operator[](const Policies& p) { m_called = true; - lua_State* L = m_obj->lua_state(); + lua_State* L = m_obj->state(); detail::stack_pop(L, 1); // pop the self reference // get the function - m_obj->pushvalue(); + m_obj->get(); lua_pushstring(L, m_member_name); lua_gettable(L, -2); // push the self-object - m_obj->pushvalue(); + m_obj->get(); detail::push_args_from_tuple<1>::apply(L, m_args, p); @@ -295,8 +295,7 @@ namespace luabind } private: - - luabind::object const* m_obj; + weak_ref const* m_obj; const char* m_member_name; Tuple m_args; mutable bool m_called; @@ -322,7 +321,7 @@ namespace luabind typename boost::mpl::if_ , luabind::detail::proxy_member_void_caller > , luabind::detail::proxy_member_caller > >::type - call_member(luabind::object const& obj, const char* name BOOST_PP_COMMA_IF(BOOST_PP_ITERATION())BOOST_PP_ENUM(BOOST_PP_ITERATION(), LUABIND_OPERATOR_PARAMS, _)) + call_member(weak_ref const& obj, const char* name BOOST_PP_COMMA_IF(BOOST_PP_ITERATION())BOOST_PP_ENUM(BOOST_PP_ITERATION(), LUABIND_OPERATOR_PARAMS, _)) { typedef boost::tuples::tuple tuple_t; #if BOOST_PP_ITERATION() == 0 diff --git a/luabind/detail/construct_rep.hpp b/luabind/detail/construct_rep.hpp index e42a79d..523dda7 100644 --- a/luabind/detail/construct_rep.hpp +++ b/luabind/detail/construct_rep.hpp @@ -35,6 +35,7 @@ #include #include +#include namespace luabind { namespace detail { @@ -49,14 +50,14 @@ namespace luabind { namespace detail } typedef void*(*construct_ptr)(lua_State*); - typedef void*(*wrapped_construct_ptr)(lua_State*, lua_reference const&); + typedef void*(*wrapped_construct_ptr)(lua_State*, weak_ref const&); typedef void(*get_signature_ptr)(lua_State*, std::string&); inline void set_constructor(construct_ptr f) { construct_fun = f; } inline void set_wrapped_constructor(wrapped_construct_ptr f) { wrapped_construct_fun = f; } inline void* construct(lua_State* L) { return construct_fun(L); } - inline void* construct_wrapped(lua_State* L, lua_reference const& ref) { return wrapped_construct_fun(L, ref); } + inline void* construct_wrapped(lua_State* L, weak_ref const& ref) { return wrapped_construct_fun(L, ref); } inline bool has_wrapped_construct() { return wrapped_construct_fun != 0; } inline void set_arity(int arity) { m_arity = arity; } diff --git a/luabind/detail/constructor.hpp b/luabind/detail/constructor.hpp index a09e00d..adfc413 100644 --- a/luabind/detail/constructor.hpp +++ b/luabind/detail/constructor.hpp @@ -37,6 +37,7 @@ #include #include #include +#include namespace luabind { namespace detail { @@ -63,7 +64,7 @@ namespace luabind { namespace detail template struct construct_wrapped_class { - inline static void* apply(lua_State* L, lua_reference const& ref) + inline static void* apply(lua_State* L, weak_ref const& ref) { typedef wrapped_constructor_helper ConstrHelp; typedef typename ConstrHelp::apply Caller; @@ -108,10 +109,10 @@ namespace luabind { namespace detail struct apply { template - static T* call(lua_State* L, lua_reference const& ref, const constructor*, const Policies*) + static T* call(lua_State* L, weak_ref const& ref, const constructor*, const Policies*) { BOOST_PP_REPEAT(BOOST_PP_ITERATION(), LUABIND_DECL, _) - return new T(luabind::object(L, ref, true/*luabind::object::reference()*/) BOOST_PP_COMMA_IF(BOOST_PP_ITERATION()) BOOST_PP_ENUM(BOOST_PP_ITERATION(), LUABIND_PARAM, _)); + return new T(ref BOOST_PP_COMMA_IF(BOOST_PP_ITERATION()) BOOST_PP_ENUM(BOOST_PP_ITERATION(), LUABIND_PARAM, _)); } }; }; diff --git a/luabind/detail/policy.hpp b/luabind/detail/policy.hpp index 7ed9832..19d13b5 100644 --- a/luabind/detail/policy.hpp +++ b/luabind/detail/policy.hpp @@ -52,6 +52,7 @@ #include #include +#include //#include //#include @@ -152,6 +153,7 @@ namespace luabind template class functor; class object; + class weak_ref; } namespace luabind { namespace detail @@ -271,6 +273,10 @@ namespace luabind { namespace detail template<> struct is_primitive: boost::mpl::bool_ {}; template<> struct is_primitive: boost::mpl::bool_ {}; + template<> struct is_primitive: boost::mpl::bool_ {}; + template<> struct is_primitive: boost::mpl::bool_ {}; + template<> struct is_primitive: boost::mpl::bool_ {}; + template<> struct is_primitive: boost::mpl::bool_ {}; template<> struct is_primitive: boost::mpl::bool_ {}; template<> struct is_primitive: boost::mpl::bool_ {}; @@ -417,6 +423,14 @@ namespace luabind { namespace detail PRIMITIVE_MATCHER(luabind::object) { return std::numeric_limits::max() - 1; } + PRIMITIVE_CONVERTER(luabind::weak_ref) + { + LUABIND_CHECK_STACK(L); + return luabind::weak_ref(L, index); + } + + PRIMITIVE_MATCHER(luabind::weak_ref) { return std::numeric_limits::max() - 1; } + const char* apply(lua_State* L, detail::by_const_pointer, int index) { return static_cast(lua_tostring(L, index)); } const char* apply(lua_State* L, detail::by_const_pointer, int index) { return static_cast(lua_tostring(L, index)); } static int match(lua_State* L, by_const_pointer, int index) { if (lua_type(L, index) == LUA_TSTRING) return 0; else return -1;} diff --git a/luabind/weak_ref.hpp b/luabind/weak_ref.hpp new file mode 100755 index 0000000..fd83ee7 --- /dev/null +++ b/luabind/weak_ref.hpp @@ -0,0 +1,53 @@ +// Copyright (c) 2004 Daniel Wallin and Arvid Norberg + +// Permission is hereby granted, free of charge, to any person obtaining a +// copy of this software and associated documentation files (the "Software"), +// to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, +// and/or sell copies of the Software, and to permit persons to whom the +// Software is furnished to do so, subject to the following conditions: + +// The above copyright notice and this permission notice shall be included +// in all copies or substantial portions of the Software. + +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF +// ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A +// PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT +// SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR +// ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN +// ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE +// OR OTHER DEALINGS IN THE SOFTWARE. + +#ifndef WEAK_REF_040402_HPP +#define WEAK_REF_040402_HPP + +struct lua_State; + +namespace luabind { + + class weak_ref + { + public: + weak_ref(); + weak_ref(lua_State*, int); + weak_ref(weak_ref const&); + ~weak_ref(); + + weak_ref& operator=(weak_ref const&); + + void swap(weak_ref&); + + lua_State* state() const; + void get() const; + + private: + struct impl; + impl* m_impl; + }; + +} // namespace luabind + +#endif // WEAK_REF_040402_HPP + diff --git a/src/Jamfile b/src/Jamfile index 784ac4c..aa1eade 100755 --- a/src/Jamfile +++ b/src/Jamfile @@ -1,7 +1,8 @@ project luabind/luabind ; lib luabind - : pcall.cpp + : weak_ref.cpp + pcall.cpp error.cpp scope.cpp class.cpp @@ -13,7 +14,7 @@ lib luabind create_class.cpp stack_content_by_name.cpp object.cpp - object_rep.cpp + object_rep.cpp class_info.cpp ref.cpp class_registry.cpp diff --git a/src/class_rep.cpp b/src/class_rep.cpp index 83b92ce..e5c4c5e 100755 --- a/src/class_rep.cpp +++ b/src/class_rep.cpp @@ -1070,11 +1070,16 @@ int luabind::detail::class_rep::super_callback(lua_State* L) else { // get reference to lua object - lua_pushvalue(L, lua_upvalueindex(2)); +/* lua_pushvalue(L, lua_upvalueindex(2)); detail::lua_reference ref; ref.set(L); + void* instance = rep->overloads[match_index].construct_wrapped(L, ref);*/ + + lua_pushvalue(L, lua_upvalueindex(2)); + weak_ref ref(L, -1); + lua_pop(L, 1); void* instance = rep->overloads[match_index].construct_wrapped(L, ref); - + if (crep->has_holder()) { crep->m_construct_holder(storage_ptr, instance); diff --git a/src/weak_ref.cpp b/src/weak_ref.cpp new file mode 100755 index 0000000..34d8a4a --- /dev/null +++ b/src/weak_ref.cpp @@ -0,0 +1,185 @@ +// Copyright (c) 2004 Daniel Wallin and Arvid Norberg + +// Permission is hereby granted, free of charge, to any person obtaining a +// copy of this software and associated documentation files (the "Software"), +// to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, +// and/or sell copies of the Software, and to permit persons to whom the +// Software is furnished to do so, subject to the following conditions: + +// The above copyright notice and this permission notice shall be included +// in all copies or substantial portions of the Software. + +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF +// ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A +// PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT +// SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR +// ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN +// ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE +// OR OTHER DEALINGS IN THE SOFTWARE. + +#include + +#include + +#include +#include +#include + +namespace luabind { + +// allocation code from lauxlib.c +/****************************************************************************** +* Copyright (C) 1994-2003 Tecgraf, PUC-Rio. All rights reserved. +* +* Permission is hereby granted, free of charge, to any person obtaining +* a copy of this software and associated documentation files (the +* "Software"), to deal in the Software without restriction, including +* without limitation the rights to use, copy, modify, merge, publish, +* distribute, sublicense, and/or sell copies of the Software, and to +* permit persons to whom the Software is furnished to do so, subject to +* the following conditions: +* +* The above copyright notice and this permission notice shall be +* included in all copies or substantial portions of the Software. +* +* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +******************************************************************************/ + + namespace { + + enum + { + freelist_ref = 1, count_ref = 2 + }; + + void get_weak_table(lua_State* L) + { + lua_pushliteral(L, "__luabind_weak_refs"); + lua_gettable(L, LUA_REGISTRYINDEX); + + if (lua_isnil(L, -1)) + { + lua_pop(L, 1); + lua_newtable(L); + // metatable + lua_newtable(L); + lua_pushliteral(L, "__mode"); + lua_pushliteral(L, "v"); + lua_rawset(L, -3); + // set metatable + lua_setmetatable(L, -2); + lua_pushnumber(L, 0); + lua_rawseti(L, -2, freelist_ref); + } + } + + } // namespace unnamed + + struct weak_ref::impl + { + impl(lua_State* s, int index) + : count(0) + , state(s) + , ref(0) + { + lua_pushvalue(s, index); + get_weak_table(s); + + lua_rawgeti(s, -1, freelist_ref); + ref = (int)lua_tonumber(s, -1); + lua_pop(s, 1); + + if (ref == 0) + { + lua_rawgeti(s, -1, count_ref); + ref = (int)lua_tonumber(s, -1) + 1; + lua_pop(s, 1); + lua_pushnumber(s, ref); + lua_rawseti(s, -2, count_ref); + } + else + { + lua_rawgeti(s, -1, ref); + lua_rawseti(s, -2, freelist_ref); + } + + lua_pushvalue(s, -2); // duplicate value + lua_rawseti(s, -2, ref); + lua_pop(s, 1); // pop weakref table + } + + ~impl() + { + get_weak_table(state); + lua_rawgeti(state, -1, freelist_ref); + lua_rawseti(state, -2, ref); + lua_pushnumber(state, ref); + lua_rawseti(state, -2, freelist_ref); + } + + int count; + lua_State* state; + int ref; + }; + + weak_ref::weak_ref() + : m_impl(0) + { + } + + weak_ref::weak_ref(lua_State* L, int index) + : m_impl(new impl(L, index)) + { + m_impl->count = 1; + } + + weak_ref::weak_ref(weak_ref const& other) + : m_impl(other.m_impl) + { + if (m_impl) ++m_impl->count; + } + + weak_ref::~weak_ref() + { + if (m_impl && --m_impl->count == 0) + { + delete m_impl; + } + } + + weak_ref& weak_ref::operator=(weak_ref const& other) + { + weak_ref(other).swap(*this); + return *this; + } + + void weak_ref::swap(weak_ref& other) + { + std::swap(m_impl, other.m_impl); + } + + void weak_ref::get() const + { + assert(m_impl); + get_weak_table(m_impl->state); + lua_rawgeti(m_impl->state, -1, m_impl->ref); + lua_remove(m_impl->state, -2); + } + + lua_State* weak_ref::state() const + { + assert(m_impl); + return m_impl->state; + } + +} // namespace luabind + diff --git a/test/test_lua_classes.cpp b/test/test_lua_classes.cpp index bc2a110..a202ab9 100644 --- a/test/test_lua_classes.cpp +++ b/test/test_lua_classes.cpp @@ -39,8 +39,8 @@ struct base : counted_type struct base_wrap : base { - object self; - base_wrap(object const& self_): self(self_) {} + weak_ref self; + base_wrap(weak_ref self_): self(self_) {} static std::string f_static(base* obj) { -- 2.11.4.GIT