~30% performance improvement with threading enabled

This commit is contained in:
Jason Turner 2014-04-05 22:49:50 -06:00
parent 4ace508339
commit 2bd1910c70
3 changed files with 64 additions and 22 deletions

View File

@ -64,8 +64,7 @@ namespace chaiscript
using std::recursive_mutex;
#ifdef CHAISCRIPT_HAS_THREAD_LOCAL
/// Typesafe thread specific storage. If threading is enabled, this class uses a mutex protected map. If
/// threading is not enabled, the class always returns the same data, regardless of which thread it is called from.
///
@ -74,6 +73,52 @@ namespace chaiscript
class Thread_Storage
{
public:
Thread_Storage(void *t_key)
: m_key(t_key)
{
}
~Thread_Storage()
{
t().erase(m_key);
}
inline T *operator->() const
{
return &(t()[m_key]);
}
inline T &operator*() const
{
return t()[m_key];
}
void *m_key;
private:
static std::unordered_map<void*, T> &t()
{
thread_local static std::unordered_map<void *, T> my_t;
return my_t;
}
};
#else
/// Typesafe thread specific storage. If threading is enabled, this class uses a mutex protected map. If
/// threading is not enabled, the class always returns the same data, regardless of which thread it is called from.
///
/// This version is used if the compiler does not support thread_local
template<typename T>
class Thread_Storage
{
public:
Thread_Storage(void *)
{
}
inline T *operator->() const
{
return get_tls().get();
@ -88,35 +133,26 @@ namespace chaiscript
private:
std::shared_ptr<T> get_tls() const
{
unique_lock<mutex> lock(m_mutex);
auto itr = m_instances.find(std::this_thread::get_id());
if (itr != m_instances.end()) { return itr->second; }
std::shared_ptr<T> new_instance(new T());
m_instances.insert(std::make_pair(std::this_thread::get_id(), new_instance));
return new_instance;
/*
static __thread std::shared_ptr<T> *m_data = 0;
if (!m_data) { m_data = new std::shared_ptr<T>(new T()); }
return *m_data;
*/
}
mutable mutex m_mutex;
mutable std::unordered_map<std::thread::id, std::shared_ptr<T> > m_instances;
};
#endif // threading enabled but no tls
#else
#else // threading disabled
template<typename T>
class unique_lock
{

View File

@ -411,7 +411,9 @@ namespace chaiscript
};
Dispatch_Engine()
: m_place_holder(std::shared_ptr<dispatch::Placeholder_Object>(new dispatch::Placeholder_Object()))
: m_stack_holder(this),
m_place_holder(std::shared_ptr<dispatch::Placeholder_Object>(new dispatch::Placeholder_Object()))
{
}
@ -745,8 +747,10 @@ namespace chaiscript
///
std::map<std::string, Boxed_Value> get_scripting_objects() const
{
Stack_Holder &s = *m_stack_holder;
// We don't want the current context, but one up if it exists
StackData &stack = (m_stack_holder->stacks.size()==1)?(*(m_stack_holder->stacks.back())):(*m_stack_holder->stacks[m_stack_holder->stacks.size()-2]);
StackData &stack = (s.stacks.size()==1)?(*(s.stacks.back())):(*s.stacks[s.stacks.size()-2]);
std::map<std::string, Boxed_Value> retval;
@ -991,7 +995,8 @@ namespace chaiscript
void save_function_params(const std::vector<Boxed_Value> &t_params)
{
m_stack_holder->call_params.insert(m_stack_holder->call_params.begin(), t_params.begin(), t_params.end());
Stack_Holder &s = *m_stack_holder;
s.call_params.insert(s.call_params.begin(), t_params.begin(), t_params.end());
}
void new_function_call()
@ -1001,15 +1006,16 @@ namespace chaiscript
void pop_function_call()
{
--m_stack_holder->call_depth;
Stack_Holder &s = *m_stack_holder;
--s.call_depth;
assert(m_stack_holder->call_depth >= 0);
assert(s.call_depth >= 0);
if (m_stack_holder->call_depth == 0)
if (s.call_depth == 0)
{
/// \todo Critical: this needs to be smarter, memory can expand quickly
/// in tight loops involving function calls
m_stack_holder->call_params.clear();
s.call_params.clear();
}
}