Add shared objects that can be used by all threads at their root scope only
This commit is contained in:
@@ -13,6 +13,7 @@
|
|||||||
#include <set>
|
#include <set>
|
||||||
#include <boost/shared_ptr.hpp>
|
#include <boost/shared_ptr.hpp>
|
||||||
#include <boost/lexical_cast.hpp>
|
#include <boost/lexical_cast.hpp>
|
||||||
|
#include <boost/tuple/tuple.hpp>
|
||||||
#include <stdexcept>
|
#include <stdexcept>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
@@ -156,14 +157,14 @@ namespace chaiscript
|
|||||||
public:
|
public:
|
||||||
typedef std::map<std::string, chaiscript::Type_Info> Type_Name_Map;
|
typedef std::map<std::string, chaiscript::Type_Info> Type_Name_Map;
|
||||||
typedef std::map<std::string, Boxed_Value> Scope;
|
typedef std::map<std::string, Boxed_Value> Scope;
|
||||||
typedef std::pair<std::map<std::string, Boxed_Value>, std::deque<Scope> > StackData;
|
typedef boost::tuples::tuple<std::map<std::string, Boxed_Value>, std::deque<Scope>, bool> StackData;
|
||||||
typedef boost::shared_ptr<StackData> Stack;
|
typedef boost::shared_ptr<StackData> Stack;
|
||||||
|
|
||||||
Dispatch_Engine()
|
Dispatch_Engine()
|
||||||
: m_place_holder(boost::shared_ptr<Placeholder_Object>(new Placeholder_Object()))
|
: m_place_holder(boost::shared_ptr<Placeholder_Object>(new Placeholder_Object()))
|
||||||
{
|
{
|
||||||
StackData &stack = get_stack_data();
|
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);
|
validate_object_name(name);
|
||||||
|
|
||||||
StackData &stack = get_stack_data();
|
StackData &stack = get_stack_data();
|
||||||
stack.first.erase(name);
|
stack.get<0>().erase(name);
|
||||||
return add_function(f, name);
|
return add_function(f, name);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -195,13 +196,13 @@ namespace chaiscript
|
|||||||
validate_object_name(name);
|
validate_object_name(name);
|
||||||
StackData &stack = get_stack_data();
|
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<std::string, Boxed_Value>::const_iterator itr = (stack.second)[i].find(name);
|
std::map<std::string, Boxed_Value>::const_iterator itr = (stack.get<1>())[i].find(name);
|
||||||
if (itr != (stack.second)[i].end())
|
if (itr != (stack.get<1>())[i].end())
|
||||||
{
|
{
|
||||||
stack.first.erase(name);
|
stack.get<0>().erase(name);
|
||||||
(stack.second)[i][name] = Boxed_Value(obj);
|
(stack.get<1>())[i][name] = obj;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -216,8 +217,21 @@ namespace chaiscript
|
|||||||
{
|
{
|
||||||
StackData &stack = get_stack_data();
|
StackData &stack = get_stack_data();
|
||||||
validate_object_name(name);
|
validate_object_name(name);
|
||||||
stack.first.erase(name);
|
stack.get<0>().erase(name);
|
||||||
stack.second.back()[name] = Boxed_Value(obj);
|
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<boost::shared_mutex> l(m_shared_object_mutex);
|
||||||
|
m_shared_objects[name] = obj;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -226,7 +240,7 @@ namespace chaiscript
|
|||||||
void new_scope()
|
void new_scope()
|
||||||
{
|
{
|
||||||
StackData &stack = get_stack_data();
|
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()
|
void pop_scope()
|
||||||
{
|
{
|
||||||
StackData &stack = get_stack_data();
|
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();
|
for (Scope::const_iterator itr = scope.begin();
|
||||||
itr != scope.end();
|
itr != scope.end();
|
||||||
++itr)
|
++itr)
|
||||||
{
|
{
|
||||||
stack.first.erase(itr->first);
|
stack.get<0>().erase(itr->first);
|
||||||
}
|
}
|
||||||
stack.second.pop_back();
|
stack.get<1>().pop_back();
|
||||||
} else {
|
} else {
|
||||||
throw std::range_error("Unable to pop global stack");
|
throw std::range_error("Unable to pop global stack");
|
||||||
}
|
}
|
||||||
@@ -276,13 +290,14 @@ namespace chaiscript
|
|||||||
Stack new_stack() const
|
Stack new_stack() const
|
||||||
{
|
{
|
||||||
Stack s(new Stack::element_type());
|
Stack s(new Stack::element_type());
|
||||||
s->second.push_back(Scope());
|
s->get<1>().push_back(Scope());
|
||||||
|
s->get<2>() = false;
|
||||||
return s;
|
return s;
|
||||||
}
|
}
|
||||||
|
|
||||||
void sync_cache()
|
void sync_cache()
|
||||||
{
|
{
|
||||||
get_stack()->first.clear();
|
get_stack()->get<0>().clear();
|
||||||
boost::shared_lock<boost::shared_mutex> l(m_mutex);
|
boost::shared_lock<boost::shared_mutex> l(m_mutex);
|
||||||
get_function_cache() = m_functions;
|
get_function_cache() = m_functions;
|
||||||
}
|
}
|
||||||
@@ -294,30 +309,46 @@ namespace chaiscript
|
|||||||
*/
|
*/
|
||||||
Boxed_Value get_object(const std::string &name) const
|
Boxed_Value get_object(const std::string &name) const
|
||||||
{
|
{
|
||||||
|
// Is it a placeholder object?
|
||||||
if (name == "_")
|
if (name == "_")
|
||||||
{
|
{
|
||||||
return m_place_holder;
|
return m_place_holder;
|
||||||
}
|
}
|
||||||
|
|
||||||
StackData &stack = get_stack_data();
|
StackData &stack = get_stack_data();
|
||||||
std::map<std::string, Boxed_Value> &cache = stack.first;
|
std::map<std::string, Boxed_Value> &cache = stack.get<0>();
|
||||||
|
|
||||||
|
// Is it in the cache?
|
||||||
std::map<std::string, Boxed_Value>::const_iterator itr = cache.find(name);
|
std::map<std::string, Boxed_Value>::const_iterator itr = cache.find(name);
|
||||||
if (itr != cache.end())
|
if (itr != cache.end())
|
||||||
{
|
{
|
||||||
return itr->second;
|
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<std::string, Boxed_Value>::const_iterator itr = (stack.second)[i].find(name);
|
std::map<std::string, Boxed_Value>::const_iterator itr = (stack.get<1>())[i].find(name);
|
||||||
if (itr != (stack.second)[i].end())
|
if (itr != (stack.get<1>())[i].end())
|
||||||
{
|
{
|
||||||
cache[name] = itr->second;
|
cache[name] = itr->second;
|
||||||
return itr->second;
|
return itr->second;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Are we in the 0th stack and should check the shared objects?
|
||||||
|
if (stack.get<2>())
|
||||||
|
{
|
||||||
|
boost::shared_lock<boost::shared_mutex> 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<std::pair<std::string, std::multimap<std::string, Proxy_Function >::mapped_type> > funcs = get_function(name);
|
std::vector<std::pair<std::string, std::multimap<std::string, Proxy_Function >::mapped_type> > funcs = get_function(name);
|
||||||
|
|
||||||
if (funcs.empty())
|
if (funcs.empty())
|
||||||
@@ -451,6 +482,7 @@ namespace chaiscript
|
|||||||
if (!m_thread_stack.get())
|
if (!m_thread_stack.get())
|
||||||
{
|
{
|
||||||
m_thread_stack.reset(new Stack_Holder(new_stack()));
|
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_mutex;
|
||||||
|
mutable boost::shared_mutex m_shared_object_mutex;
|
||||||
|
|
||||||
struct Stack_Holder
|
struct Stack_Holder
|
||||||
{
|
{
|
||||||
@@ -511,6 +544,8 @@ namespace chaiscript
|
|||||||
mutable boost::thread_specific_ptr<Stack_Holder> m_thread_stack;
|
mutable boost::thread_specific_ptr<Stack_Holder> m_thread_stack;
|
||||||
|
|
||||||
std::multimap<std::string, Proxy_Function> m_functions;
|
std::multimap<std::string, Proxy_Function> m_functions;
|
||||||
|
std::map<std::string, Boxed_Value> m_shared_objects;
|
||||||
|
|
||||||
Type_Name_Map m_types;
|
Type_Name_Map m_types;
|
||||||
Boxed_Value m_place_holder;
|
Boxed_Value m_place_holder;
|
||||||
|
|
||||||
|
@@ -86,6 +86,15 @@ namespace chaiscript
|
|||||||
build_eval_system();
|
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
|
* Adds an object to the system: type, function, object
|
||||||
*/
|
*/
|
||||||
|
@@ -13,13 +13,15 @@
|
|||||||
|
|
||||||
void do_work(chaiscript::ChaiScript &c)
|
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[]) {
|
int main(int argc, char *argv[]) {
|
||||||
std::string input;
|
std::string input;
|
||||||
chaiscript::ChaiScript chai;
|
chaiscript::ChaiScript chai;
|
||||||
|
|
||||||
|
chai.add_shared_object(chaiscript::Boxed_Value(10000), "num_iterations");
|
||||||
|
|
||||||
std::vector<boost::shared_ptr<boost::thread> > threads;
|
std::vector<boost::shared_ptr<boost::thread> > threads;
|
||||||
|
|
||||||
for (int i = 0; i < argc - 1; ++i)
|
for (int i = 0; i < argc - 1; ++i)
|
||||||
|
@@ -1,7 +1,7 @@
|
|||||||
def do_chai_work()
|
def do_chai_work(num_iters)
|
||||||
{
|
{
|
||||||
var i = 0;
|
var i = 0;
|
||||||
for (var k = 0; k<100000; ++k)
|
for (var k = 0; k<num_iters * 10; ++k)
|
||||||
{
|
{
|
||||||
i += k;
|
i += k;
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user