inheritance cast_graph cache bug/fix

eduard mueller <[email protected]>
Newsgroups gmane.comp.lang.lua.bind.user
Message-ID <[email protected]>
Hey all,

stumbled upon a bug in the inheritance cast cache. Looks like this
already was broken in earlier LuaBind versions, but now got relevant
with the other inheritance graph cache fix included in 0.9.1:
http://github.com/luabind/luabind/commit/8e9bb9c7e909b527cd87e7976e868c17ce97eb73

Problem is: with LuaBind 0.9.1 a failed cast gets an invalid, bogus
cache entry, which then results into a bogus cast when called a second
time.

Below is a simple test and a proposal for a fix. Maybe it would make
more sense to swap the args in void cache::put, so they reflect the
order of the cache_entry pair?

Greets,
Eduard


=== >>> CastCache.patch

diff --git a/src/inheritance.cpp b/src/inheritance.cpp
index 2e2ec90..b8467ad 100644
--- a/src/inheritance.cpp
+++ b/src/inheritance.cpp
@@ -190,7 +190,7 @@ std::pair<void*, int> cast_graph::impl::cast(
         }
     }

-    m_cache.put(src, target, dynamic_id, object_offset, cache::invalid, -1);
+    m_cache.put(src, target, dynamic_id, object_offset, 0, cache::invalid);

     return std::pair<void*, int>((void*)0, -1);
 }

=== <<< CastCache.patch



=== >>> CastCacheTest.cpp

extern "C"
{
 #include "lua.h"
 #include "lualib.h"
}

#include <luabind/luabind.hpp>


// =============================================================================

class CppClassBase { };
class CppClass1 : public CppClassBase { };
class CppClass2 : public CppClassBase { };


// =============================================================================

static bool is_class1(const luabind::object& Object)
{
 try
 {
   CppClass1* pObj = luabind::object_cast<CppClass1*>(Object);
   assert(typeid(pObj) == typeid(CppClass1));  (void)(pObj);
 }
 catch(luabind::cast_failed&)
 {
   return false;
 }

 return true;
}


// =============================================================================

int main(int, char**)
{
 lua_State* L = lua_open();
 luaL_openlibs(L);

 luabind::open(L);

 luabind::module(L)[
  luabind::def("is_class1", is_class1),
  luabind::class_<CppClassBase>("CppClassBase"),
  luabind::class_<CppClass1, CppClassBase>("CppClass1")
    .def(luabind::constructor<>()),
  luabind::class_<CppClass2, CppClassBase>("CppClass2")
    .def(luabind::constructor<>())
 ];

 int result = luaL_dostring(L,
  "local obj2 = CppClass2()\n"
  "assert(not is_class1(obj2))\n" // OK
  "assert(not is_class1(obj2))\n"); // FAILS

 assert(result == 0);

 lua_close(L);

 return 0;
}

=== <<< CastCacheTest.cpp

------------------------------------------------------------------------------
Beautiful is writing same markup. Internet Explorer 9 supports
standards for HTML5, CSS3, SVG 1.1,  ECMAScript5, and DOM L2 & L3.
Spend less time writing and  rewriting code and more time creating great
experiences on the web. Be a part of the beta today.
http://p.sf.net/sfu/beautyoftheweb
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.