diff options
| author | kosak <kosak@google.com> | 2015-07-19 22:33:19 +0000 | 
|---|---|---|
| committer | kosak <kosak@google.com> | 2015-07-19 22:33:19 +0000 | 
| commit | 831b87f2342df0ee2d13c466b400245bdf1c04f3 (patch) | |
| tree | 05f81c5fad59bc3d130ad3f4f884511340d2054d /include/gtest | |
| parent | 9e38d77f65eb35111701670608d8da223645e7e7 (diff) | |
| download | googletest-831b87f2342df0ee2d13c466b400245bdf1c04f3.tar.gz googletest-831b87f2342df0ee2d13c466b400245bdf1c04f3.tar.bz2 googletest-831b87f2342df0ee2d13c466b400245bdf1c04f3.zip  | |
Do not create an extra default instance of T when constructing a ThreadLocal<T>.
Diffstat (limited to 'include/gtest')
| -rw-r--r-- | include/gtest/internal/gtest-port.h | 88 | 
1 files changed, 78 insertions, 10 deletions
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 <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);  };  | 
