Re: Garbage collector crashes if luabind objects are created in a lua coroutine

James Porter <[email protected]>
Newsgroups gmane.comp.lang.lua.bind.user
Message-ID <[email protected]>
Oops! There was a bug in the version I just uploaded (it unnecessarily 
pushes the current thread onto the stack when unref'ing). Attached is 
the (hopefully) correct version.

- Jim

------------------------------------------------------------------------------

_______________________________________________
luabind-user mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/luabind-user
ref.hpp (text/plain, 3.1 KB)
// Copyright (c) 2003 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 LUABIND_REF_HPP_INCLUDED
#define LUABIND_REF_HPP_INCLUDED

#include <cassert>
#include <algorithm>

#include <luabind/config.hpp>
#include <luabind/lua_include.hpp>

struct lua_State;

namespace luabind
{

#if LUA_VERSION_NUM >= 501
#define LUA_REFNIL (-1)
#undef luaL_setn
#undef luaL_getn
#endif

namespace detail
{

	int LUABIND_API ref(lua_State *L);
	void LUABIND_API unref(lua_State *L, int ref);

	inline void getref(lua_State* L, int r)
	{
		lua_rawgeti(L, LUA_REGISTRYINDEX, r);
	}

	struct lua_reference
	{
		lua_reference(lua_State* L_ = 0)
			: L(L_)
			, m_ref(LUA_NOREF)
			, m_coref(LUA_NOREF)
		{}
		lua_reference(lua_reference const& r)
			: L(r.L)
			, m_ref(LUA_NOREF)
			, m_coref(LUA_NOREF)
		{
			if (!r.is_valid()) return;
			r.get(L);
			set(L);
		}
		~lua_reference() { reset(); }

		lua_State* state() const { return L; }

		void operator=(lua_reference const& r)
		{
			// TODO: self assignment problems
			reset();
			if (!r.is_valid()) return;
			r.get(r.state());
			set(r.state());
		}

		bool is_valid() const
		{ return m_ref != LUA_NOREF; }

		void set(lua_State* L_)
		{
			reset();
			L = L_;
			if (lua_pushthread(L) == 1)
				lua_pop(L, 1);
			else
				m_coref = luaL_ref(L, LUA_REGISTRYINDEX);
			m_ref = luaL_ref(L, LUA_REGISTRYINDEX);
		}

		void replace(lua_State* L_)
		{
			lua_rawseti(L_, LUA_REGISTRYINDEX, m_ref);
		}

		// L may not be the same pointer as
		// was used when creating this reference
		// since it may be a thread that shares
		// the same globals table.
		void get(lua_State* L_) const
		{
			assert(m_ref != LUA_NOREF);
			assert(L_);
			getref(L_, m_ref);
		}

		void reset()
		{
			if (L && m_ref != LUA_NOREF)
				luaL_unref(L, LUA_REGISTRYINDEX, m_ref);

			if (L && m_coref != LUA_NOREF)
				luaL_unref(L, LUA_REGISTRYINDEX, m_coref);

			m_ref = LUA_NOREF;
			m_coref = LUA_NOREF;
		}

		void swap(lua_reference& r)
		{
			assert(r.L == L);
			std::swap(r.m_ref, m_ref);
			std::swap(r.m_coref, m_coref);
		}

	private:
		lua_State* L;
		int m_ref;
		int m_coref;
	};

}}

#endif // LUABIND_REF_HPP_INCLUDED
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.