~30% performance improvement with threading enabled
This commit is contained in:
parent
4ace508339
commit
2bd1910c70
@ -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
|
||||
{
|
||||
|
@ -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();
|
||||
}
|
||||
}
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user