Do not create an extra default instance of T when constructing a ThreadLocal<T>.

This commit is contained in:
kosak
2015-07-19 22:33:19 +00:00
parent 9e38d77f65
commit 831b87f234
2 changed files with 87 additions and 42 deletions

View File

@@ -1838,8 +1838,9 @@ class ThreadWithParam : public ThreadWithParamBase {
template <typename T>
class ThreadLocal : public ThreadLocalBase {
public:
ThreadLocal() : default_() {}
explicit ThreadLocal(const T& value) : default_(value) {}
ThreadLocal() : default_factory_(new DefaultValueHolderFactory()) {}
explicit ThreadLocal(const T& value)
: default_factory_(new InstanceValueHolderFactory(value)) {}
~ThreadLocal() { ThreadLocalRegistry::OnThreadLocalDestroyed(this); }
@@ -1853,6 +1854,7 @@ class ThreadLocal : public ThreadLocalBase {
// knowing the type of T.
class ValueHolder : public ThreadLocalValueHolderBase {
public:
ValueHolder() : value_() {}
explicit ValueHolder(const T& value) : value_(value) {}
T* pointer() { return &value_; }
@@ -1869,10 +1871,42 @@ class ThreadLocal : public ThreadLocalBase {
}
virtual ThreadLocalValueHolderBase* NewValueForCurrentThread() const {
return new ValueHolder(default_);
return default_factory_->MakeNewHolder();
}
const T default_; // The default value for each thread.
class ValueHolderFactory {
public:
ValueHolderFactory() {}
virtual ~ValueHolderFactory() {}
virtual ValueHolder* MakeNewHolder() const = 0;
private:
GTEST_DISALLOW_COPY_AND_ASSIGN_(ValueHolderFactory);
};
class DefaultValueHolderFactory : public ValueHolderFactory {
public:
DefaultValueHolderFactory() {}
virtual ValueHolder* MakeNewHolder() const { return new ValueHolder(); }
private:
GTEST_DISALLOW_COPY_AND_ASSIGN_(DefaultValueHolderFactory);
};
class InstanceValueHolderFactory : public ValueHolderFactory {
public:
explicit InstanceValueHolderFactory(const T& value) : value_(value) {}
virtual ValueHolder* MakeNewHolder() const {
return new ValueHolder(value_);
}
private:
const T value_; // The value for each thread.
GTEST_DISALLOW_COPY_AND_ASSIGN_(InstanceValueHolderFactory);
};
scoped_ptr<ValueHolderFactory> default_factory_;
GTEST_DISALLOW_COPY_AND_ASSIGN_(ThreadLocal);
};
@@ -1993,10 +2027,11 @@ extern "C" inline void DeleteThreadLocalValue(void* value_holder) {
template <typename T>
class ThreadLocal {
public:
ThreadLocal() : key_(CreateKey()),
default_() {}
explicit ThreadLocal(const T& value) : key_(CreateKey()),
default_(value) {}
ThreadLocal()
: key_(CreateKey()), default_factory_(new DefaultValueHolderFactory()) {}
explicit ThreadLocal(const T& value)
: key_(CreateKey()),
default_factory_(new InstanceValueHolderFactory(value)) {}
~ThreadLocal() {
// Destroys the managed object for the current thread, if any.
@@ -2016,6 +2051,7 @@ class ThreadLocal {
// Holds a value of type T.
class ValueHolder : public ThreadLocalValueHolderBase {
public:
ValueHolder() : value_() {}
explicit ValueHolder(const T& value) : value_(value) {}
T* pointer() { return &value_; }
@@ -2041,15 +2077,47 @@ class ThreadLocal {
return CheckedDowncastToActualType<ValueHolder>(holder)->pointer();
}
ValueHolder* const new_holder = new ValueHolder(default_);
ValueHolder* const new_holder = default_factory_->MakeNewHolder();
ThreadLocalValueHolderBase* const holder_base = new_holder;
GTEST_CHECK_POSIX_SUCCESS_(pthread_setspecific(key_, holder_base));
return new_holder->pointer();
}
class ValueHolderFactory {
public:
ValueHolderFactory() {}
virtual ~ValueHolderFactory() {}
virtual ValueHolder* MakeNewHolder() const = 0;
private:
GTEST_DISALLOW_COPY_AND_ASSIGN_(ValueHolderFactory);
};
class DefaultValueHolderFactory : public ValueHolderFactory {
public:
DefaultValueHolderFactory() {}
virtual ValueHolder* MakeNewHolder() const { return new ValueHolder(); }
private:
GTEST_DISALLOW_COPY_AND_ASSIGN_(DefaultValueHolderFactory);
};
class InstanceValueHolderFactory : public ValueHolderFactory {
public:
explicit InstanceValueHolderFactory(const T& value) : value_(value) {}
virtual ValueHolder* MakeNewHolder() const {
return new ValueHolder(value_);
}
private:
const T value_; // The value for each thread.
GTEST_DISALLOW_COPY_AND_ASSIGN_(InstanceValueHolderFactory);
};
// A key pthreads uses for looking up per-thread values.
const pthread_key_t key_;
const T default_; // The default value for each thread.
scoped_ptr<ValueHolderFactory> default_factory_;
GTEST_DISALLOW_COPY_AND_ASSIGN_(ThreadLocal);
};