From 7ef1b8150476cb5d4339afe56919e04c956b49b2 Mon Sep 17 00:00:00 2001 From: Jason Turner Date: Mon, 15 Nov 2010 05:52:48 +0000 Subject: [PATCH] Simplify how functions are stored and passed. This is the first step in allowing us to sort functions so that dispatches are attempted in an organized order (as opposed to just the order they were added in). Should have resulted in a speed imrovement too - fewer string copies during dispatch. --- .../chaiscript/dispatchkit/dispatchkit.hpp | 121 ++++++++++-------- .../chaiscript/dispatchkit/function_call.hpp | 6 +- .../dispatchkit/function_call_detail.hpp | 13 +- .../dispatchkit/proxy_functions.hpp | 4 +- 4 files changed, 81 insertions(+), 63 deletions(-) diff --git a/include/chaiscript/dispatchkit/dispatchkit.hpp b/include/chaiscript/dispatchkit/dispatchkit.hpp index 15f6c00f..fe1e924d 100644 --- a/include/chaiscript/dispatchkit/dispatchkit.hpp +++ b/include/chaiscript/dispatchkit/dispatchkit.hpp @@ -119,7 +119,7 @@ namespace chaiscript class Dispatch_Function : public Proxy_Function_Base { public: - Dispatch_Function(const std::vector > &t_funcs) + Dispatch_Function(const std::vector &t_funcs) : Proxy_Function_Base(build_type_infos(t_funcs)), m_funcs(t_funcs) { @@ -139,39 +139,26 @@ namespace chaiscript virtual std::vector get_contained_functions() const { - typedef std::vector > function_vec; - - function_vec::const_iterator begin = m_funcs.begin(); - const function_vec::const_iterator end = m_funcs.end(); - - std::vector fs; - - while (begin != end) - { - fs.push_back(begin->second); - ++begin; - } - - return fs; + return std::vector(m_funcs.begin(), m_funcs.end()); } virtual int get_arity() const { - typedef std::vector > function_vec; + typedef std::vector function_vec; function_vec::const_iterator begin = m_funcs.begin(); const function_vec::const_iterator end = m_funcs.end(); if (begin != end) { - int arity = begin->second->get_arity(); + int arity = (*begin)->get_arity(); ++begin; while (begin != end) { - if (arity != begin->second->get_arity()) + if (arity != (*begin)->get_arity()) { // The arities in the list do not match, so it's unspecified return -1; @@ -188,14 +175,14 @@ namespace chaiscript virtual bool call_match(const std::vector &vals) const { - typedef std::vector > function_vec; + typedef std::vector function_vec; function_vec::const_iterator begin = m_funcs.begin(); function_vec::const_iterator end = m_funcs.end(); while (begin != end) { - if (begin->second->call_match(vals)) + if ((*begin)->call_match(vals)) { return true; } else { @@ -218,18 +205,18 @@ namespace chaiscript } private: - std::vector > m_funcs; + std::vector m_funcs; - static std::vector build_type_infos(const std::vector > &t_funcs) + static std::vector build_type_infos(const std::vector &t_funcs) { - typedef std::vector > function_vec; + typedef std::vector function_vec; function_vec::const_iterator begin = t_funcs.begin(); const function_vec::const_iterator end = t_funcs.end(); if (begin != end) { - std::vector type_infos = begin->second->get_param_types(); + std::vector type_infos = (*begin)->get_param_types(); ++begin; @@ -237,7 +224,7 @@ namespace chaiscript while (begin != end) { - std::vector param_types = begin->second->get_param_types(); + std::vector param_types = (*begin)->get_param_types(); if (param_types.size() != type_infos.size()) { @@ -316,7 +303,7 @@ namespace chaiscript struct State { - std::multimap m_functions; + std::map > m_functions; std::map m_global_objects; Type_Name_Map m_types; std::set m_reserved_words; @@ -486,23 +473,20 @@ namespace chaiscript } // If all that failed, then check to see if it's a function - std::vector::mapped_type> > funcs = get_function(name); + std::vector funcs = get_function(name); if (funcs.empty()) { throw std::range_error("Object not known: " + name); } else { - if (funcs.size() == 1) { // Return the first item if there is only one, // no reason to take the cast of the extra level of dispatch - return const_var(funcs.begin()->second); + return const_var(*funcs.begin()); + } else { + return Boxed_Value(Const_Proxy_Function(new Dispatch_Function(funcs))); } - - - Boxed_Value f(Const_Proxy_Function(new Dispatch_Function(funcs))); - return f; } } @@ -578,17 +562,25 @@ namespace chaiscript /** * Return a function by name */ - std::vector > + std::vector< Proxy_Function > get_function(const std::string &t_name) const { #ifndef CHAISCRIPT_NO_THREADS boost::shared_lock l(m_mutex); #endif - std::pair::const_iterator, std::multimap::const_iterator> range - = get_functions_int().equal_range(t_name); + const std::map > &funs = get_functions_int(); + + std::map >::const_iterator itr + = funs.find(t_name); + + if (itr != funs.end()) + { + return itr->second; + } else { + return std::vector(); + } - return std::vector::mapped_type> >(range.first, range.second); } /** @@ -600,7 +592,7 @@ namespace chaiscript boost::shared_lock l(m_mutex); #endif - const std::multimap &functions = get_functions_int(); + const std::map > &functions = get_functions_int(); return functions.find(name) != functions.end(); } @@ -612,9 +604,23 @@ namespace chaiscript #ifndef CHAISCRIPT_NO_THREADS boost::shared_lock l(m_mutex); #endif + std::vector > rets; - const std::multimap &functions = get_functions_int(); - return std::vector >(functions.begin(), functions.end()); + const std::map > &functions = get_functions_int(); + + for (std::map >::const_iterator itr = functions.begin(); + itr != functions.end(); + ++itr) + { + for (std::vector::const_iterator itr2 = itr->second.begin(); + itr2 != itr->second.end(); + ++itr2) + { + rets.push_back(std::make_pair(itr->first, *itr2)); + } + } + + return rets; } void add_reserved_word(const std::string &name) @@ -628,7 +634,7 @@ namespace chaiscript Boxed_Value call_function(const std::string &t_name, const std::vector ¶ms) const { - std::vector > functions = get_function(t_name); + std::vector functions = get_function(t_name); return dispatch(functions.begin(), functions.end(), params); } @@ -787,12 +793,12 @@ namespace chaiscript return *(m_stack_holder->stack); } - const std::multimap &get_functions_int() const + const std::map > &get_functions_int() const { return m_state.m_functions; } - std::multimap &get_functions_int() + std::map > &get_functions_int() { return m_state.m_functions; } @@ -818,25 +824,36 @@ namespace chaiscript * true if the function was added, false if a function with the * same signature and name already exists. */ - bool add_function(const Proxy_Function &f, const std::string &t_name) + bool add_function(const Proxy_Function &t_f, const std::string &t_name) { #ifndef CHAISCRIPT_NO_THREADS boost::unique_lock l(m_mutex); #endif - std::pair::const_iterator, std::multimap::const_iterator> range - = m_state.m_functions.equal_range(t_name); + std::map > &funcs = get_functions_int(); + + std::map >::iterator itr + = funcs.find(t_name); - while (range.first != range.second) + if (itr != funcs.end()) { - if ((*f) == *(range.first->second)) + std::vector &vec = itr->second; + for (std::vector::const_iterator itr2 = vec.begin(); + itr2 != vec.end(); + ++itr2) { - return false; + if ((*t_f) == *(*itr2)) + { + return false; + } } - ++range.first; - } - m_state.m_functions.insert(std::make_pair(t_name, f)); + vec.push_back(t_f); + } else { + std::vector vec; + vec.push_back(t_f); + funcs.insert(std::make_pair(t_name, vec)); + } return true; } diff --git a/include/chaiscript/dispatchkit/function_call.hpp b/include/chaiscript/dispatchkit/function_call.hpp index 746f476a..51899d14 100644 --- a/include/chaiscript/dispatchkit/function_call.hpp +++ b/include/chaiscript/dispatchkit/function_call.hpp @@ -30,7 +30,7 @@ namespace chaiscript */ template boost::function - functor(const std::vector > &funcs) + functor(const std::vector &funcs) { FunctionType *p=0; return detail::build_function_caller_helper(p, funcs); @@ -53,8 +53,8 @@ namespace chaiscript boost::function functor(Const_Proxy_Function func) { - std::vector > funcs; - funcs.push_back(std::make_pair(std::string(), func)); + std::vector funcs; + funcs.push_back(func); return functor(funcs); } diff --git a/include/chaiscript/dispatchkit/function_call_detail.hpp b/include/chaiscript/dispatchkit/function_call_detail.hpp index 1305c731..ab97d17f 100644 --- a/include/chaiscript/dispatchkit/function_call_detail.hpp +++ b/include/chaiscript/dispatchkit/function_call_detail.hpp @@ -32,7 +32,7 @@ namespace chaiscript template struct Function_Caller_Ret { - static Ret call(const std::vector > &t_funcs, + static Ret call(const std::vector &t_funcs, const std::vector ¶ms) { return boxed_cast(dispatch(t_funcs, params)); @@ -45,7 +45,7 @@ namespace chaiscript template<> struct Function_Caller_Ret { - static void call(const std::vector > &t_funcs, + static void call(const std::vector &t_funcs, const std::vector ¶ms) { dispatch(t_funcs, params); @@ -70,14 +70,14 @@ namespace chaiscript * used internally for unwrapping a function call's types */ template - Ret function_caller(const std::vector > &funcs + Ret function_caller(const std::vector &funcs BOOST_PP_COMMA_IF(n) BOOST_PP_ENUM_BINARY_PARAMS(n, Param, p) ) { std::vector params; BOOST_PP_REPEAT(n, addparam, ~) - return Function_Caller_Ret::call(funcs, params); + return Function_Caller_Ret::call(funcs, params); } /** @@ -85,13 +85,14 @@ namespace chaiscript */ template boost::function - build_function_caller_helper(Ret (BOOST_PP_ENUM_PARAMS(n, Param)), const std::vector > &funcs) + build_function_caller_helper(Ret (BOOST_PP_ENUM_PARAMS(n, Param)), const std::vector &funcs) { if (funcs.size() == 1) { boost::shared_ptr > pfi = boost::dynamic_pointer_cast > - (funcs[0].second); + (funcs[0]); + if (pfi) { return pfi->internal_function(); diff --git a/include/chaiscript/dispatchkit/proxy_functions.hpp b/include/chaiscript/dispatchkit/proxy_functions.hpp index 272198a3..e3a994f6 100644 --- a/include/chaiscript/dispatchkit/proxy_functions.hpp +++ b/include/chaiscript/dispatchkit/proxy_functions.hpp @@ -583,9 +583,9 @@ namespace chaiscript while (begin != end) { try { - if (begin->second->filter(plist)) + if ((*begin)->filter(plist)) { - return (*begin->second)(plist); + return (*(*begin))(plist); } } catch (const bad_boxed_cast &) { //parameter failed to cast, try again