Move to QuickFlatMap from manual vector map thing

This commit is contained in:
Jason Turner 2017-11-23 22:38:15 -07:00
parent b47fec2f71
commit 48e5a46cbd
2 changed files with 85 additions and 60 deletions

View File

@ -36,6 +36,7 @@
#include "proxy_functions.hpp" #include "proxy_functions.hpp"
#include "type_info.hpp" #include "type_info.hpp"
#include "short_alloc.hpp" #include "short_alloc.hpp"
#include "../utility/quick_flat_map.hpp"
namespace chaiscript { namespace chaiscript {
class Boxed_Number; class Boxed_Number;
@ -388,7 +389,7 @@ namespace chaiscript
using SmallVector = std::vector<T>; using SmallVector = std::vector<T>;
using Scope = SmallVector<std::pair<std::string, Boxed_Value>>; using Scope = utility::QuickFlatMap<std::string, Boxed_Value>;
using StackData = SmallVector<Scope>; using StackData = SmallVector<Scope>;
using Stacks = SmallVector<StackData>; using Stacks = SmallVector<StackData>;
using Call_Param_List = SmallVector<Boxed_Value>; using Call_Param_List = SmallVector<Boxed_Value>;
@ -409,24 +410,13 @@ namespace chaiscript
void push_stack() void push_stack()
{ {
stacks.emplace_back(1); stacks.emplace_back(1);
// stacks.emplace_back(StackData(1, Scope(scope_allocator), stack_data_allocator));
} }
void push_call_params() void push_call_params()
{ {
call_params.emplace_back(); call_params.emplace_back();
// call_params.emplace_back(Call_Param_List(call_param_list_allocator));
} }
//Scope::allocator_type::arena_type scope_allocator;
//StackData::allocator_type::arena_type stack_data_allocator;
//Stacks::allocator_type::arena_type stacks_allocator;
//Call_Param_List::allocator_type::arena_type call_param_list_allocator;
//Call_Params::allocator_type::arena_type call_params_allocator;
// Stacks stacks = Stacks(stacks_allocator);
// Call_Params call_params = Call_Params(call_params_allocator);
Stacks stacks; Stacks stacks;
Call_Params call_params; Call_Params call_params;
@ -440,7 +430,7 @@ namespace chaiscript
public: public:
using Type_Name_Map = std::map<std::string, chaiscript::Type_Info, str_less>; using Type_Name_Map = std::map<std::string, chaiscript::Type_Info, str_less>;
using Scope = std::vector<std::pair<std::string, Boxed_Value>>; using Scope = utility::QuickFlatMap<std::string, Boxed_Value>;
using StackData = Stack_Holder::StackData; using StackData = Stack_Holder::StackData;
struct State struct State
@ -486,12 +476,7 @@ namespace chaiscript
for (auto stack_elem = stack.rbegin(); stack_elem != stack.rend(); ++stack_elem) for (auto stack_elem = stack.rbegin(); stack_elem != stack.rend(); ++stack_elem)
{ {
auto itr = std::find_if(stack_elem->begin(), stack_elem->end(), if (auto itr = stack_elem->find(name); itr != stack_elem->end())
[&](const std::pair<std::string, Boxed_Value> &o) {
return o.first == name;
});
if (itr != stack_elem->end())
{ {
itr->second = std::move(obj); itr->second = std::move(obj);
return; return;
@ -504,38 +489,32 @@ namespace chaiscript
/// Adds a named object to the current scope /// Adds a named object to the current scope
/// \warning This version does not check the validity of the name /// \warning This version does not check the validity of the name
/// it is meant for internal use only /// it is meant for internal use only
Boxed_Value &add_get_object(const std::string &t_name, Boxed_Value obj, Stack_Holder &t_holder) Boxed_Value &add_get_object(std::string t_name, Boxed_Value obj, Stack_Holder &t_holder)
{ {
auto &stack_elem = get_stack_data(t_holder).back(); auto &stack_elem = get_stack_data(t_holder).back();
if (std::any_of(stack_elem.begin(), stack_elem.end(), if (auto result = stack_elem.insert(std::pair{std::move(t_name), std::move(obj)}); result.second)
[&](const std::pair<std::string, Boxed_Value> &o) {
return o.first == t_name;
}))
{ {
throw chaiscript::exception::name_conflict_error(t_name); return result.first->second;
} else {
//insert failed
throw chaiscript::exception::name_conflict_error(result.first->first);
} }
return stack_elem.emplace_back(t_name, std::move(obj)).second;
} }
/// Adds a named object to the current scope /// Adds a named object to the current scope
/// \warning This version does not check the validity of the name /// \warning This version does not check the validity of the name
/// it is meant for internal use only /// it is meant for internal use only
void add_object(const std::string &t_name, Boxed_Value obj, Stack_Holder &t_holder) void add_object(std::string t_name, Boxed_Value obj, Stack_Holder &t_holder)
{ {
auto &stack_elem = get_stack_data(t_holder).back(); auto &stack_elem = get_stack_data(t_holder).back();
if (std::any_of(stack_elem.begin(), stack_elem.end(), if (auto result = stack_elem.insert(std::pair{std::move(t_name), std::move(obj)}); !result.second)
[&](const std::pair<std::string, Boxed_Value> &o) {
return o.first == t_name;
}))
{ {
throw chaiscript::exception::name_conflict_error(t_name); //insert failed
throw chaiscript::exception::name_conflict_error(result.first->first);
} }
stack_elem.emplace_back(t_name, std::move(obj));
} }
@ -566,46 +545,30 @@ namespace chaiscript
} }
/// Adds a new global (non-const) shared object, between all the threads /// Adds a new global (non-const) shared object, between all the threads
Boxed_Value add_global_no_throw(const Boxed_Value &obj, const std::string &name) Boxed_Value add_global_no_throw(Boxed_Value obj, std::string name)
{ {
chaiscript::detail::threading::unique_lock<chaiscript::detail::threading::shared_mutex> l(m_mutex); chaiscript::detail::threading::unique_lock<chaiscript::detail::threading::shared_mutex> l(m_mutex);
const auto itr = m_state.m_global_objects.find(name); return m_state.m_global_objects.insert(std::pair{std::move(name), std::move(obj)}).first->second;
if (itr == m_state.m_global_objects.end())
{
m_state.m_global_objects.insert(std::make_pair(name, obj));
return obj;
} else {
return itr->second;
}
} }
/// Adds a new global (non-const) shared object, between all the threads /// Adds a new global (non-const) shared object, between all the threads
void add_global(const Boxed_Value &obj, const std::string &name) void add_global(Boxed_Value obj, std::string name)
{ {
chaiscript::detail::threading::unique_lock<chaiscript::detail::threading::shared_mutex> l(m_mutex); chaiscript::detail::threading::unique_lock<chaiscript::detail::threading::shared_mutex> l(m_mutex);
if (m_state.m_global_objects.find(name) != m_state.m_global_objects.end()) if (auto result = m_state.m_global_objects.insert(std::pair{std::move(name), std::move(obj)}); !result.second) {
{ // insert failed
throw chaiscript::exception::name_conflict_error(name); throw chaiscript::exception::name_conflict_error(result.first->first);
} else {
m_state.m_global_objects.insert(std::make_pair(name, obj));
} }
} }
/// Updates an existing global shared object or adds a new global shared object if not found /// Updates an existing global shared object or adds a new global shared object if not found
void set_global(const Boxed_Value &obj, const std::string &name) void set_global(Boxed_Value obj, std::string name)
{ {
chaiscript::detail::threading::unique_lock<chaiscript::detail::threading::shared_mutex> l(m_mutex); chaiscript::detail::threading::unique_lock<chaiscript::detail::threading::shared_mutex> l(m_mutex);
m_state.m_global_objects.insert_or_assign(std::move(name), std::move(obj));
const auto itr = m_state.m_global_objects.find(name);
if (itr != m_state.m_global_objects.end())
{
itr->second.assign(obj);
} else {
m_state.m_global_objects.insert(std::make_pair(name, obj));
}
} }
/// Adds a new scope to the stack /// Adds a new scope to the stack
@ -688,7 +651,7 @@ namespace chaiscript
} else if ((loc & static_cast<uint_fast32_t>(Loc::is_local)) != 0u) { } else if ((loc & static_cast<uint_fast32_t>(Loc::is_local)) != 0u) {
auto &stack = get_stack_data(t_holder); auto &stack = get_stack_data(t_holder);
return stack[stack.size() - 1 - ((loc & static_cast<uint_fast32_t>(Loc::stack_mask)) >> 16)][loc & static_cast<uint_fast32_t>(Loc::loc_mask)].second; return stack[stack.size() - 1 - ((loc & static_cast<uint_fast32_t>(Loc::stack_mask)) >> 16)].at_index(loc & static_cast<uint_fast32_t>(Loc::loc_mask));
} }
// Is the value we are looking for a global or function? // Is the value we are looking for a global or function?

View File

@ -35,6 +35,14 @@ namespace chaiscript::utility {
return data.end(); return data.end();
} }
auto &back() noexcept {
return data.back();
}
const auto &back() const noexcept {
return data.back();
}
Value &operator[](const Key &s) { Value &operator[](const Key &s) {
const auto itr = find(s); const auto itr = find(s);
@ -45,6 +53,27 @@ namespace chaiscript::utility {
} }
} }
Value &at_index(const std::size_t idx) noexcept
{
return data[idx].second;
}
const Value &at_index(const std::size_t idx) const noexcept
{
return data[idx].second;
}
bool empty() const noexcept
{
return data.empty();
}
template<typename Itr>
void assign(Itr begin, Itr end)
{
data.assign(begin, end);
}
Value &at(const Key &s) { Value &at(const Key &s) {
const auto itr = find(s); const auto itr = find(s);
if (itr != data.end()) { if (itr != data.end()) {
@ -54,6 +83,30 @@ namespace chaiscript::utility {
} }
} }
template<typename M>
auto insert_or_assign(Key &&key, M &&m)
{
if (auto itr = find(key); itr != data.end()) {
*itr = std::forward<M>(m);
return std::pair{itr, false};
} else {
return std::pair{data.emplace(itr, std::move(key), std::forward<M>(m)), true};
}
}
template<typename M>
auto insert_or_assign(const Key &key, M &&m)
{
if (auto itr = find(key); itr != data.end()) {
*itr = std::forward<M>(m);
return std::pair{itr, false};
} else {
return std::pair{data.emplace(itr, key, std::forward<M>(m)), true};
}
}
const Value &at(const Key &s) const { const Value &at(const Key &s) const {
const auto itr = find(s); const auto itr = find(s);
if (itr != data.end()) { if (itr != data.end()) {
@ -69,9 +122,18 @@ namespace chaiscript::utility {
std::vector<std::pair<Key, Value>> data; std::vector<std::pair<Key, Value>> data;
using value_type = std::pair<Key, Value>;
using iterator = typename decltype(data)::iterator; using iterator = typename decltype(data)::iterator;
using const_iterator = typename decltype(data)::const_iterator; using const_iterator = typename decltype(data)::const_iterator;
std::pair<iterator,bool> insert( value_type&& value )
{
if (const auto itr = find(value.first); itr != data.end()) {
return std::pair{itr, false};
} else {
return std::pair{data.insert(itr, std::move(value)), true};
}
}
}; };