Rip out object caching. With this removed it becomes that much more critical that we fix the scoping issue with references returned from temporaries.
This commit is contained in:
@@ -44,13 +44,6 @@ namespace chaiscript
|
|||||||
*/
|
*/
|
||||||
struct Data
|
struct Data
|
||||||
{
|
{
|
||||||
template<typename T>
|
|
||||||
static bool unique(boost::any *a)
|
|
||||||
{
|
|
||||||
boost::shared_ptr<T> *ptr = boost::any_cast<boost::shared_ptr<T> >(a);
|
|
||||||
return ptr->unique();
|
|
||||||
}
|
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
static bool is_null(boost::any *a)
|
static bool is_null(boost::any *a)
|
||||||
{
|
{
|
||||||
@@ -61,10 +54,9 @@ namespace chaiscript
|
|||||||
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 (boost::any*)> &t_unique = boost::function<bool (boost::any*)>(),
|
|
||||||
const boost::function<bool (boost::any*)> &t_is_null = boost::function<bool (boost::any*)>())
|
const boost::function<bool (boost::any*)> &t_is_null = boost::function<bool (boost::any*)>())
|
||||||
: m_type_info(ti), m_obj(to),
|
: m_type_info(ti), m_obj(to),
|
||||||
m_is_ref(tr), m_unique(t_unique), m_is_null(t_is_null)
|
m_is_ref(tr), m_is_null(t_is_null)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -73,7 +65,6 @@ namespace chaiscript
|
|||||||
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_unique = rhs.m_unique;
|
|
||||||
m_is_null = rhs.m_is_null;
|
m_is_null = rhs.m_is_null;
|
||||||
|
|
||||||
return *this;
|
return *this;
|
||||||
@@ -82,56 +73,12 @@ namespace chaiscript
|
|||||||
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::function<bool (boost::any*)> m_unique;
|
|
||||||
boost::function<bool (boost::any*)> m_is_null;
|
boost::function<bool (boost::any*)> m_is_null;
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
struct Object_Data
|
||||||
* Cache of all created objects in the dispatch kit. Used to return the
|
|
||||||
* same shared_ptr if the same object is created more than once.
|
|
||||||
* Also used for acquiring a shared_ptr of a reference object, if the
|
|
||||||
* value of the shared_ptr is known
|
|
||||||
*/
|
|
||||||
struct Object_Cache
|
|
||||||
{
|
{
|
||||||
struct Object_Cache_Key
|
static boost::shared_ptr<Data> get(Boxed_Value::Void_Type)
|
||||||
{
|
|
||||||
Object_Cache_Key(const void *t_obj, bool t_const, const std::type_info *t_objtype)
|
|
||||||
: m_obj(t_obj), m_const(t_const), m_objtype(t_objtype)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
bool operator<(const Object_Cache_Key &rhs) const
|
|
||||||
{
|
|
||||||
//Take into account the fact that sometimes there are equiv type_info objects
|
|
||||||
//that have different pointer values, so we have to dereference to use the built in
|
|
||||||
//comparison operator
|
|
||||||
return m_obj < rhs.m_obj
|
|
||||||
|| (m_obj == rhs.m_obj && m_const < rhs.m_const)
|
|
||||||
|| (m_obj == rhs.m_obj && m_const == rhs.m_const
|
|
||||||
&& m_objtype < rhs.m_objtype && !((*m_objtype) == (*rhs.m_objtype)));
|
|
||||||
}
|
|
||||||
|
|
||||||
bool operator==(const Object_Cache_Key &rhs) const
|
|
||||||
{
|
|
||||||
return m_obj == rhs.m_obj
|
|
||||||
&& m_const == rhs.m_const
|
|
||||||
&& (m_objtype == rhs.m_objtype || (*m_objtype) == (*rhs.m_objtype) );
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
const void *m_obj;
|
|
||||||
bool m_const;
|
|
||||||
const std::type_info *m_objtype;
|
|
||||||
};
|
|
||||||
|
|
||||||
Object_Cache()
|
|
||||||
: m_cullcount(0)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
boost::shared_ptr<Data> get(Boxed_Value::Void_Type)
|
|
||||||
{
|
{
|
||||||
return boost::shared_ptr<Data> (new Data(
|
return boost::shared_ptr<Data> (new Data(
|
||||||
detail::Get_Type_Info<void>::get(),
|
detail::Get_Type_Info<void>::get(),
|
||||||
@@ -141,95 +88,50 @@ namespace chaiscript
|
|||||||
}
|
}
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
boost::shared_ptr<Data> get(const boost::shared_ptr<T> *obj)
|
static boost::shared_ptr<Data> get(const boost::shared_ptr<T> *obj)
|
||||||
{
|
{
|
||||||
return get(*obj);
|
return get(*obj);
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
boost::shared_ptr<Data> get(const boost::shared_ptr<T> &obj)
|
static boost::shared_ptr<Data> get(const boost::shared_ptr<T> &obj)
|
||||||
{
|
{
|
||||||
bool b_const = boost::is_const<T>::value;
|
return boost::shared_ptr<Data>(new Data(
|
||||||
const std::type_info *ti = &typeid(typename Bare_Type<T>::type);
|
|
||||||
|
|
||||||
boost::shared_ptr<Data> data(new Data(
|
|
||||||
detail::Get_Type_Info<T>::get(),
|
detail::Get_Type_Info<T>::get(),
|
||||||
boost::any(obj),
|
boost::any(obj),
|
||||||
false,
|
false,
|
||||||
boost::function<bool (boost::any *)>(&Data::unique<T>),
|
|
||||||
boost::function<bool (boost::any *)>(&Data::is_null<T>))
|
boost::function<bool (boost::any *)>(&Data::is_null<T>))
|
||||||
);
|
);
|
||||||
|
|
||||||
std::map<Object_Cache_Key, Data>::iterator itr
|
|
||||||
= m_ptrs.find(Object_Cache_Key(obj.get(), b_const, ti));
|
|
||||||
|
|
||||||
if (itr != m_ptrs.end())
|
|
||||||
{
|
|
||||||
(*data) = (itr->second);
|
|
||||||
} else {
|
|
||||||
m_ptrs.insert(std::make_pair(Object_Cache_Key(obj.get(), b_const, ti), *data));
|
|
||||||
}
|
|
||||||
|
|
||||||
return data;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
boost::shared_ptr<Data> get(T *t)
|
static boost::shared_ptr<Data> get(T *t)
|
||||||
{
|
{
|
||||||
return get(boost::ref(*t));
|
return get(boost::ref(*t));
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
boost::shared_ptr<Data> get(boost::reference_wrapper<T> obj)
|
static boost::shared_ptr<Data> get(boost::reference_wrapper<T> obj)
|
||||||
{
|
{
|
||||||
bool b_const = boost::is_const<T>::value;
|
return boost::shared_ptr<Data>(new Data(
|
||||||
const std::type_info *ti = &typeid(typename Bare_Type<T>::type);
|
|
||||||
|
|
||||||
boost::shared_ptr<Data> data(new Data(
|
|
||||||
detail::Get_Type_Info<T>::get(),
|
detail::Get_Type_Info<T>::get(),
|
||||||
boost::any(obj),
|
boost::any(obj),
|
||||||
true)
|
true)
|
||||||
);
|
);
|
||||||
|
|
||||||
std::map<Object_Cache_Key, Data >::iterator itr
|
|
||||||
= m_ptrs.find(Object_Cache_Key(obj.get_pointer(), b_const, ti) );
|
|
||||||
|
|
||||||
// If the ptr is found in the cache and it is the correct type,
|
|
||||||
// return it. It may be the incorrect type when two variables share the
|
|
||||||
// same memory location. Example:
|
|
||||||
// struct test { int x; };
|
|
||||||
// test t;
|
|
||||||
// Both t and t.x share the same memory location, but do not represent
|
|
||||||
// objects of the same type.
|
|
||||||
if (itr != m_ptrs.end()
|
|
||||||
&& itr->second.m_type_info.bare_equal(data->m_type_info))
|
|
||||||
{
|
|
||||||
(*data) = (itr->second);
|
|
||||||
}
|
|
||||||
|
|
||||||
return data;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
boost::shared_ptr<Data> get(const T& t)
|
static boost::shared_ptr<Data> get(const T& t)
|
||||||
{
|
{
|
||||||
const std::type_info *ti = &typeid(typename Bare_Type<T>::type);
|
return boost::shared_ptr<Data>(new Data(
|
||||||
|
|
||||||
boost::shared_ptr<Data> data(new Data(
|
|
||||||
detail::Get_Type_Info<T>::get(),
|
detail::Get_Type_Info<T>::get(),
|
||||||
boost::any(boost::shared_ptr<T>(new T(t))),
|
boost::any(boost::shared_ptr<T>(new T(t))),
|
||||||
false,
|
false,
|
||||||
boost::function<bool (boost::any *)>(&Data::unique<T>),
|
|
||||||
boost::function<bool (boost::any *)>(&Data::is_null<T>))
|
boost::function<bool (boost::any *)>(&Data::is_null<T>))
|
||||||
);
|
);
|
||||||
|
|
||||||
boost::shared_ptr<T> *ptr = boost::any_cast<boost::shared_ptr<T> >(&data->m_obj);
|
|
||||||
|
|
||||||
m_ptrs.insert(std::make_pair(Object_Cache_Key(ptr->get(), false, ti), *data));
|
|
||||||
return data;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
boost::shared_ptr<Data> get()
|
static boost::shared_ptr<Data> get()
|
||||||
{
|
{
|
||||||
return boost::shared_ptr<Data> (new Data(
|
return boost::shared_ptr<Data> (new Data(
|
||||||
Type_Info(),
|
Type_Info(),
|
||||||
@@ -238,36 +140,6 @@ namespace chaiscript
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Drop objects from the cache where there is only one (ie, our)
|
|
||||||
* reference to it, so it may be destructed
|
|
||||||
*/
|
|
||||||
void cull(bool force = false)
|
|
||||||
{
|
|
||||||
|
|
||||||
++m_cullcount;
|
|
||||||
if (force || m_cullcount % 20 != 0)
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
std::map<Object_Cache_Key, Data>::iterator itr = m_ptrs.begin();
|
|
||||||
|
|
||||||
while (itr != m_ptrs.end())
|
|
||||||
{
|
|
||||||
if (itr->second.m_unique(&itr->second.m_obj))
|
|
||||||
{
|
|
||||||
std::map<Object_Cache_Key, Data >::iterator todel = itr;
|
|
||||||
++itr;
|
|
||||||
m_ptrs.erase(todel);
|
|
||||||
} else {
|
|
||||||
++itr;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
std::map<Object_Cache_Key, Data> m_ptrs;
|
|
||||||
int m_cullcount;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
public:
|
public:
|
||||||
@@ -276,9 +148,8 @@ namespace chaiscript
|
|||||||
*/
|
*/
|
||||||
template<typename T>
|
template<typename T>
|
||||||
explicit Boxed_Value(T t)
|
explicit Boxed_Value(T t)
|
||||||
: m_data(get_object_cache().get(t))
|
: m_data(Object_Data::get(t))
|
||||||
{
|
{
|
||||||
get_object_cache().cull();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -293,7 +164,7 @@ namespace chaiscript
|
|||||||
* Unknown-type constructor
|
* Unknown-type constructor
|
||||||
*/
|
*/
|
||||||
Boxed_Value()
|
Boxed_Value()
|
||||||
: m_data(get_object_cache().get())
|
: m_data(Object_Data::get())
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -306,20 +177,6 @@ namespace chaiscript
|
|||||||
std::swap(m_data, rhs.m_data);
|
std::swap(m_data, rhs.m_data);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Return a reference to the static global Object_Cache
|
|
||||||
*/
|
|
||||||
static Object_Cache &get_object_cache()
|
|
||||||
{
|
|
||||||
static chaiscript::threading::Thread_Storage<Object_Cache> oc;
|
|
||||||
return *oc;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void clear_cache()
|
|
||||||
{
|
|
||||||
get_object_cache().m_ptrs.clear();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* copy the values stored in rhs.m_data to m_data
|
* copy the values stored in rhs.m_data to m_data
|
||||||
* m_data pointers are not shared in this case
|
* m_data pointers are not shared in this case
|
||||||
|
@@ -232,9 +232,6 @@ namespace chaiscript
|
|||||||
~Dispatch_Engine()
|
~Dispatch_Engine()
|
||||||
{
|
{
|
||||||
detail::Dynamic_Conversions::get().cleanup(m_conversions.begin(), m_conversions.end());
|
detail::Dynamic_Conversions::get().cleanup(m_conversions.begin(), m_conversions.end());
|
||||||
|
|
||||||
Boxed_Value::clear_cache();
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
Reference in New Issue
Block a user