diff --git a/webrtc/base/BUILD.gn b/webrtc/base/BUILD.gn index 8d3140e400..6280903b58 100644 --- a/webrtc/base/BUILD.gn +++ b/webrtc/base/BUILD.gn @@ -508,6 +508,7 @@ rtc_static_library("rtc_base") { "optionsfile.cc", "optionsfile.h", "rollingaccumulator.h", + "scopedptrcollection.h", "sslroots.h", "testbase64.h", "testclient.cc", @@ -868,6 +869,7 @@ if (rtc_include_tests) { "rollingaccumulator_unittest.cc", "rtccertificate_unittest.cc", "rtccertificategenerator_unittest.cc", + "scopedptrcollection_unittest.cc", "sha1digest_unittest.cc", "sharedexclusivelock_unittest.cc", "signalthread_unittest.cc", diff --git a/webrtc/base/criticalsection_unittest.cc b/webrtc/base/criticalsection_unittest.cc index a16f4f2d4f..42679d987f 100644 --- a/webrtc/base/criticalsection_unittest.cc +++ b/webrtc/base/criticalsection_unittest.cc @@ -18,6 +18,7 @@ #include "webrtc/base/event.h" #include "webrtc/base/gunit.h" #include "webrtc/base/platform_thread.h" +#include "webrtc/base/scopedptrcollection.h" #include "webrtc/base/thread.h" namespace rtc { @@ -198,13 +199,13 @@ struct CompareAndSwapOp { static int AtomicOp(int* i) { return AtomicOps::CompareAndSwap(i, 0, 1); } }; -void StartThreads(std::vector>* threads, +void StartThreads(ScopedPtrCollection* threads, MessageHandler* handler) { for (int i = 0; i < kNumThreads; ++i) { - std::unique_ptr thread(new Thread()); + Thread* thread = new Thread(); thread->Start(); thread->Post(RTC_FROM_HERE, handler); - threads->push_back(std::move(thread)); + threads->PushBack(thread); } } @@ -247,7 +248,7 @@ TEST(AtomicOpsTest, SimplePtr) { TEST(AtomicOpsTest, Increment) { // Create and start lots of threads. AtomicOpRunner runner(0); - std::vector> threads; + ScopedPtrCollection threads; StartThreads(&threads, &runner); runner.SetExpectedThreadCount(kNumThreads); @@ -260,7 +261,7 @@ TEST(AtomicOpsTest, Decrement) { // Create and start lots of threads. AtomicOpRunner runner( kOperationsToRun * kNumThreads); - std::vector> threads; + ScopedPtrCollection threads; StartThreads(&threads, &runner); runner.SetExpectedThreadCount(kNumThreads); @@ -272,7 +273,7 @@ TEST(AtomicOpsTest, Decrement) { TEST(AtomicOpsTest, CompareAndSwap) { // Create and start lots of threads. AtomicOpRunner runner(0); - std::vector> threads; + ScopedPtrCollection threads; StartThreads(&threads, &runner); runner.SetExpectedThreadCount(kNumThreads); @@ -284,7 +285,7 @@ TEST(AtomicOpsTest, CompareAndSwap) { TEST(GlobalLockTest, Basic) { // Create and start lots of threads. LockRunner runner; - std::vector> threads; + ScopedPtrCollection threads; StartThreads(&threads, &runner); runner.SetExpectedThreadCount(kNumThreads); @@ -296,7 +297,7 @@ TEST(GlobalLockTest, Basic) { TEST(CriticalSectionTest, Basic) { // Create and start lots of threads. LockRunner runner; - std::vector> threads; + ScopedPtrCollection threads; StartThreads(&threads, &runner); runner.SetExpectedThreadCount(kNumThreads); diff --git a/webrtc/base/scopedptrcollection.h b/webrtc/base/scopedptrcollection.h new file mode 100644 index 0000000000..a4be035695 --- /dev/null +++ b/webrtc/base/scopedptrcollection.h @@ -0,0 +1,61 @@ +/* + * Copyright 2014 The WebRTC Project Authors. All rights reserved. + * + * Use of this source code is governed by a BSD-style license + * that can be found in the LICENSE file in the root of the source + * tree. An additional intellectual property rights grant can be found + * in the file PATENTS. All contributing project authors may + * be found in the AUTHORS file in the root of the source tree. + */ + +// Stores a collection of pointers that are deleted when the container is +// destructed. + +#ifndef WEBRTC_BASE_SCOPEDPTRCOLLECTION_H_ +#define WEBRTC_BASE_SCOPEDPTRCOLLECTION_H_ + +#include + +#include +#include + +#include "webrtc/base/constructormagic.h" + +namespace rtc { + +template +class ScopedPtrCollection { + public: + typedef std::vector VectorT; + + ScopedPtrCollection() { } + ~ScopedPtrCollection() { + for (typename VectorT::iterator it = collection_.begin(); + it != collection_.end(); ++it) { + delete *it; + } + } + + const VectorT& collection() const { return collection_; } + void Reserve(size_t size) { + collection_.reserve(size); + } + void PushBack(T* t) { + collection_.push_back(t); + } + + // Remove |t| from the collection without deleting it. + void Remove(T* t) { + collection_.erase(std::remove(collection_.begin(), collection_.end(), t), + collection_.end()); + } + + private: + VectorT collection_; + + RTC_DISALLOW_COPY_AND_ASSIGN(ScopedPtrCollection); +}; + +} // namespace rtc + +#endif // WEBRTC_BASE_SCOPEDPTRCOLLECTION_H_ diff --git a/webrtc/base/scopedptrcollection_unittest.cc b/webrtc/base/scopedptrcollection_unittest.cc new file mode 100644 index 0000000000..929fd0f324 --- /dev/null +++ b/webrtc/base/scopedptrcollection_unittest.cc @@ -0,0 +1,76 @@ +/* + * Copyright 2014 The WebRTC Project Authors. All rights reserved. + * + * Use of this source code is governed by a BSD-style license + * that can be found in the LICENSE file in the root of the source + * tree. An additional intellectual property rights grant can be found + * in the file PATENTS. All contributing project authors may + * be found in the AUTHORS file in the root of the source tree. + */ + +#include + +#include "webrtc/base/constructormagic.h" +#include "webrtc/base/scopedptrcollection.h" +#include "webrtc/base/gunit.h" + +namespace rtc { + +namespace { + +class InstanceCounter { + public: + explicit InstanceCounter(int* num_instances) + : num_instances_(num_instances) { + ++(*num_instances_); + } + ~InstanceCounter() { + --(*num_instances_); + } + + private: + int* num_instances_; + + RTC_DISALLOW_COPY_AND_ASSIGN(InstanceCounter); +}; + +} // namespace + +class ScopedPtrCollectionTest : public testing::Test { + protected: + ScopedPtrCollectionTest() + : num_instances_(0), + collection_(new ScopedPtrCollection()) { + } + + int num_instances_; + std::unique_ptr > collection_; +}; + +TEST_F(ScopedPtrCollectionTest, PushBack) { + EXPECT_EQ(0u, collection_->collection().size()); + EXPECT_EQ(0, num_instances_); + const int kNum = 100; + for (int i = 0; i < kNum; ++i) { + collection_->PushBack(new InstanceCounter(&num_instances_)); + } + EXPECT_EQ(static_cast(kNum), collection_->collection().size()); + EXPECT_EQ(kNum, num_instances_); + collection_.reset(); + EXPECT_EQ(0, num_instances_); +} + +TEST_F(ScopedPtrCollectionTest, Remove) { + InstanceCounter* ic = new InstanceCounter(&num_instances_); + collection_->PushBack(ic); + EXPECT_EQ(1u, collection_->collection().size()); + collection_->Remove(ic); + EXPECT_EQ(1, num_instances_); + collection_.reset(); + EXPECT_EQ(1, num_instances_); + delete ic; + EXPECT_EQ(0, num_instances_); +} + + +} // namespace rtc