fixed some bugs
[luabind.git] / src / weak_ref.cpp
blobf862c4a9af84405145918c93ec8b0cf637378234
1 // Copyright (c) 2004 Daniel Wallin and Arvid Norberg
3 // Permission is hereby granted, free of charge, to any person obtaining a
4 // copy of this software and associated documentation files (the "Software"),
5 // to deal in the Software without restriction, including without limitation
6 // the rights to use, copy, modify, merge, publish, distribute, sublicense,
7 // and/or sell copies of the Software, and to permit persons to whom the
8 // Software is furnished to do so, subject to the following conditions:
10 // The above copyright notice and this permission notice shall be included
11 // in all copies or substantial portions of the Software.
13 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF
14 // ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
15 // TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
16 // PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT
17 // SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR
18 // ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
19 // ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE
21 // OR OTHER DEALINGS IN THE SOFTWARE.
23 #include <algorithm>
25 #include <luabind/lua_include.hpp>
27 #include <luabind/config.hpp>
28 #include <luabind/weak_ref.hpp>
29 #include <cassert>
31 namespace luabind {
33 // allocation code from lauxlib.c
34 /******************************************************************************
35 * Copyright (C) 1994-2003 Tecgraf, PUC-Rio. All rights reserved.
37 * Permission is hereby granted, free of charge, to any person obtaining
38 * a copy of this software and associated documentation files (the
39 * "Software"), to deal in the Software without restriction, including
40 * without limitation the rights to use, copy, modify, merge, publish,
41 * distribute, sublicense, and/or sell copies of the Software, and to
42 * permit persons to whom the Software is furnished to do so, subject to
43 * the following conditions:
45 * The above copyright notice and this permission notice shall be
46 * included in all copies or substantial portions of the Software.
48 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
49 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
50 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
51 * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
52 * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
53 * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
54 * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
55 ******************************************************************************/
57 namespace {
59 enum
61 freelist_ref = 1, count_ref = 2
64 void get_weak_table(lua_State* L)
66 lua_pushliteral(L, "__luabind_weak_refs");
67 lua_gettable(L, LUA_REGISTRYINDEX);
69 if (lua_isnil(L, -1))
71 lua_pop(L, 1);
72 lua_newtable(L);
73 // metatable
74 lua_newtable(L);
75 lua_pushliteral(L, "__mode");
76 lua_pushliteral(L, "v");
77 lua_rawset(L, -3);
78 // set metatable
79 lua_setmetatable(L, -2);
80 lua_pushnumber(L, 0);
81 lua_rawseti(L, -2, freelist_ref);
82 lua_pushnumber(L, 2);
83 lua_rawseti(L, -2, count_ref);
85 lua_pushliteral(L, "__luabind_weak_refs");
86 lua_pushvalue(L, -2);
87 lua_settable(L, LUA_REGISTRYINDEX);
91 } // namespace unnamed
93 struct weak_ref::impl
95 impl(lua_State* s, int index)
96 : count(0)
97 , state(s)
98 , ref(0)
100 lua_pushvalue(s, index);
101 get_weak_table(s);
103 lua_rawgeti(s, -1, freelist_ref);
104 ref = (int)lua_tonumber(s, -1);
105 lua_pop(s, 1);
107 if (ref == 0)
109 lua_rawgeti(s, -1, count_ref);
110 ref = (int)lua_tonumber(s, -1) + 1;
111 lua_pop(s, 1);
112 lua_pushnumber(s, ref);
113 lua_rawseti(s, -2, count_ref);
115 else
117 lua_rawgeti(s, -1, ref);
118 lua_rawseti(s, -2, freelist_ref);
121 lua_pushvalue(s, -2); // duplicate value
122 lua_rawseti(s, -2, ref);
123 lua_pop(s, 2); // pop weakref table and value
126 ~impl()
128 get_weak_table(state);
129 lua_rawgeti(state, -1, freelist_ref);
130 lua_rawseti(state, -2, ref);
131 lua_pushnumber(state, ref);
132 lua_rawseti(state, -2, freelist_ref);
133 lua_pop(state, 1);
136 int count;
137 lua_State* state;
138 int ref;
141 weak_ref::weak_ref()
142 : m_impl(0)
146 weak_ref::weak_ref(lua_State* L, int index)
147 : m_impl(new impl(L, index))
149 m_impl->count = 1;
152 weak_ref::weak_ref(weak_ref const& other)
153 : m_impl(other.m_impl)
155 if (m_impl) ++m_impl->count;
158 weak_ref::~weak_ref()
160 if (m_impl && --m_impl->count == 0)
162 delete m_impl;
166 weak_ref& weak_ref::operator=(weak_ref const& other)
168 weak_ref(other).swap(*this);
169 return *this;
172 void weak_ref::swap(weak_ref& other)
174 std::swap(m_impl, other.m_impl);
177 void weak_ref::get() const
179 assert(m_impl);
180 get_weak_table(m_impl->state);
181 lua_rawgeti(m_impl->state, -1, m_impl->ref);
182 lua_remove(m_impl->state, -2);
185 lua_State* weak_ref::state() const
187 assert(m_impl);
188 return m_impl->state;
191 } // namespace luabind