1 // Copyright Daniel Wallin 2008. 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)
4
5 #ifndef LUABIND_INSTANCE_HOLDER_081024_HPP
6 # define LUABIND_INSTANCE_HOLDER_081024_HPP
7
8 # include <luabind/detail/inheritance.hpp>
9 # include <luabind/detail/class_rep.hpp> // TODO
10 # include <luabind/get_pointer.hpp>
11 # include <luabind/typeid.hpp>
12 # include <boost/type_traits/is_polymorphic.hpp>
13 # include <stdexcept>
14
15 namespace luabind { namespace detail {
16
17 class instance_holder
18 {
19 public:
instance_holder(class_rep * cls,bool pointee_const)20 instance_holder(class_rep* cls, bool pointee_const)
21 : m_cls(cls)
22 , m_pointee_const(pointee_const)
23 {}
24
~instance_holder()25 virtual ~instance_holder()
26 {}
27
28 virtual std::pair<void*, int> get(class_id target) const = 0;
29
30 virtual void release() = 0;
31
get_class() const32 class_rep* get_class() const
33 {
34 return m_cls;
35 }
36
pointee_const() const37 bool pointee_const() const
38 {
39 return m_pointee_const;
40 }
41
42 private:
43 class_rep* m_cls;
44 bool m_pointee_const;
45 };
46
47 namespace mpl = boost::mpl;
48
check_const_pointer(void *)49 inline mpl::false_ check_const_pointer(void*)
50 {
51 return mpl::false_();
52 }
53
check_const_pointer(void const *)54 inline mpl::true_ check_const_pointer(void const*)
55 {
56 return mpl::true_();
57 }
58
59 template <class T>
release_ownership(std::auto_ptr<T> & p)60 void release_ownership(std::auto_ptr<T>& p)
61 {
62 p.release();
63 }
64
65 template <class P>
release_ownership(P const &)66 void release_ownership(P const&)
67 {
68 throw std::runtime_error(
69 "luabind: smart pointer does not allow ownership transfer");
70 }
71
72 template <class T>
static_class_id(T *)73 class_id static_class_id(T*)
74 {
75 return registered_class<T>::id;
76 }
77
78 template <class P, class Pointee = void const>
79 class pointer_holder : public instance_holder
80 {
81 public:
pointer_holder(P p,class_id dynamic_id,void * dynamic_ptr,class_rep * cls)82 pointer_holder(
83 P p, class_id dynamic_id, void* dynamic_ptr, class_rep* cls
84 )
85 : instance_holder(cls, check_const_pointer(false ? get_pointer(p) : 0))
86 , p(p)
87 , weak(0)
88 , dynamic_id(dynamic_id)
89 , dynamic_ptr(dynamic_ptr)
90 {}
91
get(class_id target) const92 std::pair<void*, int> get(class_id target) const
93 {
94 if (target == registered_class<P>::id)
95 return std::pair<void*, int>(&this->p, 0);
96
97 void* naked_ptr = const_cast<void*>(static_cast<void const*>(
98 weak ? weak : get_pointer(p)));
99
100 if (!naked_ptr)
101 return std::pair<void*, int>(0, 0);
102
103 return get_class()->casts().cast(
104 naked_ptr
105 , static_class_id(false ? get_pointer(p) : 0)
106 , target
107 , dynamic_id
108 , dynamic_ptr
109 );
110 }
111
release()112 void release()
113 {
114 weak = const_cast<void*>(static_cast<void const*>(
115 get_pointer(p)));
116 release_ownership(p);
117 }
118
119 private:
120 mutable P p;
121 // weak will hold a possibly stale pointer to the object owned
122 // by p once p has released it's owership. This is a workaround
123 // to make adopt() work with virtual function wrapper classes.
124 void* weak;
125 class_id dynamic_id;
126 void* dynamic_ptr;
127 };
128
129 }} // namespace luabind::detail
130
131 #endif // LUABIND_INSTANCE_HOLDER_081024_HPP
132