Reference counting working for reals now. Previously it was counting the wrong thing (but was almost good enough)

This commit is contained in:
Jason Turner 2009-06-12 05:19:58 +00:00
parent 7e46064bdc
commit dc0f74fd36

View File

@ -13,12 +13,42 @@ class Boxed_Value
private: private:
struct Data struct Data
{ {
struct Shared_Ptr_Proxy
{
virtual ~Shared_Ptr_Proxy()
{
}
virtual bool unique(boost::any *) = 0;
virtual long use_count(boost::any *) = 0;
};
template<typename T>
struct Shared_Ptr_Proxy_Impl : Shared_Ptr_Proxy
{
virtual ~Shared_Ptr_Proxy_Impl()
{
}
virtual bool unique(boost::any *a)
{
boost::shared_ptr<T> *ptr = boost::any_cast<boost::shared_ptr<T> >(a);
return ptr->unique();
}
virtual long use_count(boost::any *a)
{
boost::shared_ptr<T> *ptr = boost::any_cast<boost::shared_ptr<T> >(a);
return ptr->use_count();
}
};
Data(const Type_Info &ti, Data(const Type_Info &ti,
const boost::any &to, const boost::any &to,
bool tr, bool tr,
const boost::function<bool ()> &t_unique = &Boxed_Value::Data::get_false) const boost::shared_ptr<Shared_Ptr_Proxy> &t_proxy = boost::shared_ptr<Shared_Ptr_Proxy>())
: m_type_info(ti), m_obj(to), : m_type_info(ti), m_obj(to),
m_is_ref(tr) m_is_ref(tr), m_ptr_proxy(t_proxy)
{ {
} }
@ -27,6 +57,7 @@ class Boxed_Value
m_type_info = rhs.m_type_info; m_type_info = rhs.m_type_info;
m_obj = rhs.m_obj; m_obj = rhs.m_obj;
m_is_ref = rhs.m_is_ref; m_is_ref = rhs.m_is_ref;
m_ptr_proxy = rhs.m_ptr_proxy;
return *this; return *this;
} }
@ -39,6 +70,7 @@ class Boxed_Value
Type_Info m_type_info; Type_Info m_type_info;
boost::any m_obj; boost::any m_obj;
bool m_is_ref; bool m_is_ref;
boost::shared_ptr<Shared_Ptr_Proxy> m_ptr_proxy;
}; };
public: public:
@ -51,19 +83,20 @@ class Boxed_Value
: m_data(new Data( : m_data(new Data(
Get_Type_Info<T>()(), Get_Type_Info<T>()(),
boost::any(obj), boost::any(obj),
false) false,
boost::shared_ptr<Data::Shared_Ptr_Proxy>(new Data::Shared_Ptr_Proxy_Impl<T>()))
) )
{ {
boost::shared_ptr<T> *ptr = boost::any_cast<boost::shared_ptr<T> >(&m_data->m_obj); boost::shared_ptr<T> *ptr = boost::any_cast<boost::shared_ptr<T> >(&m_data->m_obj);
std::map<void *, boost::shared_ptr<Data> >::iterator itr std::map<void *, Data >::iterator itr
= m_ptrs.find(ptr->get()); = m_ptrs.find(ptr->get());
if (itr != m_ptrs.end()) if (itr != m_ptrs.end())
{ {
m_data = (itr->second); (*m_data) = (itr->second);
} else { } else {
m_ptrs[ptr->get()] = m_data; m_ptrs.insert(std::make_pair(ptr->get(), *m_data));
} }
} }
@ -77,13 +110,13 @@ class Boxed_Value
{ {
void *ptr = boost::any_cast<boost::reference_wrapper<T> >(m_data->m_obj).get_pointer(); void *ptr = boost::any_cast<boost::reference_wrapper<T> >(m_data->m_obj).get_pointer();
std::map<void *, boost::shared_ptr<Data> >::iterator itr std::map<void *, Data >::iterator itr
= m_ptrs.find(ptr); = m_ptrs.find(ptr);
if (itr != m_ptrs.end()) if (itr != m_ptrs.end())
{ {
// std::cout << "Reference wrapper ptr found, using it" << std::endl; std::cout << "Reference wrapper ptr found, using it" << std::endl;
m_data = (itr->second); (*m_data) = (itr->second);
} }
} }
@ -92,13 +125,13 @@ class Boxed_Value
: m_data(new Data( : m_data(new Data(
Get_Type_Info<T>()(), Get_Type_Info<T>()(),
boost::any(boost::shared_ptr<T>(new T(t))), boost::any(boost::shared_ptr<T>(new T(t))),
false) false,
) boost::shared_ptr<Data::Shared_Ptr_Proxy>(new Data::Shared_Ptr_Proxy_Impl<T>()))
)
{ {
boost::shared_ptr<T> *ptr = boost::any_cast<boost::shared_ptr<T> >(&m_data->m_obj); boost::shared_ptr<T> *ptr = boost::any_cast<boost::shared_ptr<T> >(&m_data->m_obj);
m_ptrs[ptr->get()] m_ptrs.insert(std::make_pair(ptr->get(), *m_data));
= m_data;
} }
Boxed_Value(Boxed_Value::Void_Type) Boxed_Value(Boxed_Value::Void_Type)
@ -163,17 +196,17 @@ class Boxed_Value
private: private:
boost::shared_ptr<Data> m_data; boost::shared_ptr<Data> m_data;
static std::map<void *, boost::shared_ptr<Data> > m_ptrs; static std::map<void *, Data > m_ptrs;
void cleanup_ptrs(std::map<void *, boost::shared_ptr<Data> > &m_ptrs) void cleanup_ptrs(std::map<void *, Data > &m_ptrs)
{ {
std::map<void *, boost::shared_ptr<Data> >::iterator itr = m_ptrs.begin(); std::map<void *, Data >::iterator itr = m_ptrs.begin();
while (itr != m_ptrs.end()) while (itr != m_ptrs.end())
{ {
if (itr->second.unique()) if (itr->second.m_ptr_proxy->unique(&itr->second.m_obj) == 1)
{ {
std::map<void *, boost::shared_ptr<Data> >::iterator todel = itr; std::map<void *, Data >::iterator todel = itr;
// std::cout << "Releasing unique ptr " << std::endl; // std::cout << "Releasing unique ptr " << std::endl;
++itr; ++itr;
m_ptrs.erase(todel); m_ptrs.erase(todel);
@ -186,7 +219,7 @@ class Boxed_Value
} }
}; };
std::map<void *, boost::shared_ptr<Boxed_Value::Data> > Boxed_Value::m_ptrs; std::map<void *, Boxed_Value::Data > Boxed_Value::m_ptrs;
//cast_help specializations //cast_help specializations
template<typename Result> template<typename Result>