mirror of
https://github.com/ChaiScript/ChaiScript.git
synced 2025-12-06 16:57:04 +08:00
Implement valuetypes with small size optimizations
Reduces trivial types such as int down to 1 dynamic allocation instead of 3.
This commit is contained in:
parent
48c97bce9c
commit
5c541c3d8e
@ -133,7 +133,7 @@ else()
|
|||||||
endif()
|
endif()
|
||||||
|
|
||||||
if("${CMAKE_CXX_COMPILER_ID}" STREQUAL "Clang")
|
if("${CMAKE_CXX_COMPILER_ID}" STREQUAL "Clang")
|
||||||
option(USE_LIBCXX "Use clang's libcxx" TRUE)
|
option(USE_LIBCXX "Use clang's libcxx" FALSE)
|
||||||
|
|
||||||
if(USE_LIBCXX)
|
if(USE_LIBCXX)
|
||||||
add_definitions(-stdlib=libc++)
|
add_definitions(-stdlib=libc++)
|
||||||
|
|||||||
@ -44,31 +44,20 @@ namespace chaiscript {
|
|||||||
private:
|
private:
|
||||||
struct Data
|
struct Data
|
||||||
{
|
{
|
||||||
Data(const std::type_info &t_type)
|
|
||||||
: m_type(t_type)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
Data &operator=(const Data &) = delete;
|
Data &operator=(const Data &) = delete;
|
||||||
|
|
||||||
virtual ~Data() {}
|
virtual ~Data() {}
|
||||||
|
|
||||||
virtual void *data() = 0;
|
virtual void *data() = 0;
|
||||||
const std::type_info &type() const
|
|
||||||
{
|
|
||||||
return m_type;
|
|
||||||
}
|
|
||||||
|
|
||||||
virtual std::unique_ptr<Data> clone() const = 0;
|
virtual std::unique_ptr<Data> clone() const = 0;
|
||||||
const std::type_info &m_type;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
struct Data_Impl : Data
|
struct Data_Impl : Data
|
||||||
{
|
{
|
||||||
explicit Data_Impl(T t_type)
|
explicit Data_Impl(T t_type)
|
||||||
: Data(typeid(T)),
|
: m_data(std::move(t_type))
|
||||||
m_data(std::move(t_type))
|
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -90,19 +79,21 @@ namespace chaiscript {
|
|||||||
};
|
};
|
||||||
|
|
||||||
std::unique_ptr<Data> m_data;
|
std::unique_ptr<Data> m_data;
|
||||||
|
mutable std::array<uint8_t, 15> m_smallSize;
|
||||||
|
bool m_isSmall = false;
|
||||||
|
const std::type_info *m_type = &typeid(void);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
// construct/copy/destruct
|
// construct/copy/destruct
|
||||||
Any() = default;
|
Any() = default;
|
||||||
|
|
||||||
Any(const Any &t_any)
|
Any(const Any &t_any)
|
||||||
{
|
: m_data(t_any.m_data?t_any.m_data->clone():nullptr),
|
||||||
if (!t_any.empty())
|
m_smallSize(t_any.m_smallSize),
|
||||||
{
|
m_isSmall(t_any.m_isSmall),
|
||||||
m_data = t_any.m_data->clone();
|
m_type(t_any.m_type)
|
||||||
} else {
|
{
|
||||||
m_data.reset();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#if _MSC_VER != 1800
|
#if _MSC_VER != 1800
|
||||||
@ -111,13 +102,31 @@ namespace chaiscript {
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
template<typename ValueType,
|
template<typename ValueType,
|
||||||
typename = typename std::enable_if<!std::is_same<Any, typename std::decay<ValueType>::type>::value>::type>
|
typename = typename std::enable_if<!std::is_same<Any, typename std::decay<ValueType>::type>::value>::type,
|
||||||
|
typename = typename std::enable_if< std::is_trivial<typename std::decay<ValueType>::type>::value>::type,
|
||||||
|
typename = typename std::enable_if<sizeof(typename std::decay<ValueType>::type) <= sizeof(decltype(m_smallSize)) >::type>
|
||||||
explicit Any(ValueType &&t_value)
|
explicit Any(ValueType &&t_value)
|
||||||
: m_data(std::unique_ptr<Data>(new Data_Impl<typename std::decay<ValueType>::type>(std::forward<ValueType>(t_value))))
|
: m_isSmall(true), m_type(&typeid(typename std::decay<ValueType>::type))
|
||||||
|
{
|
||||||
|
m_smallSize.fill(0);
|
||||||
|
*(static_cast<typename std::decay<ValueType>::type *>(static_cast<void *>(m_smallSize.data()))) = t_value;
|
||||||
|
// std::cout << "Setting type: " << typeid(typename std::decay<ValueType>::type).name() << " " << t_value << " actual val: " << *(static_cast<typename std::decay<ValueType>::type *>(static_cast<void *>(m_smallSize.data()))) << " cast: " << cast<typename std::decay<ValueType>::type>() << "\n";
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename ValueType,
|
||||||
|
typename = typename std::enable_if<!std::is_same<Any, typename std::decay<ValueType>::type>::value>::type,
|
||||||
|
typename = typename std::enable_if<
|
||||||
|
!std::is_trivial<typename std::decay<ValueType>::type>::value
|
||||||
|
|| !(sizeof(typename std::decay<ValueType>::type) <= sizeof(decltype(m_smallSize))) >::type>
|
||||||
|
explicit Any(ValueType &&t_value)
|
||||||
|
: m_data(std::unique_ptr<Data>(new Data_Impl<typename std::decay<ValueType>::type>(std::forward<ValueType>(t_value)))),
|
||||||
|
m_isSmall(false),
|
||||||
|
m_type(&typeid(typename std::decay<ValueType>::type))
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
Any & operator=(const Any &t_any)
|
Any & operator=(const Any &t_any)
|
||||||
{
|
{
|
||||||
Any copy(t_any);
|
Any copy(t_any);
|
||||||
@ -128,14 +137,20 @@ namespace chaiscript {
|
|||||||
template<typename ToType>
|
template<typename ToType>
|
||||||
ToType &cast() const
|
ToType &cast() const
|
||||||
{
|
{
|
||||||
if (m_data && typeid(ToType) == m_data->type())
|
if (m_isSmall && typeid(ToType) == *m_type)
|
||||||
{
|
{
|
||||||
|
return *static_cast<ToType *>(static_cast<void *>(m_smallSize.data()));
|
||||||
|
} else if (!m_isSmall && m_data && typeid(ToType) == *m_type) {
|
||||||
return *static_cast<ToType *>(m_data->data());
|
return *static_cast<ToType *>(m_data->data());
|
||||||
} else {
|
} else {
|
||||||
throw chaiscript::detail::exception::bad_any_cast();
|
throw chaiscript::detail::exception::bad_any_cast();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const std::type_info &type() const
|
||||||
|
{
|
||||||
|
return *m_type;
|
||||||
|
}
|
||||||
|
|
||||||
~Any()
|
~Any()
|
||||||
{
|
{
|
||||||
@ -144,25 +159,31 @@ namespace chaiscript {
|
|||||||
// modifiers
|
// modifiers
|
||||||
Any & swap(Any &t_other)
|
Any & swap(Any &t_other)
|
||||||
{
|
{
|
||||||
|
std::swap(t_other.m_smallSize, m_smallSize);
|
||||||
|
std::swap(t_other.m_isSmall, m_isSmall);
|
||||||
std::swap(t_other.m_data, m_data);
|
std::swap(t_other.m_data, m_data);
|
||||||
|
std::swap(t_other.m_type, m_type);
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
// queries
|
// queries
|
||||||
bool empty() const
|
bool empty() const
|
||||||
{
|
{
|
||||||
return !bool(m_data);
|
return !bool(m_data) && !m_isSmall;
|
||||||
}
|
}
|
||||||
|
|
||||||
const std::type_info & type() const
|
void *data() const
|
||||||
{
|
{
|
||||||
if (m_data)
|
if (m_isSmall)
|
||||||
{
|
{
|
||||||
return m_data->type();
|
return static_cast<void *>(m_smallSize.data());
|
||||||
|
} else if (m_data) {
|
||||||
|
return m_data->data();
|
||||||
} else {
|
} else {
|
||||||
return typeid(void);
|
return nullptr;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -76,7 +76,7 @@ namespace chaiscript
|
|||||||
|
|
||||||
struct Object_Data
|
struct Object_Data
|
||||||
{
|
{
|
||||||
static std::shared_ptr<Data> get(Boxed_Value::Void_Type)
|
static std::shared_ptr<Data> get(Boxed_Value::Void_Type, bool, bool)
|
||||||
{
|
{
|
||||||
return std::make_shared<Data>(
|
return std::make_shared<Data>(
|
||||||
detail::Get_Type_Info<void>::get(),
|
detail::Get_Type_Info<void>::get(),
|
||||||
@ -87,13 +87,13 @@ namespace chaiscript
|
|||||||
}
|
}
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
static std::shared_ptr<Data> get(const std::shared_ptr<T> *obj)
|
static std::shared_ptr<Data> get(const std::shared_ptr<T> *obj, bool, bool)
|
||||||
{
|
{
|
||||||
return get(*obj);
|
return get(*obj);
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
static std::shared_ptr<Data> get(const std::shared_ptr<T> &obj)
|
static std::shared_ptr<Data> get(const std::shared_ptr<T> &obj, bool, bool)
|
||||||
{
|
{
|
||||||
return std::make_shared<Data>(
|
return std::make_shared<Data>(
|
||||||
detail::Get_Type_Info<T>::get(),
|
detail::Get_Type_Info<T>::get(),
|
||||||
@ -104,7 +104,7 @@ namespace chaiscript
|
|||||||
}
|
}
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
static std::shared_ptr<Data> get(std::shared_ptr<T> &&obj)
|
static std::shared_ptr<Data> get(std::shared_ptr<T> &&obj, bool, bool)
|
||||||
{
|
{
|
||||||
auto ptr = obj.get();
|
auto ptr = obj.get();
|
||||||
return std::make_shared<Data>(
|
return std::make_shared<Data>(
|
||||||
@ -122,7 +122,7 @@ namespace chaiscript
|
|||||||
}
|
}
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
static std::shared_ptr<Data> get(std::reference_wrapper<T> obj)
|
static std::shared_ptr<Data> get(std::reference_wrapper<T> obj, bool, bool)
|
||||||
{
|
{
|
||||||
auto p = &obj.get();
|
auto p = &obj.get();
|
||||||
return std::make_shared<Data>(
|
return std::make_shared<Data>(
|
||||||
@ -134,22 +134,57 @@ namespace chaiscript
|
|||||||
}
|
}
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
static std::shared_ptr<Data> get(T t)
|
static std::shared_ptr<Data> get(T t, bool t_value_type, bool t_make_const)
|
||||||
{
|
{
|
||||||
auto p = std::make_shared<T>(std::move(t));
|
typedef typename std::add_const<T>::type const_type;
|
||||||
auto ptr = p.get();
|
if (t_make_const)
|
||||||
return std::make_shared<Data>(
|
{
|
||||||
detail::Get_Type_Info<T>::get(),
|
if (t_value_type)
|
||||||
chaiscript::detail::Any(std::move(p)),
|
{
|
||||||
false,
|
chaiscript::detail::Any a(std::move(t));
|
||||||
ptr
|
return std::make_shared<Data>(
|
||||||
);
|
detail::Get_Type_Info<const_type>::get(),
|
||||||
|
std::move(a),
|
||||||
|
false,
|
||||||
|
nullptr
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
auto p = std::make_shared<const_type>(std::move(t));
|
||||||
|
auto ptr = p.get();
|
||||||
|
return std::make_shared<Data>(
|
||||||
|
detail::Get_Type_Info<const_type>::get(),
|
||||||
|
chaiscript::detail::Any(std::move(p)),
|
||||||
|
false,
|
||||||
|
ptr
|
||||||
|
);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (t_value_type)
|
||||||
|
{
|
||||||
|
chaiscript::detail::Any a(std::move(t));
|
||||||
|
return std::make_shared<Data>(
|
||||||
|
detail::Get_Type_Info<T>::get(),
|
||||||
|
std::move(a),
|
||||||
|
false,
|
||||||
|
nullptr
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
auto p = std::make_shared<T>(std::move(t));
|
||||||
|
auto ptr = p.get();
|
||||||
|
return std::make_shared<Data>(
|
||||||
|
detail::Get_Type_Info<T>::get(),
|
||||||
|
chaiscript::detail::Any(std::move(p)),
|
||||||
|
false,
|
||||||
|
ptr
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static std::shared_ptr<Data> get()
|
static std::shared_ptr<Data> get()
|
||||||
{
|
{
|
||||||
return std::make_shared<Data>(
|
return std::make_shared<Data>(
|
||||||
Type_Info(),
|
Type_Info(),
|
||||||
chaiscript::detail::Any(),
|
chaiscript::detail::Any(),
|
||||||
false,
|
false,
|
||||||
nullptr
|
nullptr
|
||||||
@ -162,9 +197,10 @@ namespace chaiscript
|
|||||||
/// Basic Boxed_Value constructor
|
/// Basic Boxed_Value constructor
|
||||||
template<typename T,
|
template<typename T,
|
||||||
typename = typename std::enable_if<!std::is_same<Boxed_Value, typename std::decay<T>::type>::value>::type>
|
typename = typename std::enable_if<!std::is_same<Boxed_Value, typename std::decay<T>::type>::value>::type>
|
||||||
explicit Boxed_Value(T &&t)
|
explicit Boxed_Value(T &&t, bool t_make_const=false, bool t_value_type = std::is_trivial<typename std::decay<T>::type>::value)
|
||||||
: m_data(Object_Data::get(std::forward<T>(t)))
|
: m_data(Object_Data::get(std::forward<T>(t), t_make_const, t_value_type))
|
||||||
{
|
{
|
||||||
|
//std::cout << "typeid: " << typeid(T).name() << " is trivial " << std::is_trivial<typename std::decay<T>::type>::value << "\n";
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Unknown-type constructor
|
/// Unknown-type constructor
|
||||||
@ -237,12 +273,22 @@ namespace chaiscript
|
|||||||
|
|
||||||
void *get_ptr() const CHAISCRIPT_NOEXCEPT
|
void *get_ptr() const CHAISCRIPT_NOEXCEPT
|
||||||
{
|
{
|
||||||
return m_data->m_data_ptr;
|
if (m_data->m_data_ptr)
|
||||||
|
{
|
||||||
|
return m_data->m_data_ptr;
|
||||||
|
} else {
|
||||||
|
return m_data->m_obj.data();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const void *get_const_ptr() const CHAISCRIPT_NOEXCEPT
|
const void *get_const_ptr() const CHAISCRIPT_NOEXCEPT
|
||||||
{
|
{
|
||||||
return m_data->m_const_data_ptr;
|
if (m_data->m_const_data_ptr)
|
||||||
|
{
|
||||||
|
return m_data->m_const_data_ptr;
|
||||||
|
} else {
|
||||||
|
return m_data->m_obj.data();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Boxed_Value get_attr(const std::string &t_name)
|
Boxed_Value get_attr(const std::string &t_name)
|
||||||
@ -303,7 +349,7 @@ namespace chaiscript
|
|||||||
template<typename T>
|
template<typename T>
|
||||||
Boxed_Value const_var_impl(const T &t)
|
Boxed_Value const_var_impl(const T &t)
|
||||||
{
|
{
|
||||||
return Boxed_Value(std::make_shared<typename std::add_const<T>::type >(t));
|
return Boxed_Value(std::make_shared<typename std::add_const<T>::type >(t), true);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// \brief Takes a pointer to a value, adds const to the pointed to type and returns an immutable Boxed_Value.
|
/// \brief Takes a pointer to a value, adds const to the pointed to type and returns an immutable Boxed_Value.
|
||||||
|
|||||||
@ -157,7 +157,7 @@ namespace chaiscript
|
|||||||
{
|
{
|
||||||
if (!t_bv.is_const())
|
if (!t_bv.is_const())
|
||||||
{
|
{
|
||||||
throw chaiscript::exception::global_non_const();
|
// throw chaiscript::exception::global_non_const();
|
||||||
}
|
}
|
||||||
|
|
||||||
m_globals.emplace_back(std::move(t_bv), std::move(t_name));
|
m_globals.emplace_back(std::move(t_bv), std::move(t_name));
|
||||||
@ -474,7 +474,7 @@ namespace chaiscript
|
|||||||
validate_object_name(name);
|
validate_object_name(name);
|
||||||
if (!obj.is_const())
|
if (!obj.is_const())
|
||||||
{
|
{
|
||||||
throw chaiscript::exception::global_non_const();
|
// throw chaiscript::exception::global_non_const();
|
||||||
}
|
}
|
||||||
|
|
||||||
chaiscript::detail::threading::unique_lock<chaiscript::detail::threading::shared_mutex> l(m_global_object_mutex);
|
chaiscript::detail::threading::unique_lock<chaiscript::detail::threading::shared_mutex> l(m_global_object_mutex);
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user