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