Change RefCountedObject to use perfect forwarding.
The main reason for doing this is to allow refcounted objects to accept rvalue references in ctor and be able to std::move ctor rvalue arguments.
Also, refcounted.h is now generated using pump.py instead of manually creating each ctor version.
BUG= none
Review-Url: https://codereview.webrtc.org/2425683003
Cr-Original-Commit-Position: refs/heads/master@{#14687}
Cr-Mirrored-From: https://chromium.googlesource.com/external/webrtc
Cr-Mirrored-Commit: 0489e498ebef75e13b7d72e7470903d3bcae50b4
diff --git a/BUILD.gn b/BUILD.gn
index 9f1fd0b..1cdc94b 100644
--- a/BUILD.gn
+++ b/BUILD.gn
@@ -383,6 +383,7 @@
"base/rate_statistics_unittest.cc",
"base/ratelimiter_unittest.cc",
"base/ratetracker_unittest.cc",
+ "base/refcountedobject_unittest.cc",
"base/rollingaccumulator_unittest.cc",
"base/rtccertificate_unittest.cc",
"base/rtccertificategenerator_unittest.cc",
diff --git a/base/BUILD.gn b/base/BUILD.gn
index aa62054..908c7b7 100644
--- a/base/BUILD.gn
+++ b/base/BUILD.gn
@@ -148,6 +148,7 @@
"ratetracker.cc",
"ratetracker.h",
"refcount.h",
+ "refcountedobject.h",
"safe_conversions.h",
"safe_conversions_impl.h",
"sanitizer.h",
diff --git a/base/refcount.h b/base/refcount.h
index 9e881c8..565ae49 100644
--- a/base/refcount.h
+++ b/base/refcount.h
@@ -7,14 +7,10 @@
* in the file PATENTS. All contributing project authors may
* be found in the AUTHORS file in the root of the source tree.
*/
-
#ifndef WEBRTC_BASE_REFCOUNT_H_
#define WEBRTC_BASE_REFCOUNT_H_
-#include <string.h>
-#include <utility>
-
-#include "webrtc/base/atomicops.h"
+#include "webrtc/base/refcountedobject.h"
namespace rtc {
@@ -28,151 +24,6 @@
virtual ~RefCountInterface() {}
};
-template <class T>
-class RefCountedObject : public T {
- public:
- RefCountedObject() {}
-
- template <typename P>
- explicit RefCountedObject(const P& p) : T(p) {}
-
- template <typename P>
- explicit RefCountedObject(P&& p) : T(std::move(p)) {}
-
- template <typename P1, typename P2>
- RefCountedObject(P1 p1, P2 p2) : T(p1, p2) {}
-
- template <typename P1, typename P2, typename P3>
- RefCountedObject(P1 p1, P2 p2, P3 p3) : T(p1, p2, p3) {}
-
- template <typename P1, typename P2, typename P3, typename P4>
- RefCountedObject(P1 p1, P2 p2, P3 p3, P4 p4) : T(p1, p2, p3, p4) {}
-
- template <typename P1, typename P2, typename P3, typename P4, typename P5>
- RefCountedObject(P1 p1, P2 p2, P3 p3, P4 p4, P5 p5) : T(p1, p2, p3, p4, p5) {}
-
- template <typename P1,
- typename P2,
- typename P3,
- typename P4,
- typename P5,
- typename P6>
- RefCountedObject(P1 p1, P2 p2, P3 p3, P4 p4, P5 p5, P6 p6)
- : T(p1, p2, p3, p4, p5, p6) {}
-
- template <typename P1,
- typename P2,
- typename P3,
- typename P4,
- typename P5,
- typename P6,
- typename P7>
- RefCountedObject(P1 p1, P2 p2, P3 p3, P4 p4, P5 p5, P6 p6, P7 p7)
- : T(p1, p2, p3, p4, p5, p6, p7) {}
-
- template <typename P1,
- typename P2,
- typename P3,
- typename P4,
- typename P5,
- typename P6,
- typename P7,
- typename P8>
- RefCountedObject(P1 p1, P2 p2, P3 p3, P4 p4, P5 p5, P6 p6, P7 p7, P8 p8)
- : T(p1, p2, p3, p4, p5, p6, p7, p8) {}
-
- template <typename P1,
- typename P2,
- typename P3,
- typename P4,
- typename P5,
- typename P6,
- typename P7,
- typename P8,
- typename P9>
- RefCountedObject(P1 p1,
- P2 p2,
- P3 p3,
- P4 p4,
- P5 p5,
- P6 p6,
- P7 p7,
- P8 p8,
- P9 p9)
- : T(p1, p2, p3, p4, p5, p6, p7, p8, p9) {}
-
- template <typename P1,
- typename P2,
- typename P3,
- typename P4,
- typename P5,
- typename P6,
- typename P7,
- typename P8,
- typename P9,
- typename P10>
- RefCountedObject(P1 p1,
- P2 p2,
- P3 p3,
- P4 p4,
- P5 p5,
- P6 p6,
- P7 p7,
- P8 p8,
- P9 p9,
- P10 p10)
- : T(p1, p2, p3, p4, p5, p6, p7, p8, p9, p10) {}
-
- template <typename P1,
- typename P2,
- typename P3,
- typename P4,
- typename P5,
- typename P6,
- typename P7,
- typename P8,
- typename P9,
- typename P10,
- typename P11>
- RefCountedObject(P1 p1,
- P2 p2,
- P3 p3,
- P4 p4,
- P5 p5,
- P6 p6,
- P7 p7,
- P8 p8,
- P9 p9,
- P10 p10,
- P11 p11)
- : T(p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11) {}
-
- virtual int AddRef() const { return AtomicOps::Increment(&ref_count_); }
-
- virtual int Release() const {
- int count = AtomicOps::Decrement(&ref_count_);
- if (!count) {
- delete this;
- }
- return count;
- }
-
- // Return whether the reference count is one. If the reference count is used
- // in the conventional way, a reference count of 1 implies that the current
- // thread owns the reference and no other thread shares it. This call
- // performs the test for a reference count of one, and performs the memory
- // barrier needed for the owning thread to act on the object, knowing that it
- // has exclusive access to the object.
- virtual bool HasOneRef() const {
- return AtomicOps::AcquireLoad(&ref_count_) == 1;
- }
-
- protected:
- virtual ~RefCountedObject() {}
-
- mutable volatile int ref_count_ = 0;
-};
-
} // namespace rtc
#endif // WEBRTC_BASE_REFCOUNT_H_
diff --git a/base/refcountedobject.h b/base/refcountedobject.h
new file mode 100644
index 0000000..ee2ec10
--- /dev/null
+++ b/base/refcountedobject.h
@@ -0,0 +1,225 @@
+// This file was GENERATED by command:
+// pump.py refcountedobject.h.pump
+// DO NOT EDIT BY HAND!!!
+
+/*
+ * Copyright 2016 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.
+ */
+
+// To generate refcount.h from refcount.h.pump, execute:
+// ./testing/gtest/scripts/pump.py ./webrtc/base/refcountedobject.h.pump
+
+#ifndef WEBRTC_BASE_REFCOUNTEDOBJECT_H_
+#define WEBRTC_BASE_REFCOUNTEDOBJECT_H_
+
+#include <utility>
+
+#include "webrtc/base/atomicops.h"
+
+namespace rtc {
+
+template <class T>
+class RefCountedObject : public T {
+ public:
+ RefCountedObject() {}
+
+ template <class P0>
+ explicit RefCountedObject(P0&& p0) : T(std::forward<P0>(p0)) {}
+ template <class P0, class P1>
+ RefCountedObject(P0&& p0, P1&& p1)
+ : T(std::forward<P0>(p0), std::forward<P1>(p1)) {}
+ template <class P0, class P1, class P2>
+ RefCountedObject(P0&& p0, P1&& p1, P2&& p2)
+ : T(std::forward<P0>(p0), std::forward<P1>(p1), std::forward<P2>(p2)) {}
+ template <class P0, class P1, class P2, class P3>
+ RefCountedObject(P0&& p0, P1&& p1, P2&& p2, P3&& p3)
+ : T(std::forward<P0>(p0),
+ std::forward<P1>(p1),
+ std::forward<P2>(p2),
+ std::forward<P3>(p3)) {}
+ template <class P0, class P1, class P2, class P3, class P4>
+ RefCountedObject(P0&& p0, P1&& p1, P2&& p2, P3&& p3, P4&& p4)
+ : T(std::forward<P0>(p0),
+ std::forward<P1>(p1),
+ std::forward<P2>(p2),
+ std::forward<P3>(p3),
+ std::forward<P4>(p4)) {}
+ template <class P0, class P1, class P2, class P3, class P4, class P5>
+ RefCountedObject(P0&& p0, P1&& p1, P2&& p2, P3&& p3, P4&& p4, P5&& p5)
+ : T(std::forward<P0>(p0),
+ std::forward<P1>(p1),
+ std::forward<P2>(p2),
+ std::forward<P3>(p3),
+ std::forward<P4>(p4),
+ std::forward<P5>(p5)) {}
+ template <class P0,
+ class P1,
+ class P2,
+ class P3,
+ class P4,
+ class P5,
+ class P6>
+ RefCountedObject(P0&& p0,
+ P1&& p1,
+ P2&& p2,
+ P3&& p3,
+ P4&& p4,
+ P5&& p5,
+ P6&& p6)
+ : T(std::forward<P0>(p0),
+ std::forward<P1>(p1),
+ std::forward<P2>(p2),
+ std::forward<P3>(p3),
+ std::forward<P4>(p4),
+ std::forward<P5>(p5),
+ std::forward<P6>(p6)) {}
+ template <class P0,
+ class P1,
+ class P2,
+ class P3,
+ class P4,
+ class P5,
+ class P6,
+ class P7>
+ RefCountedObject(P0&& p0,
+ P1&& p1,
+ P2&& p2,
+ P3&& p3,
+ P4&& p4,
+ P5&& p5,
+ P6&& p6,
+ P7&& p7)
+ : T(std::forward<P0>(p0),
+ std::forward<P1>(p1),
+ std::forward<P2>(p2),
+ std::forward<P3>(p3),
+ std::forward<P4>(p4),
+ std::forward<P5>(p5),
+ std::forward<P6>(p6),
+ std::forward<P7>(p7)) {}
+ template <class P0,
+ class P1,
+ class P2,
+ class P3,
+ class P4,
+ class P5,
+ class P6,
+ class P7,
+ class P8>
+ RefCountedObject(P0&& p0,
+ P1&& p1,
+ P2&& p2,
+ P3&& p3,
+ P4&& p4,
+ P5&& p5,
+ P6&& p6,
+ P7&& p7,
+ P8&& p8)
+ : T(std::forward<P0>(p0),
+ std::forward<P1>(p1),
+ std::forward<P2>(p2),
+ std::forward<P3>(p3),
+ std::forward<P4>(p4),
+ std::forward<P5>(p5),
+ std::forward<P6>(p6),
+ std::forward<P7>(p7),
+ std::forward<P8>(p8)) {}
+ template <class P0,
+ class P1,
+ class P2,
+ class P3,
+ class P4,
+ class P5,
+ class P6,
+ class P7,
+ class P8,
+ class P9>
+ RefCountedObject(P0&& p0,
+ P1&& p1,
+ P2&& p2,
+ P3&& p3,
+ P4&& p4,
+ P5&& p5,
+ P6&& p6,
+ P7&& p7,
+ P8&& p8,
+ P9&& p9)
+ : T(std::forward<P0>(p0),
+ std::forward<P1>(p1),
+ std::forward<P2>(p2),
+ std::forward<P3>(p3),
+ std::forward<P4>(p4),
+ std::forward<P5>(p5),
+ std::forward<P6>(p6),
+ std::forward<P7>(p7),
+ std::forward<P8>(p8),
+ std::forward<P9>(p9)) {}
+ template <class P0,
+ class P1,
+ class P2,
+ class P3,
+ class P4,
+ class P5,
+ class P6,
+ class P7,
+ class P8,
+ class P9,
+ class P10>
+ RefCountedObject(P0&& p0,
+ P1&& p1,
+ P2&& p2,
+ P3&& p3,
+ P4&& p4,
+ P5&& p5,
+ P6&& p6,
+ P7&& p7,
+ P8&& p8,
+ P9&& p9,
+ P10&& p10)
+ : T(std::forward<P0>(p0),
+ std::forward<P1>(p1),
+ std::forward<P2>(p2),
+ std::forward<P3>(p3),
+ std::forward<P4>(p4),
+ std::forward<P5>(p5),
+ std::forward<P6>(p6),
+ std::forward<P7>(p7),
+ std::forward<P8>(p8),
+ std::forward<P9>(p9),
+ std::forward<P10>(p10)) {}
+
+ virtual int AddRef() const { return AtomicOps::Increment(&ref_count_); }
+
+ virtual int Release() const {
+ int count = AtomicOps::Decrement(&ref_count_);
+ if (!count) {
+ delete this;
+ }
+ return count;
+ }
+
+ // Return whether the reference count is one. If the reference count is used
+ // in the conventional way, a reference count of 1 implies that the current
+ // thread owns the reference and no other thread shares it. This call
+ // performs the test for a reference count of one, and performs the memory
+ // barrier needed for the owning thread to act on the object, knowing that it
+ // has exclusive access to the object.
+ virtual bool HasOneRef() const {
+ return AtomicOps::AcquireLoad(&ref_count_) == 1;
+ }
+
+ protected:
+ virtual ~RefCountedObject() {}
+
+ mutable volatile int ref_count_ = 0;
+};
+
+} // namespace rtc
+
+#endif // WEBRTC_BASE_REFCOUNTEDOBJECT_H_
diff --git a/base/refcountedobject.h.pump b/base/refcountedobject.h.pump
new file mode 100644
index 0000000..cbf54e5
--- /dev/null
+++ b/base/refcountedobject.h.pump
@@ -0,0 +1,64 @@
+/*
+ * Copyright 2016 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.
+ */
+
+// To generate refcount.h from refcount.h.pump, execute:
+// ./testing/gtest/scripts/pump.py ./webrtc/base/refcountedobject.h.pump
+
+#ifndef WEBRTC_BASE_REFCOUNTEDOBJECT_H_
+#define WEBRTC_BASE_REFCOUNTEDOBJECT_H_
+
+#include <utility>
+
+#include "webrtc/base/atomicops.h"
+
+namespace rtc {
+
+template <class T>
+class RefCountedObject : public T {
+ public:
+ RefCountedObject() {}
+
+ $range i 0..10
+ $for i [[
+ $range j 0..i
+ template <$for j , [[class P$j]]>
+ $if i == 0 [[explicit ]]
+ RefCountedObject($for j , [[P$j&& p$j]]) : T($for j , [[std::forward<P$j>(p$j)]]) {}
+ ]]
+
+ virtual int AddRef() const { return AtomicOps::Increment(&ref_count_); }
+
+ virtual int Release() const {
+ int count = AtomicOps::Decrement(&ref_count_);
+ if (!count) {
+ delete this;
+ }
+ return count;
+ }
+
+ // Return whether the reference count is one. If the reference count is used
+ // in the conventional way, a reference count of 1 implies that the current
+ // thread owns the reference and no other thread shares it. This call
+ // performs the test for a reference count of one, and performs the memory
+ // barrier needed for the owning thread to act on the object, knowing that it
+ // has exclusive access to the object.
+ virtual bool HasOneRef() const {
+ return AtomicOps::AcquireLoad(&ref_count_) == 1;
+ }
+
+ protected:
+ virtual ~RefCountedObject() {}
+
+ mutable volatile int ref_count_ = 0;
+};
+
+} // namespace rtc
+
+#endif // WEBRTC_BASE_REFCOUNTEDOBJECT_H_
diff --git a/base/refcountedobject_unittest.cc b/base/refcountedobject_unittest.cc
new file mode 100644
index 0000000..3d8163f
--- /dev/null
+++ b/base/refcountedobject_unittest.cc
@@ -0,0 +1,91 @@
+/*
+ * Copyright 2016 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 <string>
+
+#include "webrtc/base/gunit.h"
+#include "webrtc/base/refcount.h"
+
+namespace rtc {
+
+namespace {
+
+class A {
+ public:
+ A() {}
+
+ private:
+ RTC_DISALLOW_COPY_AND_ASSIGN(A);
+};
+
+class RefClass : public RefCountInterface {
+ public:
+ RefClass() {}
+
+ protected:
+ virtual ~RefClass() {}
+};
+
+class RefClassWithRvalue : public RefCountInterface {
+ public:
+ explicit RefClassWithRvalue(std::unique_ptr<A> a) : a_(std::move(a)) {}
+
+ protected:
+ virtual ~RefClassWithRvalue() {}
+
+ public:
+ std::unique_ptr<A> a_;
+};
+
+class RefClassWithMixedValues : public RefCountInterface {
+ public:
+ RefClassWithMixedValues(std::unique_ptr<A> a, int b, const std::string& c)
+ : a_(std::move(a)), b_(b), c_(c) {}
+
+ protected:
+ virtual ~RefClassWithMixedValues() {}
+
+ public:
+ std::unique_ptr<A> a_;
+ int b_;
+ std::string c_;
+};
+
+} // namespace
+
+TEST(RefCountedObject, Basic) {
+ scoped_refptr<RefCountedObject<RefClass>> aref(
+ new RefCountedObject<RefClass>());
+ EXPECT_TRUE(aref->HasOneRef());
+ EXPECT_EQ(2, aref->AddRef());
+ EXPECT_EQ(1, aref->Release());
+}
+
+TEST(RefCountedObject, SupportRValuesInCtor) {
+ std::unique_ptr<A> a(new A());
+ scoped_refptr<RefClassWithRvalue> ref(
+ new RefCountedObject<RefClassWithRvalue>(std::move(a)));
+ EXPECT_TRUE(ref->a_.get() != nullptr);
+ EXPECT_TRUE(a.get() == nullptr);
+}
+
+TEST(RefCountedObject, SupportMixedTypesInCtor) {
+ std::unique_ptr<A> a(new A());
+ int b = 9;
+ std::string c = "hello";
+ scoped_refptr<RefClassWithMixedValues> ref(
+ new RefCountedObject<RefClassWithMixedValues>(std::move(a), b, c));
+ EXPECT_TRUE(ref->a_.get() != nullptr);
+ EXPECT_TRUE(a.get() == nullptr);
+ EXPECT_EQ(b, ref->b_);
+ EXPECT_EQ(c, ref->c_);
+}
+
+} // namespace rtc
diff --git a/common_video/video_frame_buffer.cc b/common_video/video_frame_buffer.cc
index dbb2743..1d20937 100644
--- a/common_video/video_frame_buffer.cc
+++ b/common_video/video_frame_buffer.cc
@@ -7,11 +7,12 @@
* in the file PATENTS. All contributing project authors may
* be found in the AUTHORS file in the root of the source tree.
*/
+#include "webrtc/common_video/include/video_frame_buffer.h"
+
+#include <string.h>
#include <algorithm>
-#include "webrtc/common_video/include/video_frame_buffer.h"
-
#include "webrtc/base/checks.h"
#include "webrtc/base/keep_ref_until_done.h"
#include "libyuv/convert.h"
diff --git a/modules/desktop_capture/screen_capturer_differ_wrapper.cc b/modules/desktop_capture/screen_capturer_differ_wrapper.cc
index b0d2282..6306d02 100644
--- a/modules/desktop_capture/screen_capturer_differ_wrapper.cc
+++ b/modules/desktop_capture/screen_capturer_differ_wrapper.cc
@@ -10,6 +10,8 @@
#include "webrtc/modules/desktop_capture/screen_capturer_differ_wrapper.h"
+#include <string.h>
+
#include <algorithm>
#include <utility>