From 831b87f2342df0ee2d13c466b400245bdf1c04f3 Mon Sep 17 00:00:00 2001 From: kosak Date: Sun, 19 Jul 2015 22:33:19 +0000 Subject: Do not create an extra default instance of T when constructing a ThreadLocal. --- include/gtest/internal/gtest-port.h | 88 ++++++++++++++++++++++++++++++++----- 1 file changed, 78 insertions(+), 10 deletions(-) (limited to 'include/gtest') diff --git a/include/gtest/internal/gtest-port.h b/include/gtest/internal/gtest-port.h index f6ed4d00..936dfd50 100644 --- a/include/gtest/internal/gtest-port.h +++ b/include/gtest/internal/gtest-port.h @@ -1838,8 +1838,9 @@ class ThreadWithParam : public ThreadWithParamBase { template 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 default_factory_; GTEST_DISALLOW_COPY_AND_ASSIGN_(ThreadLocal); }; @@ -1993,10 +2027,11 @@ extern "C" inline void DeleteThreadLocalValue(void* value_holder) { template 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(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 default_factory_; GTEST_DISALLOW_COPY_AND_ASSIGN_(ThreadLocal); }; -- cgit v1.2.3