Rework local_id allocation in class_id_map.
[luabind.git] / luabind / detail / inheritance.hpp
blob2c422ecbc931718fc9a36bc1ace5c49adec5cae0
1 // Copyright Daniel Wallin 2009. Use, modification and distribution is
2 // subject to the Boost Software License, Version 1.0. (See accompanying
3 // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
5 #ifndef LUABIND_INHERITANCE_090217_HPP
6 # define LUABIND_INHERITANCE_090217_HPP
8 # include <cassert>
9 # include <limits>
10 # include <map>
11 # include <memory>
12 # include <vector>
13 # include <luabind/typeid.hpp>
15 namespace luabind { namespace detail {
17 typedef void*(*cast_function)(void*);
18 typedef std::size_t class_id;
20 class_id const unknown_class = std::numeric_limits<class_id>::max();
22 class class_rep;
24 class LUABIND_API cast_graph
26 public:
27 cast_graph();
28 ~cast_graph();
30 // `src` and `p` here describe the *most derived* object. This means that
31 // for a polymorphic type, the pointer must be cast with
32 // dynamic_cast<void*> before being passed in here, and `src` has to
33 // match typeid(*p).
34 std::pair<void*, std::size_t> cast(
35 void* p, class_id src, class_id target
36 , class_id dynamic_id, void const* dynamic_ptr) const;
37 void insert(class_id src, class_id target, cast_function cast);
39 private:
40 class impl;
41 std::auto_ptr<impl> m_impl;
44 // Maps a type_id to a class_id. Note that this actually partitions the
45 // id-space into two, using one half for "local" ids; ids that are used only as
46 // keys into the conversion cache. This is needed because we need a unique key
47 // even for types that hasn't been registered explicitly.
48 class class_id_map
50 public:
51 class_id_map();
53 class_id get(type_id const& type) const;
54 class_id get_local(type_id const& type);
55 void put(class_id id, type_id const& type);
57 private:
58 typedef std::map<type_id, class_id> map_type;
59 map_type m_classes;
60 class_id m_local_id;
62 static class_id const local_id_base;
65 inline class_id_map::class_id_map()
66 : m_local_id(local_id_base)
69 inline class_id class_id_map::get(type_id const& type) const
71 map_type::const_iterator i = m_classes.find(type);
72 if (i == m_classes.end() || i->second >= local_id_base)
73 return unknown_class;
74 return i->second;
77 inline class_id class_id_map::get_local(type_id const& type)
79 std::pair<map_type::iterator, bool> result = m_classes.insert(
80 std::make_pair(type, 0));
82 if (result.second)
83 result.first->second = m_local_id++;
85 assert(m_local_id >= local_id_base);
87 return result.first->second;
90 inline void class_id_map::put(class_id id, type_id const& type)
92 assert(id < local_id_base);
94 std::pair<map_type::iterator, bool> result = m_classes.insert(
95 std::make_pair(type, 0));
97 assert(
98 result.second
99 || result.first->second == id
100 || result.first->second >= local_id_base
103 if (!result.second)
105 result.first->second = id;
106 --m_local_id;
109 assert(m_local_id >= local_id_base);
112 class class_map
114 public:
115 class_rep* get(class_id id) const;
116 void put(class_id id, class_rep* cls);
118 private:
119 std::vector<class_rep*> m_classes;
122 inline class_rep* class_map::get(class_id id) const
124 if (id >= m_classes.size())
125 return 0;
126 return m_classes[id];
129 inline void class_map::put(class_id id, class_rep* cls)
131 if (id >= m_classes.size())
132 m_classes.resize(id + 1);
133 m_classes[id] = cls;
136 template <class S, class T>
137 struct static_cast_
139 static void* execute(void* p)
141 return static_cast<T*>(static_cast<S*>(p));
145 template <class S, class T>
146 struct dynamic_cast_
148 static void* execute(void* p)
150 return dynamic_cast<T*>(static_cast<S*>(p));
154 // Thread safe class_id allocation.
155 LUABIND_API class_id allocate_class_id();
157 template <class T>
158 struct registered_class
160 static class_id const id;
163 template <class T>
164 class_id const registered_class<T>::id = allocate_class_id();
166 template <class T>
167 struct registered_class<T const>
168 : registered_class<T>
171 }} // namespace luabind::detail
173 #endif // LUABIND_INHERITANCE_090217_HPP