diff --git a/include/chaiscript/dispatchkit/dispatchkit.hpp b/include/chaiscript/dispatchkit/dispatchkit.hpp index a7d021f..0fbfb1f 100644 --- a/include/chaiscript/dispatchkit/dispatchkit.hpp +++ b/include/chaiscript/dispatchkit/dispatchkit.hpp @@ -13,6 +13,7 @@ #include #include #include +#include #include #include #include @@ -156,14 +157,14 @@ namespace chaiscript public: typedef std::map Type_Name_Map; typedef std::map Scope; - typedef std::pair, std::deque > StackData; + typedef boost::tuples::tuple, std::deque, bool> StackData; typedef boost::shared_ptr Stack; Dispatch_Engine() : m_place_holder(boost::shared_ptr(new Placeholder_Object())) { StackData &stack = get_stack_data(); - stack.second.push_back(Scope()); + stack.get<1>().push_back(Scope()); } /** @@ -174,7 +175,7 @@ namespace chaiscript validate_object_name(name); StackData &stack = get_stack_data(); - stack.first.erase(name); + stack.get<0>().erase(name); return add_function(f, name); } @@ -195,13 +196,13 @@ namespace chaiscript validate_object_name(name); StackData &stack = get_stack_data(); - for (int i = stack.second.size()-1; i >= 0; --i) + for (int i = stack.get<1>().size()-1; i >= 0; --i) { - std::map::const_iterator itr = (stack.second)[i].find(name); - if (itr != (stack.second)[i].end()) + std::map::const_iterator itr = (stack.get<1>())[i].find(name); + if (itr != (stack.get<1>())[i].end()) { - stack.first.erase(name); - (stack.second)[i][name] = Boxed_Value(obj); + stack.get<0>().erase(name); + (stack.get<1>())[i][name] = obj; return; } } @@ -216,8 +217,21 @@ namespace chaiscript { StackData &stack = get_stack_data(); validate_object_name(name); - stack.first.erase(name); - stack.second.back()[name] = Boxed_Value(obj); + stack.get<0>().erase(name); + stack.get<1>().back()[name] = obj; + } + + /** + * Adds a new shared object, between all the threads + */ + void add_shared_object(const Boxed_Value &obj, const std::string &name) + { + StackData &stack = get_stack_data(); + validate_object_name(name); + stack.get<0>().erase(name); + + boost::unique_lock l(m_shared_object_mutex); + m_shared_objects[name] = obj; } /** @@ -226,7 +240,7 @@ namespace chaiscript void new_scope() { StackData &stack = get_stack_data(); - stack.second.push_back(Scope()); + stack.get<1>().push_back(Scope()); } /** @@ -235,16 +249,16 @@ namespace chaiscript void pop_scope() { StackData &stack = get_stack_data(); - if (stack.second.size() > 1) + if (stack.get<1>().size() > 1) { - Scope &scope(stack.second.back()); + Scope &scope(stack.get<1>().back()); for (Scope::const_iterator itr = scope.begin(); itr != scope.end(); ++itr) { - stack.first.erase(itr->first); + stack.get<0>().erase(itr->first); } - stack.second.pop_back(); + stack.get<1>().pop_back(); } else { throw std::range_error("Unable to pop global stack"); } @@ -276,13 +290,14 @@ namespace chaiscript Stack new_stack() const { Stack s(new Stack::element_type()); - s->second.push_back(Scope()); + s->get<1>().push_back(Scope()); + s->get<2>() = false; return s; } void sync_cache() { - get_stack()->first.clear(); + get_stack()->get<0>().clear(); boost::shared_lock l(m_mutex); get_function_cache() = m_functions; } @@ -294,30 +309,46 @@ namespace chaiscript */ Boxed_Value get_object(const std::string &name) const { + // Is it a placeholder object? if (name == "_") { return m_place_holder; } StackData &stack = get_stack_data(); - std::map &cache = stack.first; + std::map &cache = stack.get<0>(); + // Is it in the cache? std::map::const_iterator itr = cache.find(name); if (itr != cache.end()) { return itr->second; } - for (int i = stack.second.size()-1; i >= 0; --i) + // Is it in the stack? + for (int i = stack.get<1>().size()-1; i >= 0; --i) { - std::map::const_iterator itr = (stack.second)[i].find(name); - if (itr != (stack.second)[i].end()) + std::map::const_iterator itr = (stack.get<1>())[i].find(name); + if (itr != (stack.get<1>())[i].end()) { cache[name] = itr->second; return itr->second; } } + // Are we in the 0th stack and should check the shared objects? + if (stack.get<2>()) + { + boost::shared_lock l(m_shared_object_mutex); + itr = m_shared_objects.find(name); + if (itr != m_shared_objects.end()) + { + cache[name] = itr->second; + return itr->second; + } + } + + // If all that failed, then check to see if it's a function std::vector::mapped_type> > funcs = get_function(name); if (funcs.empty()) @@ -451,6 +482,7 @@ namespace chaiscript if (!m_thread_stack.get()) { m_thread_stack.reset(new Stack_Holder(new_stack())); + m_thread_stack->stack->get<2>() = true; } } @@ -495,6 +527,7 @@ namespace chaiscript } mutable boost::shared_mutex m_mutex; + mutable boost::shared_mutex m_shared_object_mutex; struct Stack_Holder { @@ -511,6 +544,8 @@ namespace chaiscript mutable boost::thread_specific_ptr m_thread_stack; std::multimap m_functions; + std::map m_shared_objects; + Type_Name_Map m_types; Boxed_Value m_place_holder; diff --git a/include/chaiscript/language/chaiscript_engine.hpp b/include/chaiscript/language/chaiscript_engine.hpp index 8d71987..058a6cc 100644 --- a/include/chaiscript/language/chaiscript_engine.hpp +++ b/include/chaiscript/language/chaiscript_engine.hpp @@ -86,6 +86,15 @@ namespace chaiscript build_eval_system(); } + /** + * Adds a shared object, that can be used by all threads, to the system + */ + ChaiScript_System &add_shared_object(const Boxed_Value &bv, const std::string &name) + { + engine.add_shared_object(bv, name); + return *this; + } + /** * Adds an object to the system: type, function, object */ diff --git a/src/multithreaded.cpp b/src/multithreaded.cpp index 9126ef9..3b78808 100644 --- a/src/multithreaded.cpp +++ b/src/multithreaded.cpp @@ -13,13 +13,15 @@ void do_work(chaiscript::ChaiScript &c) { - c("use(\"work.chai\"); do_chai_work();"); + c("use(\"work.chai\"); do_chai_work(num_iterations);"); } int main(int argc, char *argv[]) { std::string input; chaiscript::ChaiScript chai; + chai.add_shared_object(chaiscript::Boxed_Value(10000), "num_iterations"); + std::vector > threads; for (int i = 0; i < argc - 1; ++i) diff --git a/src/work.chai b/src/work.chai index c1afa47..c17470c 100644 --- a/src/work.chai +++ b/src/work.chai @@ -1,7 +1,7 @@ -def do_chai_work() +def do_chai_work(num_iters) { var i = 0; - for (var k = 0; k<100000; ++k) + for (var k = 0; k